src/video/haiku/SDL_bframebuffer.cc
author Sam Lantinga <slouken@libsdl.org>
Thu, 23 May 2019 14:19:00 -0700
changeset 12756 4116bf232fe7
parent 12503 806492103856
permissions -rw-r--r--
Added a function to get the current Android SDK version at runtime
     1 /*
     2   Simple DirectMedia Layer
     3   Copyright (C) 1997-2019 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: */