cscg22-gearboy

CSCG 2022 Challenge 'Gearboy'
git clone https://git.sinitax.com/sinitax/cscg22-gearboy
Log | Files | Refs | sfeed.txt

SDL_bframebuffer.cc (6633B)


      1/*
      2  Simple DirectMedia Layer
      3  Copyright (C) 1997-2014 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
     35extern "C" {
     36#endif
     37
     38int32 BE_UpdateOnce(SDL_Window *window);
     39
     40static SDL_INLINE SDL_BWin *_ToBeWin(SDL_Window *window) {
     41	return ((SDL_BWin*)(window->driverdata));
     42}
     43
     44static SDL_INLINE SDL_BApp *_GetBeApp() {
     45	return ((SDL_BApp*)be_app);
     46}
     47
     48int 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
     99int 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
    118int32 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);
    172escape:
    173			bwin->UnlockBuffer();
    174		} else {
    175			snooze(16000);
    176		}
    177	}
    178	
    179	return B_OK;
    180}
    181
    182void 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 */
    202int32 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 */