src/video/haiku/SDL_bframebuffer.cc
author Sam Lantinga <slouken@libsdl.org>
Fri, 09 Dec 2016 01:47:43 -0800
changeset 10690 23a825f341e6
parent 9998 f67cf37e9cd4
child 10737 3406a0f8b041
permissions -rw-r--r--
Fixed bug 3513 - SDL_GL_SwapWindow does not return error status

Return an error code from SDL_GL_SwapWindow(), like the other SDL APIs.
     1 /*
     2   Simple DirectMedia Layer
     3   Copyright (C) 1997-2016 Sam Lantinga <slouken@libsdl.org>
     4 
     5   This software is provided 'as-is', without any express or implied
     6   warranty.  In no event will the authors be held liable for any damages
     7   arising from the use of this software.
     8 
     9   Permission is granted to anyone to use this software for any purpose,
    10   including commercial applications, and to alter it and redistribute it
    11   freely, subject to the following restrictions:
    12 
    13   1. The origin of this software must not be misrepresented; you must not
    14      claim that you wrote the original software. If you use this software
    15      in a product, an acknowledgment in the product documentation would be
    16      appreciated but is not required.
    17   2. Altered source versions must be plainly marked as such, and must not be
    18      misrepresented as being the original software.
    19   3. This notice may not be removed or altered from any source distribution.
    20 */
    21 #include "../../SDL_internal.h"
    22 
    23 #if SDL_VIDEO_DRIVER_HAIKU
    24 
    25 #include "SDL_bframebuffer.h"
    26 
    27 #include <AppKit.h>
    28 #include <InterfaceKit.h>
    29 #include "SDL_bmodes.h"
    30 #include "SDL_BWin.h"
    31 
    32 #include "../../main/haiku/SDL_BApp.h"
    33 
    34 #ifdef __cplusplus
    35 extern "C" {
    36 #endif
    37 
    38 int32 BE_UpdateOnce(SDL_Window *window);
    39 
    40 static SDL_INLINE SDL_BWin *_ToBeWin(SDL_Window *window) {
    41 	return ((SDL_BWin*)(window->driverdata));
    42 }
    43 
    44 static SDL_INLINE SDL_BApp *_GetBeApp() {
    45 	return ((SDL_BApp*)be_app);
    46 }
    47 
    48 int BE_CreateWindowFramebuffer(_THIS, SDL_Window * window,
    49                                        Uint32 * format,
    50                                        void ** pixels, int *pitch) {
    51 	SDL_BWin *bwin = _ToBeWin(window);
    52 	BScreen bscreen;
    53 	if(!bscreen.IsValid()) {
    54 		return -1;
    55 	}
    56 
    57 	while(!bwin->Connected()) { snooze(100); }
    58 	
    59 	/* Make sure we have exclusive access to frame buffer data */
    60 	bwin->LockBuffer();
    61 
    62 	/* format */
    63 	display_mode bmode;
    64 	bscreen.GetMode(&bmode);
    65 	int32 bpp = BE_ColorSpaceToBitsPerPixel(bmode.space);
    66 	*format = BE_BPPToSDLPxFormat(bpp);
    67 
    68 	/* Create the new bitmap object */
    69 	BBitmap *bitmap = bwin->GetBitmap();
    70 
    71 	if(bitmap) {
    72 		delete bitmap;
    73 	}
    74 	bitmap = new BBitmap(bwin->Bounds(), (color_space)bmode.space,
    75 			false,	/* Views not accepted */
    76 			true);	/* Contiguous memory required */
    77 			
    78 	if(bitmap->InitCheck() != B_OK) {
    79 		return SDL_SetError("Could not initialize back buffer!\n");
    80 	}
    81 
    82 
    83 	bwin->SetBitmap(bitmap);
    84 	
    85 	/* Set the pixel pointer */
    86 	*pixels = bitmap->Bits();
    87 
    88 	/* pitch = width of window, in bytes */
    89 	*pitch = bitmap->BytesPerRow();
    90 
    91 	bwin->SetBufferExists(true);
    92 	bwin->SetTrashBuffer(false);
    93 	bwin->UnlockBuffer();
    94 	return 0;
    95 }
    96 
    97 
    98 
    99 int BE_UpdateWindowFramebuffer(_THIS, SDL_Window * window,
   100                                       const SDL_Rect * rects, int numrects) {
   101 	if(!window)
   102 		return 0;
   103 
   104 	SDL_BWin *bwin = _ToBeWin(window);
   105 
   106 #ifdef DRAWTHREAD	
   107 	bwin->LockBuffer();
   108 	bwin->SetBufferDirty(true);
   109 	bwin->UnlockBuffer();
   110 #else
   111 	bwin->SetBufferDirty(true);
   112 	BE_UpdateOnce(window);
   113 #endif
   114 
   115 	return 0;
   116 }
   117 
   118 int32 BE_DrawThread(void *data) {
   119 	SDL_BWin *bwin = (SDL_BWin*)data;
   120 	
   121 	BScreen bscreen;
   122 	if(!bscreen.IsValid()) {
   123 		return -1;
   124 	}
   125 
   126 	while(bwin->ConnectionEnabled()) {
   127 		if( bwin->Connected() && bwin->BufferExists() && bwin->BufferIsDirty() ) {
   128 			bwin->LockBuffer();
   129 			BBitmap *bitmap = NULL;
   130 			bitmap = bwin->GetBitmap();
   131 			int32 windowPitch = bitmap->BytesPerRow();
   132 			int32 bufferPitch = bwin->GetRowBytes();
   133 			uint8 *windowpx;
   134 			uint8 *bufferpx;
   135 
   136 			int32 BPP = bwin->GetBytesPerPx();
   137 			int32 windowSub = bwin->GetFbX() * BPP +
   138 						  bwin->GetFbY() * windowPitch;
   139 			clipping_rect *clips = bwin->GetClips();
   140 			int32 numClips = bwin->GetNumClips();
   141 			int i, y;
   142 
   143 			/* Blit each clipping rectangle */
   144 			bscreen.WaitForRetrace();
   145 			for(i = 0; i < numClips; ++i) {
   146 				clipping_rect rc = clips[i];
   147 				/* Get addresses of the start of each clipping rectangle */
   148 				int32 width = clips[i].right - clips[i].left + 1;
   149 				int32 height = clips[i].bottom - clips[i].top + 1;
   150 				bufferpx = bwin->GetBufferPx() + 
   151 					clips[i].top * bufferPitch + clips[i].left * BPP;
   152 				windowpx = (uint8*)bitmap->Bits() + 
   153 					clips[i].top * windowPitch + clips[i].left * BPP -
   154 					windowSub;
   155 
   156 				/* Copy each row of pixels from the window buffer into the frame
   157 				   buffer */
   158 				for(y = 0; y < height; ++y)
   159 				{
   160 
   161 					if(bwin->CanTrashWindowBuffer()) {
   162 						goto escape;	/* Break out before the buffer is killed */
   163 					}
   164 
   165 					memcpy(bufferpx, windowpx, width * BPP);
   166 					bufferpx += bufferPitch;
   167 					windowpx += windowPitch;
   168 				}
   169 			}
   170 
   171 			bwin->SetBufferDirty(false);
   172 escape:
   173 			bwin->UnlockBuffer();
   174 		} else {
   175 			snooze(16000);
   176 		}
   177 	}
   178 	
   179 	return B_OK;
   180 }
   181 
   182 void BE_DestroyWindowFramebuffer(_THIS, SDL_Window * window) {
   183 	SDL_BWin *bwin = _ToBeWin(window);
   184 	
   185 	bwin->LockBuffer();
   186 	
   187 	/* Free and clear the window buffer */
   188 	BBitmap *bitmap = bwin->GetBitmap();
   189 	delete bitmap;
   190 	bwin->SetBitmap(NULL);
   191 	bwin->SetBufferExists(false);
   192 	bwin->UnlockBuffer();
   193 }
   194 
   195 
   196 /*
   197  * TODO:
   198  * This was written to test if certain errors were caused by threading issues.
   199  * The specific issues have since become rare enough that they may have been
   200  * solved, but I doubt it- they were pretty sporadic before now.
   201  */
   202 int32 BE_UpdateOnce(SDL_Window *window) {
   203 	SDL_BWin *bwin = _ToBeWin(window);
   204 	BScreen bscreen;
   205 	if(!bscreen.IsValid()) {
   206 		return -1;
   207 	}
   208 
   209 	if(bwin->ConnectionEnabled() && bwin->Connected()) {
   210 		bwin->LockBuffer();
   211 		int32 windowPitch = window->surface->pitch;
   212 		int32 bufferPitch = bwin->GetRowBytes();
   213 		uint8 *windowpx;
   214 		uint8 *bufferpx;
   215 
   216 		int32 BPP = bwin->GetBytesPerPx();
   217 		uint8 *windowBaseAddress = (uint8*)window->surface->pixels;
   218 		int32 windowSub = bwin->GetFbX() * BPP +
   219 						  bwin->GetFbY() * windowPitch;
   220 		clipping_rect *clips = bwin->GetClips();
   221 		int32 numClips = bwin->GetNumClips();
   222 		int i, y;
   223 
   224 		/* Blit each clipping rectangle */
   225 		bscreen.WaitForRetrace();
   226 		for(i = 0; i < numClips; ++i) {
   227 			clipping_rect rc = clips[i];
   228 			/* Get addresses of the start of each clipping rectangle */
   229 			int32 width = clips[i].right - clips[i].left + 1;
   230 			int32 height = clips[i].bottom - clips[i].top + 1;
   231 			bufferpx = bwin->GetBufferPx() + 
   232 				clips[i].top * bufferPitch + clips[i].left * BPP;
   233 			windowpx = windowBaseAddress + 
   234 				clips[i].top * windowPitch + clips[i].left * BPP - windowSub;
   235 
   236 			/* Copy each row of pixels from the window buffer into the frame
   237 			   buffer */
   238 			for(y = 0; y < height; ++y)
   239 			{
   240 				memcpy(bufferpx, windowpx, width * BPP);
   241 				bufferpx += bufferPitch;
   242 				windowpx += windowPitch;
   243 			}
   244 		}
   245 		bwin->UnlockBuffer();
   246 	}
   247 	return 0;
   248 }
   249 
   250 #ifdef __cplusplus
   251 }
   252 #endif
   253 
   254 #endif /* SDL_VIDEO_DRIVER_HAIKU */
   255 
   256 /* vi: set ts=4 sw=4 expandtab: */