Commit ee8ee9d1 authored by Nathan Heisey's avatar Nathan Heisey

Corrected memory leak with rendering.

parent 8932a116
/*
Simple DirectMedia Layer
Copyright (C) 1997-2011 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#include "SDL_config.h"
#ifndef _SDL_BView_h
#define _SDL_BView_h
/* This is the event handling and graphics update portion of SDL_BWin */
#ifdef __cplusplus
extern "C" {
#endif
#include "../../events/SDL_events_c.h"
#ifdef __cplusplus
}
#endif
class SDL_BView:public BView
{
public:
SDL_BView(BRect frame):BView(frame, "SDL View", B_FOLLOW_ALL_SIDES,
(B_WILL_DRAW | B_FRAME_EVENTS))
{
image = NULL;
xoff = yoff = 0;
SetViewColor(0, 0, 0, 0);
SetHighColor(0, 0, 0, 0);
}
virtual ~ SDL_BView()
{
SetBitmap(NULL);
}
/* Set drawing offsets for fullscreen mode */
virtual void SetXYOffset(int x, int y)
{
xoff = x;
yoff = y;
}
virtual void GetXYOffset(int &x, int &y)
{
x = xoff;
y = yoff;
}
/* The view changed size. If it means we're in fullscreen, we
* draw a nice black box in the entire view to get black borders.
*/
virtual void FrameResized(float width, float height)
{
BRect bounds;
bounds.top = bounds.left = 0;
bounds.right = width;
bounds.bottom = height;
/* Fill the entire view with black */
FillRect(bounds, B_SOLID_HIGH);
/* And if there's an image, redraw it. */
if (image) {
bounds = image->Bounds();
Draw(bounds);
}
}
/* Drawing portion of this complete breakfast. :) */
virtual void SetBitmap(BBitmap * bitmap)
{
if (image) {
delete image;
}
image = bitmap;
}
virtual void Draw(BRect updateRect)
{
if (image) {
if (xoff || yoff) {
BRect dest;
dest.top = updateRect.top + yoff;
dest.left = updateRect.left + xoff;
dest.bottom = updateRect.bottom + yoff;
dest.right = updateRect.right + xoff;
DrawBitmap(image, updateRect, dest);
} else {
DrawBitmap(image, updateRect, updateRect);
}
}
}
virtual void DrawAsync(BRect updateRect)
{
if (xoff || yoff) {
BRect dest;
dest.top = updateRect.top + yoff;
dest.left = updateRect.left + xoff;
dest.bottom = updateRect.bottom + yoff;
dest.right = updateRect.right + xoff;;
DrawBitmapAsync(image, updateRect, dest);
} else {
DrawBitmapAsync(image, updateRect, updateRect);
}
}
private:
BBitmap * image;
int xoff, yoff;
};
#endif /* _SDL_BView_h */
/* vi: set ts=4 sw=4 expandtab: */
......@@ -42,7 +42,6 @@ extern "C" {
#include <be/opengl/GLView.h>
#endif
#include "SDL_events.h"
#include "SDL_BView.h"
#include "../../main/beos/SDL_BApp.h"
enum WinCommands {
......@@ -67,11 +66,10 @@ class SDL_BWin:public BDirectWindow
{
last_buttons = 0;
printf("SDL_BWin.h: 69\n");
the_view = NULL;
#if SDL_VIDEO_OPENGL
SDL_GLView = NULL;
#endif
SDL_View = NULL;
_shown = false;
inhibit_resize = false;
mouse_focused = false;
......@@ -79,42 +77,39 @@ printf("SDL_BWin.h: 69\n");
/* Handle framebuffer stuff */
_connected = connection_disabled = false;
trash_window_buffer = false;
buffer_locker = new BLocker();
window_buffer = NULL;
// LockBuffer(); /* Unlocked by buffer initialization */
}
virtual ~ SDL_BWin()
{
Lock();
connection_disabled = false;
connection_disabled = true;
if (the_view) {
#if SDL_VIDEO_OPENGL
if (the_view == SDL_GLView) {
SDL_GLView->UnlockGL();
}
#endif
RemoveChild(the_view);
the_view = NULL;
if (SDL_GLView) {
SDL_GLView->UnlockGL();
}
RemoveChild(SDL_GLView);
#endif
Unlock();
#if SDL_VIDEO_OPENGL
if (SDL_GLView) {
delete SDL_GLView;
}
#endif
if (SDL_View) {
delete SDL_View;
}
/* Clean up framebuffer stuff */
buffer_locker->Lock();
buffer_locker->Unlock();
free(_clips);
delete buffer_locker;
}
/* Other construction */
#if SDL_VIDEO_OPENGL
virtual int CreateView(Uint32 flags, Uint32 gl_flags)
{
int retval;
......@@ -122,7 +117,6 @@ printf("SDL_BWin.h: 69\n");
retval = 0;
Lock();
if (flags & SDL_OPENGL/*SDL_INTERNALOPENGL*/) {
#if SDL_VIDEO_OPENGL
if (SDL_GLView == NULL) {
SDL_GLView = new BGLView(Bounds(), "SDL GLView",
B_FOLLOW_ALL_SIDES,
......@@ -137,31 +131,16 @@ printf("SDL_BWin.h: 69\n");
SDL_GLView->LockGL();
the_view = SDL_GLView;
}
#else
SDL_SetError("OpenGL support not enabled");
retval = -1;
#endif
} else {
if (SDL_View == NULL) {
SDL_View = new SDL_BView(Bounds());
}
if (the_view != SDL_View) {
if (the_view) {
#if SDL_VIDEO_OPENGL
if (the_view == SDL_GLView) {
SDL_GLView->UnlockGL();
}
#endif
RemoveChild(the_view);
}
AddChild(SDL_View);
the_view = SDL_View;
if (the_view) {
SDL_GLView->UnlockGL();
RemoveChild(the_view);
}
}
Unlock();
return (retval);
}
#endif
/* * * * * Framebuffering* * * * */
virtual void DirectConnected(direct_buffer_info *info) {
......@@ -172,7 +151,7 @@ printf("SDL_BWin.h: 69\n");
switch(info->buffer_state & B_DIRECT_MODE_MASK) {
case B_DIRECT_START:
printf("SDL_BWin.h: 175 Direct start.\n");
printf(__FILE__": %d; Direct start.\n", __LINE__);
_connected = true;
case B_DIRECT_MODIFY:
......@@ -182,6 +161,12 @@ printf("SDL_BWin.h: 175 Direct start.\n");
_clips = NULL;
}
/* Can we reuse the window's pixel buffer after this? */
trash_window_buffer = ((info->buffer_state & B_BUFFER_RESIZED)
|| (info->buffer_state & B_BUFFER_RESET)
|| ((info->buffer_state & B_DIRECT_MODE_MASK)
== B_DIRECT_START));
num_clips = info->clip_list_count;
_clips = (clipping_rect *)malloc(num_clips*sizeof(clipping_rect));
if(_clips) {
......@@ -191,6 +176,7 @@ printf("SDL_BWin.h: 175 Direct start.\n");
_bits = (uint8*) info->bits;
row_bytes = info->bytes_per_row;
_bounds = info->window_bounds;
bytes_per_px = info->bits_per_pixel / 8;
}
break;
......@@ -203,6 +189,8 @@ printf("SDL_BWin.h: 175 Direct start.\n");
}
/* * * * * Event sending * * * * */
/* Hook functions */
virtual void FrameMoved(BPoint origin) {
......@@ -412,54 +400,16 @@ printf("SDL_BWin.h: 175 Direct start.\n");
clipping_rect *GetClips() { return _clips; }
int32 GetNumClips() { return num_clips; }
uint8* GetBufferPx() { return _bits; }
int32 GetBytesPerPx() { return bytes_per_px; }
void SetWindowFramebuffer(uint8* fb) { window_buffer = fb; }
uint8* GetWindowFramebuffer() { return window_buffer; }
bool CanTrashWindowBuffer() { return trash_window_buffer; }
/* Setter methods */
void SetID(int32 id) { _id = id; }
/* FIXME: Methods copied directly; do we need them? */
#if 0 /* Disabled until its purpose is determined */
virtual void SetXYOffset(int x, int y)
{
#if SDL_VIDEO_OPENGL
if (the_view == SDL_GLView) {
return;
}
#endif
SDL_View->SetXYOffset(x, y);
}
virtual void GetXYOffset(int &x, int &y)
{
#if SDL_VIDEO_OPENGL
if (the_view == SDL_GLView) {
x = 0;
y = 0;
return;
}
#endif
SDL_View->GetXYOffset(x, y);
}
#endif
virtual bool BeginDraw(void)
{
return (Lock());
}
virtual void DrawAsync(BRect updateRect)
{
SDL_View->DrawAsync(updateRect);
}
virtual void EndDraw(void)
{
SDL_View->Sync();
Unlock();
}
#if SDL_VIDEO_OPENGL
virtual void SwapBuffers(void)
{
......@@ -631,7 +581,6 @@ private:
#if SDL_VIDEO_OPENGL
BGLView * SDL_GLView;
#endif
SDL_BView *SDL_View;
BView *the_view;
int32 last_buttons;
......@@ -650,6 +599,9 @@ private:
BLocker *buffer_locker;
clipping_rect *_clips;
int32 num_clips;
int32 bytes_per_px;
uint8 *window_buffer; /* A copy of the window buffer */
bool trash_window_buffer;
};
#endif
......@@ -43,8 +43,8 @@ static inline SDL_BApp *_GetBeApp() {
/* Copied from haiku/trunk/src/preferences/screen/ScreenMode.cpp */
static float get_refresh_rate(display_mode &mode) {
return rint(10 * float(mode.timing.pixel_clock * 1000)
/ float(mode.timing.h_total * mode.timing.v_total)) / 10.0;
return float(mode.timing.pixel_clock * 1000)
/ float(mode.timing.h_total * mode.timing.v_total);
}
static inline int ColorSpaceToBitsPerPixel(uint32 colorspace)
......@@ -78,7 +78,7 @@ static inline int ColorSpaceToBitsPerPixel(uint32 colorspace)
return(bitsperpixel);
}
static inline int32 BppToSDLPxFormat(int32 bpp) {
static inline int32 BPPToSDLPxFormat(int32 bpp) {
/* Translation taken from SDL_windowsmodes.c */
switch (bpp) {
case 32:
......@@ -112,7 +112,7 @@ static inline void BE_BDisplayModeToSdlDisplayMode(display_mode *bmode,
/* Set the format */
int32 bpp = ColorSpaceToBitsPerPixel(bmode->space);
mode->format = BppToSDLPxFormat(bpp);
mode->format = BPPToSDLPxFormat(bpp);
}
/* Later, there may be more than one monitor available */
......@@ -145,8 +145,6 @@ int BE_InitModes(_THIS) {
int BE_QuitModes(_THIS) {
/* Restore the previous video mode */
printf("Quit Modes\n");
BScreen screen;
display_mode *savedMode = _GetBeApp()->GetPrevMode();
screen.SetMode(savedMode);
......@@ -223,14 +221,21 @@ int BE_CreateWindowFramebuffer(_THIS, SDL_Window * window,
display_mode bmode;
bscreen.GetMode(&bmode);
int32 bpp = ColorSpaceToBitsPerPixel(bmode.space);
*format = BppToSDLPxFormat(bpp);
*format = BPPToSDLPxFormat(bpp);
/* pitch = width of screen, in bytes */
*pitch = bpp * bwin->GetFbWidth() / 8;
*pitch = bwin->GetFbWidth() * bwin->GetBytesPerPx();
/* Create a copy of the pixel buffer */
printf("SDL_bmodes.cc: 230; fbh: %i, pitch: %i; (x,y) = (%i, %i)\n", bwin->GetFbHeight(), (*pitch), bwin->GetFbX(), bwin->GetFbY());
*pixels = SDL_calloc((*pitch) * bwin->GetFbHeight() * bpp / 8, sizeof(uint8));
/* Create a copy of the pixel buffer if it doesn't recycle */
*pixels = bwin->GetWindowFramebuffer();
if( bwin->CanTrashWindowBuffer() ) {
if( (*pixels) != NULL ) {
SDL_free(*pixels);
}
*pixels = SDL_calloc((*pitch) * bwin->GetFbHeight() *
bwin->GetBytesPerPx(), sizeof(uint8));
bwin->SetWindowFramebuffer((uint8*)(*pixels));
}
bwin->UnlockBuffer();
return 0;
......@@ -253,9 +258,9 @@ int BE_UpdateWindowFramebuffer(_THIS, SDL_Window * window,
uint8 *windowpx;
uint8 *bufferpx;
int32 bpp = window->surface->format->BitsPerPixel;
int32 BPP = bwin->GetBytesPerPx();
uint8 *windowBaseAddress = (uint8*)window->surface->pixels;
int32 windowSub = bwin->GetFbX() * bpp / 8 +
int32 windowSub = bwin->GetFbX() * BPP +
bwin->GetFbY() * windowPitch;
clipping_rect *clips = bwin->GetClips();
int32 numClips = bwin->GetNumClips();
......@@ -268,16 +273,15 @@ int BE_UpdateWindowFramebuffer(_THIS, SDL_Window * window,
int32 width = clips[i].right - clips[i].left + 1;
int32 height = clips[i].bottom - clips[i].top + 1;
bufferpx = bwin->GetBufferPx() +
clips[i].top * bufferPitch + clips[i].left * bpp / 8;
clips[i].top * bufferPitch + clips[i].left * BPP;
windowpx = windowBaseAddress +
clips[i].top * windowPitch + clips[i].left * bpp / 8
- windowSub;
clips[i].top * windowPitch + clips[i].left * BPP - windowSub;
/* Copy each row of pixels from the window buffer into the frame
buffer */
for(y = 0; y < height; ++y)
{
memcpy(bufferpx, windowpx, width * bpp / 8);
memcpy(bufferpx, windowpx, width * BPP);
bufferpx += bufferPitch;
windowpx += windowPitch;
}
......@@ -288,8 +292,15 @@ int BE_UpdateWindowFramebuffer(_THIS, SDL_Window * window,
}
void BE_DestroyWindowFramebuffer(_THIS, SDL_Window * window) {
/* FIXME: FINISH! */
printf("ERROR: Attempted to destroy the window frame buffer\n");
SDL_BWin *bwin = _ToBeWin(window);
bwin->LockBuffer();
/* Free and clear the window buffer */
uint8* winBuffer = bwin->GetWindowFramebuffer();
SDL_free(winBuffer);
bwin->SetWindowFramebuffer(NULL);
bwin->UnlockBuffer();
}
#ifdef __cplusplus
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment