src/video/haiku/SDL_bframebuffer.cc
author Ryan C. Gordon <icculus@icculus.org>
Tue, 07 Aug 2018 18:07:11 -0400
changeset 12082 09999a0e8f9a
parent 11811 5d94cb6b24d3
child 12201 8bdc4d340419
permissions -rw-r--r--
haiku: Rename internal functions from BE_* to HAIKU_*

Fixes Bugzilla #2349.
     1 /*
     2   Simple DirectMedia Layer
     3   Copyright (C) 1997-2018 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 #ifndef DRAWTHREAD
    39 static int32 HAIKU_UpdateOnce(SDL_Window *window);
    40 #endif
    41 
    42 static SDL_INLINE SDL_BWin *_ToBeWin(SDL_Window *window) {
    43 	return ((SDL_BWin*)(window->driverdata));
    44 }
    45 
    46 static SDL_INLINE SDL_BApp *_GetBeApp() {
    47 	return ((SDL_BApp*)be_app);
    48 }
    49 
    50 int HAIKU_CreateWindowFramebuffer(_THIS, SDL_Window * window,
    51                                        Uint32 * format,
    52                                        void ** pixels, int *pitch) {
    53 	SDL_BWin *bwin = _ToBeWin(window);
    54 	BScreen bscreen;
    55 	if(!bscreen.IsValid()) {
    56 		return -1;
    57 	}
    58 
    59 	while(!bwin->Connected()) { snooze(100); }
    60 	
    61 	/* Make sure we have exclusive access to frame buffer data */
    62 	bwin->LockBuffer();
    63 
    64 	/* format */
    65 	display_mode bmode;
    66 	bscreen.GetMode(&bmode);
    67 	int32 bpp = HAIKU_ColorSpaceToBitsPerPixel(bmode.space);
    68 	*format = HAIKU_BPPToSDLPxFormat(bpp);
    69 
    70 	/* Create the new bitmap object */
    71 	BBitmap *bitmap = bwin->GetBitmap();
    72 
    73 	if(bitmap) {
    74 		delete bitmap;
    75 	}
    76 	bitmap = new BBitmap(bwin->Bounds(), (color_space)bmode.space,
    77 			false,	/* Views not accepted */
    78 			true);	/* Contiguous memory required */
    79 			
    80 	if(bitmap->InitCheck() != B_OK) {
    81 		delete bitmap;
    82 		return SDL_SetError("Could not initialize back buffer!");
    83 	}
    84 
    85 
    86 	bwin->SetBitmap(bitmap);
    87 	
    88 	/* Set the pixel pointer */
    89 	*pixels = bitmap->Bits();
    90 
    91 	/* pitch = width of window, in bytes */
    92 	*pitch = bitmap->BytesPerRow();
    93 
    94 	bwin->SetBufferExists(true);
    95 	bwin->SetTrashBuffer(false);
    96 	bwin->UnlockBuffer();
    97 	return 0;
    98 }
    99 
   100 
   101 
   102 int HAIKU_UpdateWindowFramebuffer(_THIS, SDL_Window * window,
   103                                       const SDL_Rect * rects, int numrects) {
   104 	if(!window)
   105 		return 0;
   106 
   107 	SDL_BWin *bwin = _ToBeWin(window);
   108 
   109 #ifdef DRAWTHREAD	
   110 	bwin->LockBuffer();
   111 	bwin->SetBufferDirty(true);
   112 	bwin->UnlockBuffer();
   113 #else
   114 	bwin->SetBufferDirty(true);
   115 	HAIKU_UpdateOnce(window);
   116 #endif
   117 
   118 	return 0;
   119 }
   120 
   121 int32 HAIKU_DrawThread(void *data) {
   122 	SDL_BWin *bwin = (SDL_BWin*)data;
   123 	
   124 	BScreen bscreen;
   125 	if(!bscreen.IsValid()) {
   126 		return -1;
   127 	}
   128 
   129 	while(bwin->ConnectionEnabled()) {
   130 		if( bwin->Connected() && bwin->BufferExists() && bwin->BufferIsDirty() ) {
   131 			bwin->LockBuffer();
   132 			BBitmap *bitmap = NULL;
   133 			bitmap = bwin->GetBitmap();
   134 			int32 windowPitch = bitmap->BytesPerRow();
   135 			int32 bufferPitch = bwin->GetRowBytes();
   136 			uint8 *windowpx;
   137 			uint8 *bufferpx;
   138 
   139 			int32 BPP = bwin->GetBytesPerPx();
   140 			int32 windowSub = bwin->GetFbX() * BPP +
   141 						  bwin->GetFbY() * windowPitch;
   142 			clipping_rect *clips = bwin->GetClips();
   143 			int32 numClips = bwin->GetNumClips();
   144 			int i, y;
   145 
   146 			/* Blit each clipping rectangle */
   147 			bscreen.WaitForRetrace();
   148 			for(i = 0; i < numClips; ++i) {
   149 				/* Get addresses of the start of each clipping rectangle */
   150 				int32 width = clips[i].right - clips[i].left + 1;
   151 				int32 height = clips[i].bottom - clips[i].top + 1;
   152 				bufferpx = bwin->GetBufferPx() + 
   153 					clips[i].top * bufferPitch + clips[i].left * BPP;
   154 				windowpx = (uint8*)bitmap->Bits() + 
   155 					clips[i].top * windowPitch + clips[i].left * BPP -
   156 					windowSub;
   157 
   158 				/* Copy each row of pixels from the window buffer into the frame
   159 				   buffer */
   160 				for(y = 0; y < height; ++y)
   161 				{
   162 
   163 					if(bwin->CanTrashWindowBuffer()) {
   164 						goto escape;	/* Break out before the buffer is killed */
   165 					}
   166 
   167 					memcpy(bufferpx, windowpx, width * BPP);
   168 					bufferpx += bufferPitch;
   169 					windowpx += windowPitch;
   170 				}
   171 			}
   172 
   173 			bwin->SetBufferDirty(false);
   174 escape:
   175 			bwin->UnlockBuffer();
   176 		} else {
   177 			snooze(16000);
   178 		}
   179 	}
   180 	
   181 	return B_OK;
   182 }
   183 
   184 void HAIKU_DestroyWindowFramebuffer(_THIS, SDL_Window * window) {
   185 	SDL_BWin *bwin = _ToBeWin(window);
   186 	
   187 	bwin->LockBuffer();
   188 	
   189 	/* Free and clear the window buffer */
   190 	BBitmap *bitmap = bwin->GetBitmap();
   191 	delete bitmap;
   192 	bwin->SetBitmap(NULL);
   193 	bwin->SetBufferExists(false);
   194 	bwin->UnlockBuffer();
   195 }
   196 
   197 
   198 /*
   199  * TODO:
   200  * This was written to test if certain errors were caused by threading issues.
   201  * The specific issues have since become rare enough that they may have been
   202  * solved, but I doubt it- they were pretty sporadic before now.
   203  */
   204 #ifndef DRAWTHREAD
   205 static int32 HAIKU_UpdateOnce(SDL_Window *window) {
   206 	SDL_BWin *bwin = _ToBeWin(window);
   207 	BScreen bscreen;
   208 	if(!bscreen.IsValid()) {
   209 		return -1;
   210 	}
   211 
   212 	if(bwin->ConnectionEnabled() && bwin->Connected()) {
   213 		bwin->LockBuffer();
   214 		int32 windowPitch = window->surface->pitch;
   215 		int32 bufferPitch = bwin->GetRowBytes();
   216 		uint8 *windowpx;
   217 		uint8 *bufferpx;
   218 
   219 		int32 BPP = bwin->GetBytesPerPx();
   220 		uint8 *windowBaseAddress = (uint8*)window->surface->pixels;
   221 		int32 windowSub = bwin->GetFbX() * BPP +
   222 						  bwin->GetFbY() * windowPitch;
   223 		clipping_rect *clips = bwin->GetClips();
   224 		int32 numClips = bwin->GetNumClips();
   225 		int i, y;
   226 
   227 		/* Blit each clipping rectangle */
   228 		bscreen.WaitForRetrace();
   229 		for(i = 0; i < numClips; ++i) {
   230 			/* Get addresses of the start of each clipping rectangle */
   231 			int32 width = clips[i].right - clips[i].left + 1;
   232 			int32 height = clips[i].bottom - clips[i].top + 1;
   233 			bufferpx = bwin->GetBufferPx() + 
   234 				clips[i].top * bufferPitch + clips[i].left * BPP;
   235 			windowpx = windowBaseAddress + 
   236 				clips[i].top * windowPitch + clips[i].left * BPP - windowSub;
   237 
   238 			/* Copy each row of pixels from the window buffer into the frame
   239 			   buffer */
   240 			for(y = 0; y < height; ++y)
   241 			{
   242 				memcpy(bufferpx, windowpx, width * BPP);
   243 				bufferpx += bufferPitch;
   244 				windowpx += windowPitch;
   245 			}
   246 		}
   247 		bwin->UnlockBuffer();
   248 	}
   249 	return 0;
   250 }
   251 #endif
   252 
   253 #ifdef __cplusplus
   254 }
   255 #endif
   256 
   257 #endif /* SDL_VIDEO_DRIVER_HAIKU */
   258 
   259 /* vi: set ts=4 sw=4 expandtab: */