cscg22-gearboy

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

SDL_DirectFB_render.c (44234B)


      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_DIRECTFB
     24#include "SDL_DirectFB_window.h"
     25#include "SDL_DirectFB_modes.h"
     26
     27#include "SDL_syswm.h"
     28#include "SDL_DirectFB_shape.h"
     29
     30#include "../SDL_sysvideo.h"
     31#include "../../render/SDL_sysrender.h"
     32
     33#ifndef DFB_VERSION_ATLEAST
     34
     35#define DFB_VERSIONNUM(X, Y, Z)                     \
     36    ((X)*1000 + (Y)*100 + (Z))
     37
     38#define DFB_COMPILEDVERSION \
     39    DFB_VERSIONNUM(DIRECTFB_MAJOR_VERSION, DIRECTFB_MINOR_VERSION, DIRECTFB_MICRO_VERSION)
     40
     41#define DFB_VERSION_ATLEAST(X, Y, Z) \
     42    (DFB_COMPILEDVERSION >= DFB_VERSIONNUM(X, Y, Z))
     43
     44#define SDL_DFB_CHECK(x)    x
     45
     46#endif
     47
     48/* the following is not yet tested ... */
     49#define USE_DISPLAY_PALETTE         (0)
     50
     51
     52#define SDL_DFB_RENDERERDATA(rend) DirectFB_RenderData *renddata = ((rend) ? (DirectFB_RenderData *) (rend)->driverdata : NULL)
     53
     54
     55/* DirectFB renderer implementation */
     56
     57static SDL_Renderer *DirectFB_CreateRenderer(SDL_Window * window,
     58                                             Uint32 flags);
     59static void DirectFB_ActivateRenderer(SDL_Renderer * renderer);
     60static int DirectFB_CreateTexture(SDL_Renderer * renderer,
     61                                  SDL_Texture * texture);
     62static int DirectFB_QueryTexturePixels(SDL_Renderer * renderer,
     63                                       SDL_Texture * texture,
     64                                       void **pixels, int *pitch);
     65static int DirectFB_SetTexturePalette(SDL_Renderer * renderer,
     66                                      SDL_Texture * texture,
     67                                      const SDL_Color * colors,
     68                                      int firstcolor, int ncolors);
     69static int DirectFB_GetTexturePalette(SDL_Renderer * renderer,
     70                                      SDL_Texture * texture,
     71                                      SDL_Color * colors,
     72                                      int firstcolor, int ncolors);
     73static int DirectFB_SetTextureAlphaMod(SDL_Renderer * renderer,
     74                                       SDL_Texture * texture);
     75static int DirectFB_SetTextureColorMod(SDL_Renderer * renderer,
     76                                       SDL_Texture * texture);
     77static int DirectFB_SetTextureBlendMode(SDL_Renderer * renderer,
     78                                        SDL_Texture * texture);
     79static int DirectFB_SetTextureScaleMode(SDL_Renderer * renderer,
     80                                        SDL_Texture * texture);
     81static int DirectFB_UpdateTexture(SDL_Renderer * renderer,
     82                                  SDL_Texture * texture,
     83                                  const SDL_Rect * rect,
     84                                  const void *pixels, int pitch);
     85static int DirectFB_LockTexture(SDL_Renderer * renderer,
     86                                SDL_Texture * texture,
     87                                const SDL_Rect * rect,
     88                                void **pixels, int *pitch);
     89static void DirectFB_UnlockTexture(SDL_Renderer * renderer,
     90                                   SDL_Texture * texture);
     91static void DirectFB_DirtyTexture(SDL_Renderer * renderer,
     92                                  SDL_Texture * texture, int numrects,
     93                                  const SDL_Rect * rects);
     94static int DirectFB_SetDrawBlendMode(SDL_Renderer * renderer);
     95static int DirectFB_RenderDrawPoints(SDL_Renderer * renderer,
     96                                const SDL_FPoint * points, int count);
     97static int DirectFB_RenderDrawLines(SDL_Renderer * renderer,
     98                               const SDL_FPoint * points, int count);
     99static int DirectFB_RenderDrawRects(SDL_Renderer * renderer,
    100        const SDL_Rect ** rects, int count);
    101static int DirectFB_RenderFillRects(SDL_Renderer * renderer,
    102        const SDL_FRect * rects, int count);
    103static int DirectFB_RenderCopy(SDL_Renderer * renderer,
    104                               SDL_Texture * texture,
    105                               const SDL_Rect * srcrect,
    106                               const SDL_FRect * dstrect);
    107static void DirectFB_RenderPresent(SDL_Renderer * renderer);
    108static void DirectFB_DestroyTexture(SDL_Renderer * renderer,
    109                                    SDL_Texture * texture);
    110static void DirectFB_DestroyRenderer(SDL_Renderer * renderer);
    111static int DirectFB_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect,
    112                     Uint32 format, void * pixels, int pitch);
    113static int DirectFB_RenderWritePixels(SDL_Renderer * renderer, const SDL_Rect * rect,
    114                      Uint32 format, const void * pixels, int pitch);
    115static int DirectFB_UpdateViewport(SDL_Renderer * renderer);
    116static int DirectFB_UpdateClipRect(SDL_Renderer * renderer);
    117static int DirectFB_SetRenderTarget(SDL_Renderer * renderer, SDL_Texture * texture);
    118
    119static int PrepareDraw(SDL_Renderer * renderer);
    120
    121
    122#define SDL_DFB_WINDOWSURFACE(win)  IDirectFBSurface *destsurf = ((DFB_WindowData *) ((win)->driverdata))->surface;
    123
    124SDL_RenderDriver DirectFB_RenderDriver = {
    125    DirectFB_CreateRenderer,
    126    {
    127     "directfb",
    128     (SDL_RENDERER_PRESENTVSYNC | SDL_RENDERER_ACCELERATED),
    129     /* (SDL_TEXTUREMODULATE_NONE | SDL_TEXTUREMODULATE_COLOR |
    130      SDL_TEXTUREMODULATE_ALPHA),
    131      (SDL_BLENDMODE_NONE | SDL_BLENDMODE_MASK | SDL_BLENDMODE_BLEND |
    132      SDL_BLENDMODE_ADD | SDL_BLENDMODE_MOD),
    133     (SDL_SCALEMODE_NONE | SDL_SCALEMODE_FAST |
    134      SDL_SCALEMODE_SLOW | SDL_SCALEMODE_BEST), */
    135     0,
    136     {
    137             /* formats filled in later */
    138     },
    139     0,
    140     0}
    141};
    142
    143typedef struct
    144{
    145    SDL_Window *window;
    146    DFBSurfaceFlipFlags flipflags;
    147    int size_changed;
    148    int lastBlendMode;
    149    DFBSurfaceBlittingFlags blitFlags;
    150    DFBSurfaceDrawingFlags drawFlags;
    151    IDirectFBSurface* target;
    152} DirectFB_RenderData;
    153
    154typedef struct
    155{
    156    IDirectFBSurface *surface;
    157    Uint32 format;
    158    void *pixels;
    159    int pitch;
    160    IDirectFBPalette *palette;
    161    int isDirty;
    162
    163    SDL_VideoDisplay *display;      /* only for yuv textures */
    164
    165#if (DFB_VERSION_ATLEAST(1,2,0))
    166    DFBSurfaceRenderOptions render_options;
    167#endif
    168} DirectFB_TextureData;
    169
    170static SDL_INLINE void
    171SDLtoDFBRect(const SDL_Rect * sr, DFBRectangle * dr)
    172{
    173    dr->x = sr->x;
    174    dr->y = sr->y;
    175    dr->h = sr->h;
    176    dr->w = sr->w;
    177}
    178static SDL_INLINE void
    179SDLtoDFBRect_Float(const SDL_FRect * sr, DFBRectangle * dr)
    180{
    181    dr->x = sr->x;
    182    dr->y = sr->y;
    183    dr->h = sr->h;
    184    dr->w = sr->w;
    185}
    186
    187
    188static int
    189TextureHasAlpha(DirectFB_TextureData * data)
    190{
    191    /* Drawing primitive ? */
    192    if (!data)
    193        return 0;
    194
    195    return (DFB_PIXELFORMAT_HAS_ALPHA(DirectFB_SDLToDFBPixelFormat(data->format)) ? 1 : 0);
    196#if 0
    197    switch (data->format) {
    198    case SDL_PIXELFORMAT_INDEX4LSB:
    199    case SDL_PIXELFORMAT_INDEX4MSB:
    200    case SDL_PIXELFORMAT_ARGB4444:
    201    case SDL_PIXELFORMAT_ARGB1555:
    202    case SDL_PIXELFORMAT_ARGB8888:
    203    case SDL_PIXELFORMAT_RGBA8888:
    204    case SDL_PIXELFORMAT_ABGR8888:
    205    case SDL_PIXELFORMAT_BGRA8888:
    206    case SDL_PIXELFORMAT_ARGB2101010:
    207       return 1;
    208    default:
    209        return 0;
    210    }
    211#endif
    212}
    213
    214static SDL_INLINE IDirectFBSurface *get_dfb_surface(SDL_Window *window)
    215{
    216    SDL_SysWMinfo wm_info;
    217    SDL_memset(&wm_info, 0, sizeof(SDL_SysWMinfo));
    218
    219    SDL_VERSION(&wm_info.version);
    220    SDL_GetWindowWMInfo(window, &wm_info);
    221
    222    return wm_info.info.dfb.surface;
    223}
    224
    225static SDL_INLINE IDirectFBWindow *get_dfb_window(SDL_Window *window)
    226{
    227    SDL_SysWMinfo wm_info;
    228    SDL_memset(&wm_info, 0, sizeof(SDL_SysWMinfo));
    229
    230    SDL_VERSION(&wm_info.version);
    231    SDL_GetWindowWMInfo(window, &wm_info);
    232
    233    return wm_info.info.dfb.window;
    234}
    235
    236static void
    237SetBlendMode(DirectFB_RenderData * data, int blendMode,
    238             DirectFB_TextureData * source)
    239{
    240    IDirectFBSurface *destsurf = data->target;
    241
    242    /* FIXME: check for format change */
    243    if (1 || data->lastBlendMode != blendMode) {
    244        switch (blendMode) {
    245        case SDL_BLENDMODE_NONE:
    246                                           /**< No blending */
    247            data->blitFlags = DSBLIT_NOFX;
    248            data->drawFlags = DSDRAW_NOFX;
    249            SDL_DFB_CHECK(destsurf->SetSrcBlendFunction(destsurf, DSBF_ONE));
    250            SDL_DFB_CHECK(destsurf->SetDstBlendFunction(destsurf, DSBF_ZERO));
    251            break;
    252#if 0
    253        case SDL_BLENDMODE_MASK:
    254            data->blitFlags =  DSBLIT_BLEND_ALPHACHANNEL;
    255            data->drawFlags = DSDRAW_BLEND;
    256            SDL_DFB_CHECK(destsurf->SetSrcBlendFunction(destsurf, DSBF_SRCALPHA));
    257            SDL_DFB_CHECK(destsurf->SetDstBlendFunction(destsurf, DSBF_INVSRCALPHA));
    258            break;
    259#endif
    260        case SDL_BLENDMODE_BLEND:
    261            data->blitFlags = DSBLIT_BLEND_ALPHACHANNEL;
    262            data->drawFlags = DSDRAW_BLEND;
    263            SDL_DFB_CHECK(destsurf->SetSrcBlendFunction(destsurf, DSBF_SRCALPHA));
    264            SDL_DFB_CHECK(destsurf->SetDstBlendFunction(destsurf, DSBF_INVSRCALPHA));
    265            break;
    266        case SDL_BLENDMODE_ADD:
    267            data->blitFlags = DSBLIT_BLEND_ALPHACHANNEL;
    268            data->drawFlags = DSDRAW_BLEND;
    269            /* FIXME: SRCALPHA kills performance on radeon ...
    270             * It will be cheaper to copy the surface to a temporary surface and premultiply
    271             */
    272            if (source && TextureHasAlpha(source))
    273                SDL_DFB_CHECK(destsurf->SetSrcBlendFunction(destsurf, DSBF_SRCALPHA));
    274            else
    275                SDL_DFB_CHECK(destsurf->SetSrcBlendFunction(destsurf, DSBF_ONE));
    276            SDL_DFB_CHECK(destsurf->SetDstBlendFunction(destsurf, DSBF_ONE));
    277            break;
    278        case SDL_BLENDMODE_MOD:
    279            data->blitFlags = DSBLIT_BLEND_ALPHACHANNEL;
    280            data->drawFlags = DSDRAW_BLEND;
    281            SDL_DFB_CHECK(destsurf->SetSrcBlendFunction(destsurf, DSBF_ZERO));
    282            SDL_DFB_CHECK(destsurf->SetDstBlendFunction(destsurf, DSBF_SRCCOLOR));
    283
    284            break;
    285        }
    286        data->lastBlendMode = blendMode;
    287    }
    288}
    289
    290static int
    291DisplayPaletteChanged(void *userdata, SDL_Palette * palette)
    292{
    293#if USE_DISPLAY_PALETTE
    294    DirectFB_RenderData *data = (DirectFB_RenderData *) userdata;
    295    SDL_DFB_WINDOWSURFACE(data->window);
    296    IDirectFBPalette *surfpal;
    297
    298    int i;
    299    int ncolors;
    300    DFBColor entries[256];
    301
    302    SDL_DFB_CHECKERR(destsurf->GetPalette(destsurf, &surfpal));
    303
    304    /* FIXME: number of colors */
    305    ncolors = (palette->ncolors < 256 ? palette->ncolors : 256);
    306
    307    for (i = 0; i < ncolors; ++i) {
    308        entries[i].r = palette->colors[i].r;
    309        entries[i].g = palette->colors[i].g;
    310        entries[i].b = palette->colors[i].b;
    311        entries[i].a = palette->colors[i].a;
    312    }
    313    SDL_DFB_CHECKERR(surfpal->SetEntries(surfpal, entries, ncolors, 0));
    314    return 0;
    315  error:
    316#else
    317    SDL_Unsupported();
    318#endif
    319    return -1;
    320}
    321
    322static void
    323DirectFB_WindowEvent(SDL_Renderer * renderer, const SDL_WindowEvent *event)
    324{
    325    SDL_DFB_RENDERERDATA(renderer);
    326
    327    if (event->event == SDL_WINDOWEVENT_SIZE_CHANGED) {
    328        /* Rebind the context to the window area and update matrices */
    329        /* SDL_CurrentContext = NULL; */
    330        /* data->updateSize = SDL_TRUE; */
    331        renddata->size_changed = SDL_TRUE;
    332   }
    333}
    334
    335int
    336DirectFB_RenderClear(SDL_Renderer * renderer)
    337{
    338    DirectFB_RenderData *data = (DirectFB_RenderData *) renderer->driverdata;
    339    IDirectFBSurface *destsurf = data->target;
    340
    341    DirectFB_ActivateRenderer(renderer);
    342
    343    PrepareDraw(renderer);
    344
    345    destsurf->Clear(destsurf, renderer->r, renderer->g, renderer->b, renderer->a);
    346
    347
    348    return 0;
    349}
    350
    351SDL_Renderer *
    352DirectFB_CreateRenderer(SDL_Window * window, Uint32 flags)
    353{
    354    IDirectFBSurface *winsurf = get_dfb_surface(window);
    355    SDL_VideoDisplay *display = SDL_GetDisplayForWindow(window);
    356    SDL_Renderer *renderer = NULL;
    357    DirectFB_RenderData *data = NULL;
    358    DFBSurfaceCapabilities scaps;
    359
    360    SDL_DFB_ALLOC_CLEAR(renderer, sizeof(*renderer));
    361    SDL_DFB_ALLOC_CLEAR(data, sizeof(*data));
    362
    363    renderer->WindowEvent = DirectFB_WindowEvent;
    364    renderer->CreateTexture = DirectFB_CreateTexture;
    365    renderer->SetTextureAlphaMod = DirectFB_SetTextureAlphaMod;
    366    renderer->SetTextureColorMod = DirectFB_SetTextureColorMod;
    367    renderer->SetTextureBlendMode = DirectFB_SetTextureBlendMode;
    368    renderer->UpdateTexture = DirectFB_UpdateTexture;
    369    renderer->LockTexture = DirectFB_LockTexture;
    370    renderer->RenderClear = DirectFB_RenderClear;
    371    renderer->UnlockTexture = DirectFB_UnlockTexture;
    372    renderer->RenderDrawPoints = DirectFB_RenderDrawPoints;
    373    renderer->RenderDrawLines = DirectFB_RenderDrawLines;
    374    /* SetDrawColor - no needed */
    375    renderer->RenderFillRects = DirectFB_RenderFillRects;
    376
    377    renderer->RenderCopy = DirectFB_RenderCopy;
    378    renderer->RenderPresent = DirectFB_RenderPresent;
    379
    380    /* FIXME: Yet to be tested */
    381    renderer->RenderReadPixels = DirectFB_RenderReadPixels;
    382    /* renderer->RenderWritePixels = DirectFB_RenderWritePixels; */
    383
    384    renderer->DestroyTexture = DirectFB_DestroyTexture;
    385    renderer->DestroyRenderer = DirectFB_DestroyRenderer;
    386    renderer->UpdateViewport = DirectFB_UpdateViewport;
    387    renderer->UpdateClipRect = DirectFB_UpdateClipRect;
    388    renderer->SetRenderTarget = DirectFB_SetRenderTarget;
    389
    390#if 0
    391    renderer->QueryTexturePixels = DirectFB_QueryTexturePixels;
    392    renderer->SetTexturePalette = DirectFB_SetTexturePalette;
    393    renderer->GetTexturePalette = DirectFB_GetTexturePalette;
    394    renderer->SetTextureScaleMode = DirectFB_SetTextureScaleMode;
    395    renderer->DirtyTexture = DirectFB_DirtyTexture;
    396    renderer->SetDrawBlendMode = DirectFB_SetDrawBlendMode;
    397    renderer->RenderDrawRects = DirectFB_RenderDrawRects;
    398#endif
    399
    400    renderer->info = DirectFB_RenderDriver.info;
    401    renderer->window = window;      /* SDL window */
    402    renderer->driverdata = data;
    403
    404    renderer->info.flags =
    405        SDL_RENDERER_ACCELERATED | SDL_RENDERER_TARGETTEXTURE;
    406
    407    data->window = window;
    408    data->target = winsurf;
    409
    410    data->flipflags = DSFLIP_PIPELINE | DSFLIP_BLIT;
    411
    412    if (flags & SDL_RENDERER_PRESENTVSYNC) {
    413        data->flipflags |= DSFLIP_WAITFORSYNC | DSFLIP_ONSYNC;
    414        renderer->info.flags |= SDL_RENDERER_PRESENTVSYNC;
    415    } else
    416        data->flipflags |= DSFLIP_ONSYNC;
    417
    418    SDL_DFB_CHECKERR(winsurf->GetCapabilities(winsurf, &scaps));
    419
    420#if 0
    421    if (scaps & DSCAPS_DOUBLE)
    422        renderer->info.flags |= SDL_RENDERER_PRESENTFLIP2;
    423    else if (scaps & DSCAPS_TRIPLE)
    424        renderer->info.flags |= SDL_RENDERER_PRESENTFLIP3;
    425    else
    426        renderer->info.flags |= SDL_RENDERER_SINGLEBUFFER;
    427#endif
    428
    429    DirectFB_SetSupportedPixelFormats(&renderer->info);
    430
    431#if 0
    432    /* Set up a palette watch on the display palette */
    433    if (display-> palette) {
    434        SDL_AddPaletteWatch(display->palette, DisplayPaletteChanged, data);
    435    }
    436#endif
    437
    438    return renderer;
    439
    440  error:
    441    SDL_DFB_FREE(renderer);
    442    SDL_DFB_FREE(data);
    443    return NULL;
    444}
    445
    446static void
    447DirectFB_ActivateRenderer(SDL_Renderer * renderer)
    448{
    449    SDL_DFB_RENDERERDATA(renderer);
    450    SDL_Window *window = renderer->window;
    451    SDL_DFB_WINDOWDATA(window);
    452
    453    if (renddata->size_changed /* || windata->wm_needs_redraw */) {
    454        renddata->size_changed = SDL_FALSE;
    455    }
    456}
    457
    458
    459static int
    460DirectFB_AcquireVidLayer(SDL_Renderer * renderer, SDL_Texture * texture)
    461{
    462    SDL_Window *window = renderer->window;
    463    SDL_VideoDisplay *display = SDL_GetDisplayForWindow(window);
    464    SDL_DFB_DEVICEDATA(display->device);
    465    DFB_DisplayData *dispdata = (DFB_DisplayData *) display->driverdata;
    466    DirectFB_TextureData *data = texture->driverdata;
    467    DFBDisplayLayerConfig layconf;
    468    DFBResult ret;
    469
    470    if (devdata->use_yuv_direct && (dispdata->vidID >= 0)
    471        && (!dispdata->vidIDinuse)
    472        && SDL_ISPIXELFORMAT_FOURCC(data->format)) {
    473        layconf.flags =
    474            DLCONF_WIDTH | DLCONF_HEIGHT | DLCONF_PIXELFORMAT |
    475            DLCONF_SURFACE_CAPS;
    476        layconf.width = texture->w;
    477        layconf.height = texture->h;
    478        layconf.pixelformat = DirectFB_SDLToDFBPixelFormat(data->format);
    479        layconf.surface_caps = DSCAPS_VIDEOONLY | DSCAPS_DOUBLE;
    480
    481        SDL_DFB_CHECKERR(devdata->dfb->GetDisplayLayer(devdata->dfb,
    482                                                       dispdata->vidID,
    483                                                       &dispdata->vidlayer));
    484        SDL_DFB_CHECKERR(dispdata->
    485                         vidlayer->SetCooperativeLevel(dispdata->vidlayer,
    486                                                       DLSCL_EXCLUSIVE));
    487
    488        if (devdata->use_yuv_underlays) {
    489            ret = dispdata->vidlayer->SetLevel(dispdata->vidlayer, -1);
    490            if (ret != DFB_OK)
    491                SDL_DFB_DEBUG("Underlay Setlevel not supported\n");
    492        }
    493        SDL_DFB_CHECKERR(dispdata->
    494                         vidlayer->SetConfiguration(dispdata->vidlayer,
    495                                                    &layconf));
    496        SDL_DFB_CHECKERR(dispdata->
    497                         vidlayer->GetSurface(dispdata->vidlayer,
    498                                              &data->surface));
    499        dispdata->vidIDinuse = 1;
    500        data->display = display;
    501        return 0;
    502    }
    503    return 1;
    504  error:
    505    if (dispdata->vidlayer) {
    506        SDL_DFB_RELEASE(data->surface);
    507        SDL_DFB_CHECKERR(dispdata->
    508                         vidlayer->SetCooperativeLevel(dispdata->vidlayer,
    509                                                       DLSCL_ADMINISTRATIVE));
    510        SDL_DFB_RELEASE(dispdata->vidlayer);
    511    }
    512    return 1;
    513}
    514
    515static int
    516DirectFB_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture)
    517{
    518    SDL_Window *window = renderer->window;
    519    SDL_VideoDisplay *display = SDL_GetDisplayForWindow(window);
    520    SDL_DFB_DEVICEDATA(display->device);
    521    DirectFB_TextureData *data;
    522    DFBSurfaceDescription dsc;
    523    DFBSurfacePixelFormat pixelformat;
    524
    525    DirectFB_ActivateRenderer(renderer);
    526
    527    SDL_DFB_ALLOC_CLEAR(data, sizeof(*data));
    528    texture->driverdata = data;
    529
    530    /* find the right pixelformat */
    531    pixelformat = DirectFB_SDLToDFBPixelFormat(texture->format);
    532    if (pixelformat == DSPF_UNKNOWN) {
    533        SDL_SetError("Unknown pixel format %d\n", data->format);
    534        goto error;
    535    }
    536
    537    data->format = texture->format;
    538    data->pitch = texture->w * DFB_BYTES_PER_PIXEL(pixelformat);
    539
    540    if (DirectFB_AcquireVidLayer(renderer, texture) != 0) {
    541        /* fill surface description */
    542        dsc.flags =
    543            DSDESC_WIDTH | DSDESC_HEIGHT | DSDESC_PIXELFORMAT | DSDESC_CAPS;
    544        dsc.width = texture->w;
    545        dsc.height = texture->h;
    546        if(texture->format == SDL_PIXELFORMAT_YV12 ||
    547           texture->format == SDL_PIXELFORMAT_IYUV) {
    548           /* dfb has problems with odd sizes -make them even internally */
    549           dsc.width += (dsc.width % 2);
    550           dsc.height += (dsc.height % 2);
    551        }
    552        /* <1.2 Never use DSCAPS_VIDEOONLY here. It kills performance
    553         * No DSCAPS_SYSTEMONLY either - let dfb decide
    554         * 1.2: DSCAPS_SYSTEMONLY boosts performance by factor ~8
    555         * Depends on other settings as well. Let dfb decide.
    556         */
    557        dsc.caps = DSCAPS_PREMULTIPLIED;
    558#if 0
    559        if (texture->access == SDL_TEXTUREACCESS_STREAMING)
    560            dsc.caps |= DSCAPS_SYSTEMONLY;
    561        else
    562            dsc.caps |= DSCAPS_VIDEOONLY;
    563#endif
    564
    565        dsc.pixelformat = pixelformat;
    566        data->pixels = NULL;
    567
    568        /* Create the surface */
    569        SDL_DFB_CHECKERR(devdata->dfb->CreateSurface(devdata->dfb, &dsc,
    570                                                     &data->surface));
    571        if (SDL_ISPIXELFORMAT_INDEXED(data->format)
    572            && !SDL_ISPIXELFORMAT_FOURCC(data->format)) {
    573#if 1
    574            SDL_DFB_CHECKERR(data->surface->GetPalette(data->surface, &data->palette));
    575#else
    576            /* DFB has issues with blitting LUT8 surfaces.
    577             * Creating a new palette does not help.
    578             */
    579            DFBPaletteDescription pal_desc;
    580            pal_desc.flags = DPDESC_SIZE; /* | DPDESC_ENTRIES */
    581            pal_desc.size = 256;
    582            SDL_DFB_CHECKERR(devdata->dfb->CreatePalette(devdata->dfb, &pal_desc,&data->palette));
    583            SDL_DFB_CHECKERR(data->surface->SetPalette(data->surface, data->palette));
    584#endif
    585        }
    586
    587    }
    588#if (DFB_VERSION_ATLEAST(1,2,0))
    589    data->render_options = DSRO_NONE;
    590#endif
    591    if (texture->access == SDL_TEXTUREACCESS_STREAMING) {
    592        /* 3 plane YUVs return 1 bpp, but we need more space for other planes */
    593        if(texture->format == SDL_PIXELFORMAT_YV12 ||
    594           texture->format == SDL_PIXELFORMAT_IYUV) {
    595            SDL_DFB_ALLOC_CLEAR(data->pixels, (texture->h * data->pitch  + ((texture->h + texture->h % 2) * (data->pitch + data->pitch % 2) * 2) / 4));
    596        } else {
    597            SDL_DFB_ALLOC_CLEAR(data->pixels, texture->h * data->pitch);
    598        }
    599    }
    600
    601    return 0;
    602
    603  error:
    604    SDL_DFB_RELEASE(data->palette);
    605    SDL_DFB_RELEASE(data->surface);
    606    SDL_DFB_FREE(texture->driverdata);
    607    return -1;
    608}
    609
    610static int
    611DirectFB_QueryTexturePixels(SDL_Renderer * renderer,
    612                            SDL_Texture * texture, void **pixels, int *pitch)
    613{
    614    DirectFB_TextureData *texturedata =
    615        (DirectFB_TextureData *) texture->driverdata;
    616
    617    if (texturedata->display) {
    618        return -1;
    619    } else {
    620        *pixels = texturedata->pixels;
    621        *pitch = texturedata->pitch;
    622    }
    623    return 0;
    624}
    625
    626static int
    627DirectFB_SetTexturePalette(SDL_Renderer * renderer,
    628                           SDL_Texture * texture,
    629                           const SDL_Color * colors, int firstcolor,
    630                           int ncolors)
    631{
    632    DirectFB_TextureData *data = (DirectFB_TextureData *) texture->driverdata;
    633    if (SDL_ISPIXELFORMAT_INDEXED(data->format)
    634        && !SDL_ISPIXELFORMAT_FOURCC(data->format)) {
    635        DFBColor entries[256];
    636        int i;
    637
    638        if (ncolors > 256)
    639            ncolors = 256;
    640
    641        for (i = 0; i < ncolors; ++i) {
    642            entries[i].r = colors[i].r;
    643            entries[i].g = colors[i].g;
    644            entries[i].b = colors[i].b;
    645            entries[i].a = 0xff;
    646        }
    647        SDL_DFB_CHECKERR(data->
    648                         palette->SetEntries(data->palette, entries, ncolors, firstcolor));
    649        return 0;
    650    } else {
    651        return SDL_SetError("YUV textures don't have a palette");
    652    }
    653  error:
    654    return -1;
    655}
    656
    657static int
    658DirectFB_GetTexturePalette(SDL_Renderer * renderer,
    659                           SDL_Texture * texture, SDL_Color * colors,
    660                           int firstcolor, int ncolors)
    661{
    662    DirectFB_TextureData *data = (DirectFB_TextureData *) texture->driverdata;
    663
    664    if (SDL_ISPIXELFORMAT_INDEXED(data->format)
    665        && !SDL_ISPIXELFORMAT_FOURCC(data->format)) {
    666        DFBColor entries[256];
    667        int i;
    668
    669        SDL_DFB_CHECKERR(data->
    670                         palette->GetEntries(data->palette, entries, ncolors,
    671                                             firstcolor));
    672
    673        for (i = 0; i < ncolors; ++i) {
    674            colors[i].r = entries[i].r;
    675            colors[i].g = entries[i].g;
    676            colors[i].b = entries[i].b;
    677            colors[i].a = SDL_ALPHA_OPAQUE;
    678        }
    679        return 0;
    680    } else {
    681        return SDL_SetError("YUV textures don't have a palette");
    682    }
    683  error:
    684    return -1;
    685}
    686
    687static int
    688DirectFB_SetTextureAlphaMod(SDL_Renderer * renderer, SDL_Texture * texture)
    689{
    690    return 0;
    691}
    692
    693static int
    694DirectFB_SetTextureColorMod(SDL_Renderer * renderer, SDL_Texture * texture)
    695{
    696    return 0;
    697}
    698
    699static int
    700DirectFB_SetTextureBlendMode(SDL_Renderer * renderer, SDL_Texture * texture)
    701{
    702    switch (texture->blendMode) {
    703    case SDL_BLENDMODE_NONE:
    704    /* case SDL_BLENDMODE_MASK: */
    705    case SDL_BLENDMODE_BLEND:
    706    case SDL_BLENDMODE_ADD:
    707    case SDL_BLENDMODE_MOD:
    708        return 0;
    709    default:
    710        texture->blendMode = SDL_BLENDMODE_NONE;
    711        return SDL_Unsupported();
    712    }
    713}
    714
    715static int
    716DirectFB_SetDrawBlendMode(SDL_Renderer * renderer)
    717{
    718    switch (renderer->blendMode) {
    719    case SDL_BLENDMODE_NONE:
    720    /* case SDL_BLENDMODE_MASK: */
    721    case SDL_BLENDMODE_BLEND:
    722    case SDL_BLENDMODE_ADD:
    723    case SDL_BLENDMODE_MOD:
    724        return 0;
    725    default:
    726        renderer->blendMode = SDL_BLENDMODE_NONE;
    727        return SDL_Unsupported();
    728    }
    729}
    730
    731#if 0
    732static int
    733DirectFB_SetTextureScaleMode(SDL_Renderer * renderer, SDL_Texture * texture)
    734{
    735#if (DFB_VERSION_ATLEAST(1,2,0))
    736
    737    DirectFB_TextureData *data = (DirectFB_TextureData *) texture->driverdata;
    738
    739    switch (texture->scaleMode) {
    740    case SDL_SCALEMODE_NONE:
    741    case SDL_SCALEMODE_FAST:
    742        data->render_options = DSRO_NONE;
    743        break;
    744    case SDL_SCALEMODE_SLOW:
    745        data->render_options = DSRO_SMOOTH_UPSCALE | DSRO_SMOOTH_DOWNSCALE;
    746        break;
    747    case SDL_SCALEMODE_BEST:
    748        data->render_options =
    749            DSRO_SMOOTH_UPSCALE | DSRO_SMOOTH_DOWNSCALE | DSRO_ANTIALIAS;
    750        break;
    751    default:
    752        data->render_options = DSRO_NONE;
    753        texture->scaleMode = SDL_SCALEMODE_NONE;
    754        return SDL_Unsupported();
    755    }
    756#endif
    757    return 0;
    758}
    759#endif
    760
    761static int
    762DirectFB_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture,
    763                       const SDL_Rect * rect, const void *pixels, int pitch)
    764{
    765    DirectFB_TextureData *data = (DirectFB_TextureData *) texture->driverdata;
    766    Uint8 *dpixels;
    767    int dpitch;
    768    Uint8 *src, *dst;
    769    int row;
    770    size_t length;
    771    int bpp = DFB_BYTES_PER_PIXEL(DirectFB_SDLToDFBPixelFormat(texture->format));
    772    /* FIXME: SDL_BYTESPERPIXEL(texture->format) broken for yuv yv12 3 planes */
    773
    774    DirectFB_ActivateRenderer(renderer);
    775
    776    if ((texture->format == SDL_PIXELFORMAT_YV12) ||
    777        (texture->format == SDL_PIXELFORMAT_IYUV)) {
    778        bpp = 1;
    779    }
    780
    781    SDL_DFB_CHECKERR(data->surface->Lock(data->surface,
    782                                         DSLF_WRITE | DSLF_READ,
    783                                         ((void **) &dpixels), &dpitch));
    784    src = (Uint8 *) pixels;
    785    dst = (Uint8 *) dpixels + rect->y * dpitch + rect->x * bpp;
    786    length = rect->w * bpp;
    787    for (row = 0; row < rect->h; ++row) {
    788        SDL_memcpy(dst, src, length);
    789        src += pitch;
    790        dst += dpitch;
    791    }
    792    /* copy other planes for 3 plane formats */
    793    if ((texture->format == SDL_PIXELFORMAT_YV12) ||
    794        (texture->format == SDL_PIXELFORMAT_IYUV)) {
    795        src = (Uint8 *) pixels + texture->h * pitch;
    796        dst = (Uint8 *) dpixels + texture->h * dpitch + rect->y * dpitch / 4 + rect->x * bpp / 2;
    797        for (row = 0; row < rect->h / 2 + (rect->h & 1); ++row) {
    798            SDL_memcpy(dst, src, length / 2);
    799            src += pitch / 2;
    800            dst += dpitch / 2;
    801        }
    802        src = (Uint8 *) pixels + texture->h * pitch + texture->h * pitch / 4;
    803        dst = (Uint8 *) dpixels + texture->h * dpitch + texture->h * dpitch / 4 + rect->y * dpitch / 4 + rect->x * bpp / 2;
    804        for (row = 0; row < rect->h / 2 + (rect->h & 1); ++row) {
    805            SDL_memcpy(dst, src, length / 2);
    806            src += pitch / 2;
    807            dst += dpitch / 2;
    808        }
    809    }
    810    SDL_DFB_CHECKERR(data->surface->Unlock(data->surface));
    811    data->isDirty = 0;
    812    return 0;
    813  error:
    814    return 1;
    815
    816}
    817
    818static int
    819DirectFB_LockTexture(SDL_Renderer * renderer, SDL_Texture * texture,
    820                     const SDL_Rect * rect, void **pixels, int *pitch)
    821{
    822    DirectFB_TextureData *texturedata =
    823        (DirectFB_TextureData *) texture->driverdata;
    824
    825    DirectFB_ActivateRenderer(renderer);
    826
    827#if 0
    828    if (markDirty) {
    829        SDL_AddDirtyRect(&texturedata->dirty, rect);
    830    }
    831#endif
    832
    833    if (texturedata->display) {
    834        void *fdata;
    835        int fpitch;
    836
    837        SDL_DFB_CHECKERR(texturedata->surface->Lock(texturedata->surface,
    838                                                    DSLF_WRITE | DSLF_READ,
    839                                                    &fdata, &fpitch));
    840        *pitch = fpitch;
    841        *pixels = fdata;
    842    } else {
    843        *pixels =
    844            (void *) ((Uint8 *) texturedata->pixels +
    845                      rect->y * texturedata->pitch +
    846                      rect->x * DFB_BYTES_PER_PIXEL(DirectFB_SDLToDFBPixelFormat(texture->format)));
    847        *pitch = texturedata->pitch;
    848        texturedata->isDirty = 1;
    849    }
    850    return 0;
    851
    852  error:
    853    return -1;
    854}
    855
    856static void
    857DirectFB_UnlockTexture(SDL_Renderer * renderer, SDL_Texture * texture)
    858{
    859    DirectFB_TextureData *texturedata =
    860        (DirectFB_TextureData *) texture->driverdata;
    861
    862    DirectFB_ActivateRenderer(renderer);
    863
    864    if (texturedata->display) {
    865        SDL_DFB_CHECK(texturedata->surface->Unlock(texturedata->surface));
    866        texturedata->pixels = NULL;
    867    }
    868}
    869
    870#if 0
    871static void
    872DirectFB_DirtyTexture(SDL_Renderer * renderer, SDL_Texture * texture,
    873                      int numrects, const SDL_Rect * rects)
    874{
    875    DirectFB_TextureData *data = (DirectFB_TextureData *) texture->driverdata;
    876    int i;
    877
    878    for (i = 0; i < numrects; ++i) {
    879        SDL_AddDirtyRect(&data->dirty, &rects[i]);
    880    }
    881}
    882#endif
    883
    884static int DirectFB_SetRenderTarget(SDL_Renderer * renderer, SDL_Texture * texture)
    885{
    886    DirectFB_RenderData *data = (DirectFB_RenderData *) renderer->driverdata;
    887    DirectFB_TextureData *tex_data = NULL;
    888
    889    DirectFB_ActivateRenderer(renderer);
    890    if (texture) {
    891        tex_data = (DirectFB_TextureData *) texture->driverdata;
    892        data->target = tex_data->surface;
    893    } else {
    894        data->target = get_dfb_surface(data->window);
    895    }
    896    data->lastBlendMode = 0;
    897    return 0;
    898}
    899
    900
    901static int
    902PrepareDraw(SDL_Renderer * renderer)
    903{
    904    DirectFB_RenderData *data = (DirectFB_RenderData *) renderer->driverdata;
    905    IDirectFBSurface *destsurf = data->target;
    906
    907    Uint8 r, g, b, a;
    908
    909    r = renderer->r;
    910    g = renderer->g;
    911    b = renderer->b;
    912    a = renderer->a;
    913
    914    SetBlendMode(data, renderer->blendMode, NULL);
    915    SDL_DFB_CHECKERR(destsurf->SetDrawingFlags(destsurf, data->drawFlags));
    916
    917    switch (renderer->blendMode) {
    918    case SDL_BLENDMODE_NONE:
    919    /* case SDL_BLENDMODE_MASK: */
    920    case SDL_BLENDMODE_BLEND:
    921        break;
    922    case SDL_BLENDMODE_ADD:
    923    case SDL_BLENDMODE_MOD:
    924        r = ((int) r * (int) a) / 255;
    925        g = ((int) g * (int) a) / 255;
    926        b = ((int) b * (int) a) / 255;
    927        a = 255;
    928        break;
    929    }
    930
    931    SDL_DFB_CHECKERR(destsurf->SetColor(destsurf, r, g, b, a));
    932    return 0;
    933  error:
    934    return -1;
    935}
    936
    937static int DirectFB_RenderDrawPoints(SDL_Renderer * renderer,
    938                                const SDL_FPoint * points, int count)
    939{
    940    DirectFB_RenderData *data = (DirectFB_RenderData *) renderer->driverdata;
    941    IDirectFBSurface *destsurf = data->target;
    942    DFBRegion clip_region;
    943    int i;
    944
    945    DirectFB_ActivateRenderer(renderer);
    946
    947    PrepareDraw(renderer);
    948    destsurf->GetClip(destsurf, &clip_region);
    949    for (i=0; i < count; i++) {
    950        int x = points[i].x + clip_region.x1;
    951        int y = points[i].y + clip_region.y1;
    952        SDL_DFB_CHECKERR(destsurf->DrawLine(destsurf, x, y, x, y));
    953    }
    954    return 0;
    955  error:
    956    return -1;
    957}
    958
    959static int DirectFB_RenderDrawLines(SDL_Renderer * renderer,
    960                               const SDL_FPoint * points, int count)
    961{
    962    DirectFB_RenderData *data = (DirectFB_RenderData *) renderer->driverdata;
    963    IDirectFBSurface *destsurf = data->target;
    964    DFBRegion clip_region;
    965    int i;
    966
    967    DirectFB_ActivateRenderer(renderer);
    968
    969    PrepareDraw(renderer);
    970    /* Use antialiasing when available */
    971#if (DFB_VERSION_ATLEAST(1,2,0))
    972    SDL_DFB_CHECKERR(destsurf->SetRenderOptions(destsurf, DSRO_ANTIALIAS));
    973#endif
    974
    975    destsurf->GetClip(destsurf, &clip_region);
    976    for (i=0; i < count - 1; i++) {
    977        int x1 = points[i].x + clip_region.x1;
    978        int y1 = points[i].y + clip_region.y1;
    979        int x2 = points[i + 1].x + clip_region.x1;
    980        int y2 = points[i + 1].y + clip_region.y1;
    981        SDL_DFB_CHECKERR(destsurf->DrawLine(destsurf, x1, y1, x2, y2));
    982    }
    983
    984    return 0;
    985  error:
    986    return -1;
    987}
    988
    989static int
    990DirectFB_RenderDrawRects(SDL_Renderer * renderer, const SDL_Rect ** rects, int count)
    991{
    992    DirectFB_RenderData *data = (DirectFB_RenderData *) renderer->driverdata;
    993    IDirectFBSurface *destsurf = data->target;
    994    DFBRegion clip_region;
    995    int i;
    996
    997    DirectFB_ActivateRenderer(renderer);
    998
    999    PrepareDraw(renderer);
   1000
   1001    destsurf->GetClip(destsurf, &clip_region);
   1002    for (i=0; i<count; i++) {
   1003        SDL_Rect dst = {rects[i]->x, rects[i]->y, rects[i]->w, rects[i]->h};
   1004        dst.x += clip_region.x1;
   1005        dst.y += clip_region.y1;
   1006        SDL_DFB_CHECKERR(destsurf->DrawRectangle(destsurf, dst.x, dst.y,
   1007                dst.w, dst.h));
   1008    }
   1009
   1010    return 0;
   1011  error:
   1012    return -1;
   1013}
   1014
   1015static int
   1016DirectFB_RenderFillRects(SDL_Renderer * renderer, const SDL_FRect * rects, int count)
   1017{
   1018    DirectFB_RenderData *data = (DirectFB_RenderData *) renderer->driverdata;
   1019    IDirectFBSurface *destsurf = data->target;
   1020    DFBRegion clip_region;
   1021    int i;
   1022
   1023    DirectFB_ActivateRenderer(renderer);
   1024
   1025    PrepareDraw(renderer);
   1026
   1027    destsurf->GetClip(destsurf, &clip_region);
   1028    for (i=0; i<count; i++) {
   1029        SDL_Rect dst = {rects[i].x, rects[i].y, rects[i].w, rects[i].h};
   1030        dst.x += clip_region.x1;
   1031        dst.y += clip_region.y1;
   1032        SDL_DFB_CHECKERR(destsurf->FillRectangle(destsurf, dst.x, dst.y,
   1033                dst.w, dst.h));
   1034    }
   1035
   1036    return 0;
   1037  error:
   1038    return -1;
   1039}
   1040
   1041static int
   1042DirectFB_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture,
   1043                    const SDL_Rect * srcrect, const SDL_FRect * dstrect)
   1044{
   1045    DirectFB_RenderData *data = (DirectFB_RenderData *) renderer->driverdata;
   1046    IDirectFBSurface *destsurf = data->target;
   1047    DirectFB_TextureData *texturedata =
   1048        (DirectFB_TextureData *) texture->driverdata;
   1049    Uint8 alpha, r, g, b;
   1050    DFBRegion clip_region;
   1051    DFBRectangle sr, dr;
   1052
   1053    DirectFB_ActivateRenderer(renderer);
   1054
   1055    SDLtoDFBRect(srcrect, &sr);
   1056    SDLtoDFBRect_Float(dstrect, &dr);
   1057
   1058    destsurf->GetClip(destsurf, &clip_region);
   1059    dr.x += clip_region.x1;
   1060    dr.y += clip_region.y1;
   1061
   1062    if (texturedata->display) {
   1063        int px, py;
   1064        SDL_Window *window = renderer->window;
   1065        IDirectFBWindow *dfbwin = get_dfb_window(window);
   1066        SDL_DFB_WINDOWDATA(window);
   1067        SDL_VideoDisplay *display = texturedata->display;
   1068        DFB_DisplayData *dispdata = (DFB_DisplayData *) display->driverdata;
   1069
   1070        SDL_DFB_CHECKERR(dispdata->
   1071                         vidlayer->SetSourceRectangle(dispdata->vidlayer,
   1072                                                      sr.x, sr.y, sr.w, sr.h));
   1073        dfbwin->GetPosition(dfbwin, &px, &py);
   1074        px += windata->client.x;
   1075        py += windata->client.y;
   1076        SDL_DFB_CHECKERR(dispdata->
   1077                         vidlayer->SetScreenRectangle(dispdata->vidlayer,
   1078                                                      px + dr.x,
   1079                                                      py + dr.y,
   1080                                                      dr.w,
   1081                                                      dr.h));
   1082    } else {
   1083        DFBSurfaceBlittingFlags flags = 0;
   1084
   1085#if 0
   1086        if (texturedata->dirty.list) {
   1087            SDL_DirtyRect *dirty;
   1088            void *pixels;
   1089            int bpp = DFB_BYTES_PER_PIXEL(DirectFB_SDLToDFBPixelFormat(texture->format));
   1090            int pitch = texturedata->pitch;
   1091
   1092            for (dirty = texturedata->dirty.list; dirty; dirty = dirty->next) {
   1093                SDL_Rect *rect = &dirty->rect;
   1094                pixels =
   1095                    (void *) ((Uint8 *) texturedata->pixels +
   1096                              rect->y * pitch + rect->x * bpp);
   1097                DirectFB_UpdateTexture(renderer, texture, rect,
   1098                                       pixels,
   1099                                       texturedata->pitch);
   1100            }
   1101            SDL_ClearDirtyRects(&texturedata->dirty);
   1102        }
   1103#endif
   1104        if (texturedata->isDirty)
   1105        {
   1106            SDL_Rect rect;
   1107
   1108            rect.x = 0;
   1109            rect.y = 0;
   1110            rect.w = texture->w;
   1111            rect.h = texture->h;
   1112
   1113            DirectFB_UpdateTexture(renderer, texture, &rect, texturedata->pixels, texturedata->pitch);
   1114        }
   1115
   1116        alpha = r = g = b = 0xff;
   1117        if (texture->modMode & SDL_TEXTUREMODULATE_ALPHA){
   1118            alpha = texture->a;
   1119            flags |= DSBLIT_BLEND_COLORALPHA;
   1120        }
   1121
   1122        if (texture->modMode & SDL_TEXTUREMODULATE_COLOR) {
   1123            r = texture->r;
   1124            g = texture->g;
   1125            b = texture->b;
   1126            flags |= DSBLIT_COLORIZE;
   1127        }
   1128        SDL_DFB_CHECKERR(destsurf->
   1129                         SetColor(destsurf, r, g, b, alpha));
   1130
   1131        /* ???? flags |= DSBLIT_SRC_PREMULTCOLOR; */
   1132
   1133        SetBlendMode(data, texture->blendMode, texturedata);
   1134
   1135        SDL_DFB_CHECKERR(destsurf->SetBlittingFlags(destsurf,
   1136                                                    data->blitFlags | flags));
   1137
   1138#if (DFB_VERSION_ATLEAST(1,2,0))
   1139        SDL_DFB_CHECKERR(destsurf->SetRenderOptions(destsurf,
   1140                                                    texturedata->
   1141                                                    render_options));
   1142#endif
   1143
   1144        if (srcrect->w == dstrect->w && srcrect->h == dstrect->h) {
   1145            SDL_DFB_CHECKERR(destsurf->Blit(destsurf,
   1146                                            texturedata->surface,
   1147                                            &sr, dr.x, dr.y));
   1148        } else {
   1149            SDL_DFB_CHECKERR(destsurf->StretchBlit(destsurf,
   1150                                                   texturedata->surface,
   1151                                                   &sr, &dr));
   1152        }
   1153    }
   1154    return 0;
   1155  error:
   1156    return -1;
   1157}
   1158
   1159static void
   1160DirectFB_RenderPresent(SDL_Renderer * renderer)
   1161{
   1162    DirectFB_RenderData *data = (DirectFB_RenderData *) renderer->driverdata;
   1163    SDL_Window *window = renderer->window;
   1164    SDL_DFB_WINDOWDATA(window);
   1165    SDL_ShapeData *shape_data = (window->shaper ? window->shaper->driverdata : NULL);
   1166
   1167    DirectFB_ActivateRenderer(renderer);
   1168
   1169    if (shape_data && shape_data->surface) {
   1170        /* saturate the window surface alpha channel */
   1171        SDL_DFB_CHECK(windata->window_surface->SetSrcBlendFunction(windata->window_surface, DSBF_ONE));
   1172        SDL_DFB_CHECK(windata->window_surface->SetDstBlendFunction(windata->window_surface, DSBF_ONE));
   1173        SDL_DFB_CHECK(windata->window_surface->SetDrawingFlags(windata->window_surface, DSDRAW_BLEND));
   1174        SDL_DFB_CHECK(windata->window_surface->SetColor(windata->window_surface, 0, 0, 0, 0xff));
   1175        SDL_DFB_CHECK(windata->window_surface->FillRectangle(windata->window_surface, 0,0, windata->size.w, windata->size.h));
   1176
   1177        /* blit the mask */
   1178        SDL_DFB_CHECK(windata->surface->SetSrcBlendFunction(windata->surface, DSBF_DESTCOLOR));
   1179        SDL_DFB_CHECK(windata->surface->SetDstBlendFunction(windata->surface, DSBF_ZERO));
   1180        SDL_DFB_CHECK(windata->surface->SetBlittingFlags(windata->surface, DSBLIT_BLEND_ALPHACHANNEL));
   1181#if (DFB_VERSION_ATLEAST(1,2,0))
   1182        SDL_DFB_CHECK(windata->surface->SetRenderOptions(windata->surface, DSRO_NONE));
   1183#endif
   1184        SDL_DFB_CHECK(windata->surface->Blit(windata->surface, shape_data->surface, NULL, 0, 0));
   1185    }
   1186
   1187    /* Send the data to the display */
   1188    SDL_DFB_CHECK(windata->window_surface->Flip(windata->window_surface, NULL,
   1189                                                data->flipflags));
   1190}
   1191
   1192static void
   1193DirectFB_DestroyTexture(SDL_Renderer * renderer, SDL_Texture * texture)
   1194{
   1195    DirectFB_TextureData *data = (DirectFB_TextureData *) texture->driverdata;
   1196
   1197    DirectFB_ActivateRenderer(renderer);
   1198
   1199    if (!data) {
   1200        return;
   1201    }
   1202    SDL_DFB_RELEASE(data->palette);
   1203    SDL_DFB_RELEASE(data->surface);
   1204    if (data->display) {
   1205        DFB_DisplayData *dispdata =
   1206            (DFB_DisplayData *) data->display->driverdata;
   1207        dispdata->vidIDinuse = 0;
   1208        /* FIXME: Shouldn't we reset the cooperative level */
   1209        SDL_DFB_CHECK(dispdata->vidlayer->SetCooperativeLevel(dispdata->vidlayer,
   1210                                                DLSCL_ADMINISTRATIVE));
   1211        SDL_DFB_RELEASE(dispdata->vidlayer);
   1212    }
   1213    SDL_DFB_FREE(data->pixels);
   1214    SDL_free(data);
   1215    texture->driverdata = NULL;
   1216}
   1217
   1218static void
   1219DirectFB_DestroyRenderer(SDL_Renderer * renderer)
   1220{
   1221    DirectFB_RenderData *data = (DirectFB_RenderData *) renderer->driverdata;
   1222    SDL_VideoDisplay *display = SDL_GetDisplayForWindow(data->window);
   1223#if 0
   1224    if (display->palette) {
   1225        SDL_DelPaletteWatch(display->palette, DisplayPaletteChanged, data);
   1226    }
   1227#endif
   1228
   1229    SDL_free(data);
   1230    SDL_free(renderer);
   1231}
   1232
   1233static int
   1234DirectFB_UpdateViewport(SDL_Renderer * renderer)
   1235{
   1236    DirectFB_RenderData *data = (DirectFB_RenderData *) renderer->driverdata;
   1237    IDirectFBSurface *winsurf = data->target;
   1238    DFBRegion dreg;
   1239
   1240    dreg.x1 = renderer->viewport.x;
   1241    dreg.y1 = renderer->viewport.y;
   1242    dreg.x2 = dreg.x1 + renderer->viewport.w - 1;
   1243    dreg.y2 = dreg.y1 + renderer->viewport.h - 1;
   1244
   1245    winsurf->SetClip(winsurf, &dreg);
   1246    return 0;
   1247}
   1248
   1249static int
   1250DirectFB_UpdateClipRect(SDL_Renderer * renderer)
   1251{
   1252    const SDL_Rect *rect = &renderer->clip_rect;
   1253    DirectFB_RenderData *data = (DirectFB_RenderData *) renderer->driverdata;
   1254    IDirectFBSurface *destsurf = get_dfb_surface(data->window);
   1255    DFBRegion region;
   1256
   1257    if (!SDL_RectEmpty(rect)) {
   1258        region.x1 = rect->x;
   1259        region.x2 = rect->x + rect->w;
   1260        region.y1 = rect->y;
   1261        region.y2 = rect->y + rect->h;
   1262        SDL_DFB_CHECKERR(destsurf->SetClip(destsurf, &region));
   1263    } else {
   1264        SDL_DFB_CHECKERR(destsurf->SetClip(destsurf, NULL));
   1265    }
   1266    return 0;
   1267  error:
   1268    return -1;
   1269}
   1270
   1271static int
   1272DirectFB_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect,
   1273                     Uint32 format, void * pixels, int pitch)
   1274{
   1275    Uint32 sdl_format;
   1276    void * laypixels;
   1277    int laypitch;
   1278    DFBSurfacePixelFormat dfb_format;
   1279    DirectFB_RenderData *data = (DirectFB_RenderData *) renderer->driverdata;
   1280    IDirectFBSurface *winsurf = data->target;
   1281
   1282    DirectFB_ActivateRenderer(renderer);
   1283
   1284    winsurf->GetPixelFormat(winsurf, &dfb_format);
   1285    sdl_format = DirectFB_DFBToSDLPixelFormat(dfb_format);
   1286    winsurf->Lock(winsurf, DSLF_READ, (void **) &laypixels, &laypitch);
   1287
   1288    laypixels += (rect->y * laypitch + rect->x * SDL_BYTESPERPIXEL(sdl_format) );
   1289    SDL_ConvertPixels(rect->w, rect->h,
   1290                      sdl_format, laypixels, laypitch,
   1291                      format, pixels, pitch);
   1292
   1293    winsurf->Unlock(winsurf);
   1294
   1295    return 0;
   1296}
   1297
   1298#if 0
   1299static int
   1300DirectFB_RenderWritePixels(SDL_Renderer * renderer, const SDL_Rect * rect,
   1301                      Uint32 format, const void * pixels, int pitch)
   1302{
   1303    SDL_Window *window = renderer->window;
   1304    SDL_DFB_WINDOWDATA(window);
   1305    Uint32 sdl_format;
   1306    void * laypixels;
   1307    int laypitch;
   1308    DFBSurfacePixelFormat dfb_format;
   1309
   1310    SDL_DFB_CHECK(windata->surface->GetPixelFormat(windata->surface, &dfb_format));
   1311    sdl_format = DirectFB_DFBToSDLPixelFormat(dfb_format);
   1312
   1313    SDL_DFB_CHECK(windata->surface->Lock(windata->surface, DSLF_WRITE, (void **) &laypixels, &laypitch));
   1314
   1315    laypixels += (rect->y * laypitch + rect->x * SDL_BYTESPERPIXEL(sdl_format) );
   1316    SDL_ConvertPixels(rect->w, rect->h,
   1317                      format, pixels, pitch,
   1318                      sdl_format, laypixels, laypitch);
   1319
   1320    SDL_DFB_CHECK(windata->surface->Unlock(windata->surface));
   1321
   1322    return 0;
   1323}
   1324#endif
   1325
   1326#endif /* SDL_VIDEO_DRIVER_DIRECTFB */
   1327
   1328/* vi: set ts=4 sw=4 expandtab: */