sdl

FORK: Simple Directmedia Layer
git clone https://git.neptards.moe/neptards/sdl.git
Log | Files | Refs

SDL_bframebuffer.cc (7720B)


      1 /*
      2   Simple DirectMedia Layer
      3   Copyright (C) 1997-2020 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: */