src/video/directfb/SDL_DirectFB_video.c
author Sam Lantinga
Sun, 04 Jan 2004 15:57:16 +0000
changeset 767 d9e79e31a7b7
parent 759 26ac9609211f
child 769 b8d311d90021
permissions -rw-r--r--
Date: Mon, 17 Nov 2003 21:59:24 -0800
From: Pete Shinners
Subject: [SDL] directfb cursor patch

here is a quick and dirty patch that allows directfb to change the
visibility of the cursor. this display backend still has no way to change
the actual cursor shape, but being able to set the cursor visibility is a
simple change that should offer some benefits.

the code was largely based on the cursor code for other sdl backends. and
this documentation.
http://directfb.org/documentation/DirectFB_Reference/IDirectFBDisplayLayer_SetCursorOpacity.html
slouken@167
     1
/*
slouken@167
     2
	SDL - Simple DirectMedia Layer
slouken@297
     3
	Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002  Sam Lantinga
slouken@167
     4
slouken@167
     5
	This library is free software; you can redistribute it and/or
slouken@167
     6
	modify it under the terms of the GNU Library General Public
slouken@167
     7
	License as published by the Free Software Foundation; either
slouken@167
     8
	version 2 of the License, or (at your option) any later version.
slouken@167
     9
slouken@167
    10
	This library is distributed in the hope that it will be useful,
slouken@167
    11
	but WITHOUT ANY WARRANTY; without even the implied warranty of
slouken@167
    12
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
slouken@167
    13
	Library General Public License for more details.
slouken@167
    14
slouken@167
    15
	You should have received a copy of the GNU Library General Public
slouken@167
    16
	License along with this library; if not, write to the Free
slouken@167
    17
	Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
slouken@167
    18
slouken@167
    19
	Sam Lantinga
slouken@252
    20
	slouken@libsdl.org
icculus@728
    21
icculus@728
    22
	MGA CRTC2 support by Thomas Jarosch - tomj@simonv.com
icculus@728
    23
	CRTC2 support is inspired by mplayer's dfbmga driver
icculus@728
    24
	written by Ville Syrj��<syrjala@sci.fi>
slouken@167
    25
*/
slouken@167
    26
slouken@167
    27
#ifdef SAVE_RCSID
slouken@167
    28
static char rcsid =
slouken@167
    29
 "@(#) $Id$";
slouken@167
    30
#endif
slouken@167
    31
slouken@167
    32
/* DirectFB video driver implementation.
slouken@167
    33
*/
slouken@167
    34
slouken@167
    35
#include <stdlib.h>
slouken@464
    36
#include <string.h>
slouken@167
    37
#include <stdio.h>
slouken@167
    38
#include <fcntl.h>
slouken@167
    39
#include <unistd.h>
slouken@167
    40
#include <sys/mman.h>
slouken@167
    41
slouken@167
    42
#include <directfb.h>
slouken@167
    43
slouken@167
    44
#include "SDL.h"
slouken@167
    45
#include "SDL_error.h"
slouken@167
    46
#include "SDL_video.h"
slouken@167
    47
#include "SDL_mouse.h"
slouken@167
    48
#include "SDL_sysvideo.h"
slouken@167
    49
#include "SDL_pixels_c.h"
slouken@167
    50
#include "SDL_events_c.h"
slouken@167
    51
#include "SDL_DirectFB_video.h"
slouken@167
    52
#include "SDL_DirectFB_events.h"
slouken@478
    53
#include "SDL_DirectFB_yuv.h"
slouken@167
    54
slouken@767
    55
/* The implementation dependent data for the window manager cursor */
slouken@767
    56
struct WMcursor {
slouken@767
    57
	int unused;
slouken@767
    58
};
slouken@767
    59
slouken@167
    60
slouken@167
    61
/* Initialization/Query functions */
slouken@167
    62
static int DirectFB_VideoInit(_THIS, SDL_PixelFormat *vformat);
slouken@167
    63
static SDL_Rect **DirectFB_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags);
slouken@167
    64
static SDL_Surface *DirectFB_SetVideoMode(_THIS, SDL_Surface *current, int width, int height, int bpp, Uint32 flags);
slouken@167
    65
static int DirectFB_SetColors(_THIS, int firstcolor, int ncolors,
slouken@167
    66
			 SDL_Color *colors);
slouken@167
    67
static void DirectFB_VideoQuit(_THIS);
slouken@167
    68
slouken@167
    69
/* Hardware surface functions */
slouken@167
    70
static int DirectFB_AllocHWSurface(_THIS, SDL_Surface *surface);
slouken@167
    71
static int DirectFB_FillHWRect(_THIS, SDL_Surface *dst, SDL_Rect *dstrect, Uint32 color);
slouken@167
    72
static int DirectFB_LockHWSurface(_THIS, SDL_Surface *surface);
slouken@167
    73
static void DirectFB_UnlockHWSurface(_THIS, SDL_Surface *surface);
slouken@167
    74
static void DirectFB_FreeHWSurface(_THIS, SDL_Surface *surface);
slouken@167
    75
static int DirectFB_CheckHWBlit(_THIS, SDL_Surface *src, SDL_Surface *dst);
slouken@167
    76
static int DirectFB_HWAccelBlit(SDL_Surface *src, SDL_Rect *srcrect,
slouken@167
    77
                                SDL_Surface *dst, SDL_Rect *dstrect);
slouken@167
    78
static int DirectFB_SetHWColorKey(_THIS, SDL_Surface *surface, Uint32 key);
slouken@167
    79
static int DirectFB_SetHWAlpha(_THIS, SDL_Surface *surface, Uint8 alpha);
slouken@167
    80
static int DirectFB_FlipHWSurface(_THIS, SDL_Surface *surface);
slouken@767
    81
static int DirectFB_ShowWMCursor(_THIS, WMcursor *cursor);
slouken@167
    82
slouken@167
    83
/* Various screen update functions available */
slouken@167
    84
static void DirectFB_DirectUpdate(_THIS, int numrects, SDL_Rect *rects);
slouken@167
    85
static void DirectFB_WindowedUpdate(_THIS, int numrects, SDL_Rect *rects);
slouken@167
    86
slouken@167
    87
/* This is the rect EnumModes2 uses */
slouken@167
    88
struct DirectFBEnumRect {
slouken@167
    89
	SDL_Rect r;
slouken@167
    90
	struct DirectFBEnumRect* next;
slouken@167
    91
};
slouken@167
    92
slouken@464
    93
static struct DirectFBEnumRect *enumlist = NULL;
slouken@167
    94
slouken@167
    95
slouken@167
    96
/* DirectFB driver bootstrap functions */
slouken@167
    97
slouken@167
    98
static int DirectFB_Available(void)
slouken@167
    99
{
slouken@167
   100
  return 1;
slouken@167
   101
}
slouken@167
   102
slouken@167
   103
static void DirectFB_DeleteDevice(SDL_VideoDevice *device)
slouken@167
   104
{
slouken@167
   105
  free(device->hidden);
slouken@167
   106
  free(device);
slouken@167
   107
}
slouken@167
   108
slouken@167
   109
static SDL_VideoDevice *DirectFB_CreateDevice(int devindex)
slouken@167
   110
{
slouken@167
   111
  SDL_VideoDevice *device;
slouken@167
   112
slouken@167
   113
  /* Initialize all variables that we clean on shutdown */
slouken@167
   114
  device = (SDL_VideoDevice *)malloc(sizeof(SDL_VideoDevice));
slouken@167
   115
  if (device)
slouken@167
   116
    {
slouken@167
   117
      memset (device, 0, (sizeof *device));
slouken@167
   118
      device->hidden = (struct SDL_PrivateVideoData *) malloc (sizeof (*device->hidden));
slouken@167
   119
    }
slouken@167
   120
  if (device == NULL  ||  device->hidden == NULL)
slouken@167
   121
    {
slouken@167
   122
      SDL_OutOfMemory();
slouken@167
   123
      if (device)
slouken@167
   124
        {
slouken@167
   125
          free (device);
slouken@167
   126
        }
slouken@167
   127
      return(0);
slouken@167
   128
    }
slouken@167
   129
  memset (device->hidden, 0, sizeof (*device->hidden));
slouken@167
   130
slouken@167
   131
  /* Set the function pointers */
slouken@167
   132
  device->VideoInit = DirectFB_VideoInit;
slouken@167
   133
  device->ListModes = DirectFB_ListModes;
slouken@167
   134
  device->SetVideoMode = DirectFB_SetVideoMode;
slouken@167
   135
  device->SetColors = DirectFB_SetColors;
slouken@167
   136
  device->UpdateRects = NULL;
slouken@478
   137
  device->CreateYUVOverlay = DirectFB_CreateYUVOverlay;
slouken@167
   138
  device->VideoQuit = DirectFB_VideoQuit;
slouken@167
   139
  device->AllocHWSurface = DirectFB_AllocHWSurface;
slouken@167
   140
  device->CheckHWBlit = DirectFB_CheckHWBlit;
slouken@167
   141
  device->FillHWRect = DirectFB_FillHWRect;
slouken@167
   142
  device->SetHWColorKey = DirectFB_SetHWColorKey;
slouken@167
   143
  device->SetHWAlpha = DirectFB_SetHWAlpha;
slouken@167
   144
  device->LockHWSurface = DirectFB_LockHWSurface;
slouken@167
   145
  device->UnlockHWSurface = DirectFB_UnlockHWSurface;
slouken@167
   146
  device->FlipHWSurface = DirectFB_FlipHWSurface;
slouken@167
   147
  device->FreeHWSurface = DirectFB_FreeHWSurface;
slouken@767
   148
  device->ShowWMCursor = DirectFB_ShowWMCursor;
slouken@167
   149
  device->SetCaption = NULL;
slouken@167
   150
  device->SetIcon = NULL;
slouken@167
   151
  device->IconifyWindow = NULL;
slouken@167
   152
  device->GrabInput = NULL;
slouken@167
   153
  device->GetWMInfo = NULL;
slouken@167
   154
  device->InitOSKeymap = DirectFB_InitOSKeymap;
slouken@167
   155
  device->PumpEvents = DirectFB_PumpEvents;
slouken@167
   156
slouken@167
   157
  device->free = DirectFB_DeleteDevice;
slouken@167
   158
slouken@167
   159
  return device;
slouken@167
   160
}
slouken@167
   161
slouken@167
   162
VideoBootStrap DirectFB_bootstrap = {
slouken@167
   163
  "directfb", "DirectFB",
slouken@167
   164
  DirectFB_Available, DirectFB_CreateDevice
slouken@167
   165
};
slouken@167
   166
slouken@464
   167
static DFBSurfacePixelFormat GetFormatForBpp (int bpp, IDirectFBDisplayLayer *layer)
slouken@464
   168
{
slouken@464
   169
  DFBDisplayLayerConfig dlc;
slouken@464
   170
  int                   bytes = (bpp + 7) / 8;
slouken@464
   171
slouken@464
   172
  layer->GetConfiguration (layer, &dlc);
slouken@464
   173
slouken@477
   174
  if (bytes == DFB_BYTES_PER_PIXEL(dlc.pixelformat) && bytes > 1)
slouken@464
   175
    return dlc.pixelformat;
slouken@464
   176
slouken@464
   177
  switch (bytes)
slouken@464
   178
    {
slouken@464
   179
    case 1:
slouken@477
   180
      return DSPF_LUT8;
slouken@464
   181
    case 2:
slouken@464
   182
      return DSPF_RGB16;
slouken@464
   183
    case 3:
slouken@464
   184
      return DSPF_RGB24;
slouken@464
   185
    case 4:
slouken@464
   186
      return DSPF_RGB32;
slouken@464
   187
    }
slouken@464
   188
slouken@464
   189
  return DSPF_UNKNOWN;
slouken@464
   190
}
slouken@464
   191
slouken@167
   192
static DFBEnumerationResult EnumModesCallback (unsigned int  width,
slouken@167
   193
                                               unsigned int  height,
slouken@167
   194
                                               unsigned int  bpp,
slouken@167
   195
                                               void         *data)
slouken@167
   196
{
slouken@167
   197
  SDL_VideoDevice *this = (SDL_VideoDevice *)data;
slouken@167
   198
  struct DirectFBEnumRect *enumrect;
slouken@167
   199
slouken@464
   200
  HIDDEN->nummodes++;
slouken@464
   201
slouken@464
   202
  enumrect = calloc(1, sizeof(struct DirectFBEnumRect));
slouken@464
   203
  if (!enumrect)
slouken@167
   204
    {
slouken@464
   205
      SDL_OutOfMemory();
slouken@464
   206
      return DFENUM_CANCEL;
slouken@167
   207
    }
slouken@167
   208
slouken@464
   209
  enumrect->r.w  = width;
slouken@464
   210
  enumrect->r.h  = height;
slouken@464
   211
  enumrect->next = enumlist;
slouken@464
   212
slouken@464
   213
  enumlist = enumrect;
slouken@464
   214
slouken@167
   215
  return DFENUM_OK;
slouken@167
   216
}
slouken@167
   217
slouken@167
   218
struct private_hwdata {
slouken@167
   219
  IDirectFBSurface *surface;
slouken@477
   220
  IDirectFBPalette *palette;
slouken@167
   221
};
slouken@167
   222
slouken@167
   223
void SetDirectFBerror (const char *function, DFBResult code)
slouken@167
   224
{
slouken@167
   225
  const char *error = DirectFBErrorString (code);
slouken@167
   226
slouken@167
   227
  if (error)
slouken@167
   228
    SDL_SetError("%s: %s", function, error);
slouken@167
   229
  else
slouken@167
   230
    SDL_SetError("Unknown error code from %s", function);
slouken@167
   231
}
slouken@167
   232
slouken@167
   233
static DFBSurfacePixelFormat SDLToDFBPixelFormat (SDL_PixelFormat *format)
slouken@167
   234
{
slouken@167
   235
  if (format->Rmask && format->Gmask && format->Bmask)
slouken@167
   236
    {
slouken@167
   237
      switch (format->BitsPerPixel)
slouken@167
   238
        {
slouken@477
   239
        case 8:
slouken@477
   240
          return DSPF_LUT8;
slouken@477
   241
          
slouken@167
   242
        case 16:
slouken@167
   243
          if (format->Rmask == 0xF800 &&
slouken@167
   244
              format->Gmask == 0x07E0 &&
slouken@167
   245
              format->Bmask == 0x001F)
slouken@167
   246
            return DSPF_RGB16;
slouken@167
   247
          /* fall through */
slouken@167
   248
          
slouken@167
   249
        case 15:
slouken@167
   250
          if (format->Rmask == 0x7C00 &&
slouken@167
   251
              format->Gmask == 0x03E0 &&
slouken@167
   252
              format->Bmask == 0x001F)
slouken@167
   253
            return DSPF_RGB15;
slouken@167
   254
          break;
slouken@167
   255
          
slouken@167
   256
        case 24:
slouken@167
   257
          if (format->Rmask == 0xFF0000 &&
slouken@167
   258
              format->Gmask == 0x00FF00 &&
slouken@167
   259
              format->Bmask == 0x0000FF)
slouken@167
   260
            return DSPF_RGB24;
slouken@167
   261
          break;
slouken@464
   262
slouken@167
   263
        case 32:
slouken@167
   264
          if (format->Rmask == 0xFF0000 &&
slouken@167
   265
              format->Gmask == 0x00FF00 &&
slouken@167
   266
              format->Bmask == 0x0000FF)
slouken@167
   267
            {
slouken@167
   268
              if (format->Amask == 0xFF000000)
slouken@167
   269
                return DSPF_ARGB;
slouken@167
   270
              else
slouken@167
   271
                return DSPF_RGB32;
slouken@167
   272
            }
slouken@167
   273
          break;
slouken@167
   274
        }
slouken@167
   275
    }
slouken@167
   276
  else
slouken@167
   277
    {
slouken@167
   278
      switch (format->BitsPerPixel)
slouken@167
   279
	{
slouken@464
   280
        case 8:
slouken@477
   281
          return DSPF_LUT8;
slouken@167
   282
	case 15:
slouken@167
   283
	  return DSPF_RGB15;
slouken@167
   284
	case 16:
slouken@167
   285
	  return DSPF_RGB16;
slouken@167
   286
	case 24:
slouken@167
   287
	  return DSPF_RGB24;
slouken@167
   288
	case 32:
slouken@167
   289
	  return DSPF_RGB32;
slouken@167
   290
	}
slouken@167
   291
    }
slouken@167
   292
slouken@167
   293
  return DSPF_UNKNOWN;
slouken@167
   294
}
slouken@167
   295
slouken@477
   296
static SDL_Palette *AllocatePalette(int size)
slouken@464
   297
{
slouken@464
   298
  SDL_Palette *palette;
slouken@464
   299
  SDL_Color   *colors;
slouken@464
   300
slouken@464
   301
  palette = calloc (1, sizeof(SDL_Palette));
slouken@464
   302
  if (!palette)
slouken@464
   303
    {
slouken@464
   304
      SDL_OutOfMemory();
slouken@464
   305
      return NULL;
slouken@464
   306
    }
slouken@464
   307
slouken@477
   308
  colors = calloc (size, sizeof(SDL_Color));
slouken@464
   309
  if (!colors)
slouken@464
   310
    {
slouken@464
   311
      SDL_OutOfMemory();
slouken@464
   312
      return NULL;
slouken@464
   313
    }
slouken@464
   314
slouken@477
   315
  palette->ncolors = size;
slouken@464
   316
  palette->colors  = colors;
slouken@464
   317
slouken@464
   318
  return palette;
slouken@464
   319
}
slouken@464
   320
slouken@167
   321
static int DFBToSDLPixelFormat (DFBSurfacePixelFormat pixelformat, SDL_PixelFormat *format)
slouken@167
   322
{
slouken@167
   323
  format->Amask = format->Rmask = format->Gmask = format->Bmask = 0;
slouken@464
   324
  format->BitsPerPixel = format->BytesPerPixel = 0;
slouken@167
   325
slouken@167
   326
  switch (pixelformat)
slouken@167
   327
    {
slouken@167
   328
    case DSPF_A8:
slouken@167
   329
      format->Amask = 0x000000FF;
slouken@167
   330
      break;
slouken@464
   331
slouken@167
   332
    case DSPF_RGB15:
slouken@167
   333
      format->Rmask = 0x00007C00;
slouken@167
   334
      format->Gmask = 0x000003E0;
slouken@167
   335
      format->Bmask = 0x0000001F;
slouken@167
   336
      break;
slouken@464
   337
slouken@167
   338
    case DSPF_RGB16:
slouken@167
   339
      format->Rmask = 0x0000F800;
slouken@167
   340
      format->Gmask = 0x000007E0;
slouken@167
   341
      format->Bmask = 0x0000001F;
slouken@167
   342
      break;
slouken@464
   343
slouken@167
   344
    case DSPF_ARGB:
slouken@464
   345
      format->Amask = 0; /* apps don't seem to like that:  0xFF000000; */
slouken@167
   346
      /* fall through */
slouken@167
   347
    case DSPF_RGB24:
slouken@167
   348
    case DSPF_RGB32:
slouken@167
   349
      format->Rmask = 0x00FF0000;
slouken@167
   350
      format->Gmask = 0x0000FF00;
slouken@167
   351
      format->Bmask = 0x000000FF;
slouken@167
   352
      break;
slouken@464
   353
slouken@477
   354
    case DSPF_LUT8:
slouken@477
   355
      format->Rmask = 0x000000FF;
slouken@477
   356
      format->Gmask = 0x000000FF;
slouken@477
   357
      format->Bmask = 0x000000FF;
slouken@464
   358
slouken@477
   359
      if (!format->palette)
slouken@477
   360
        format->palette = AllocatePalette(256);
slouken@464
   361
      break;
slouken@464
   362
slouken@167
   363
    default:
slouken@477
   364
      fprintf (stderr, "SDL_DirectFB: Unsupported pixelformat (0x%08x)!\n", pixelformat);
slouken@167
   365
      return -1;
slouken@167
   366
    }
slouken@167
   367
slouken@464
   368
  format->BitsPerPixel  = DFB_BYTES_PER_PIXEL(pixelformat) * 8;
slouken@464
   369
  format->BytesPerPixel = DFB_BYTES_PER_PIXEL(pixelformat);
slouken@167
   370
slouken@167
   371
  return 0;
slouken@167
   372
}
slouken@167
   373
slouken@167
   374
slouken@167
   375
int DirectFB_VideoInit(_THIS, SDL_PixelFormat *vformat)
slouken@167
   376
{
slouken@464
   377
  int                      i;
slouken@464
   378
  DFBResult                ret;
slouken@464
   379
  DFBCardCapabilities      caps;
slouken@464
   380
  DFBDisplayLayerConfig    dlc;
slouken@464
   381
  struct DirectFBEnumRect *rect;
slouken@464
   382
  IDirectFB               *dfb    = NULL;
slouken@464
   383
  IDirectFBDisplayLayer   *layer  = NULL;
slouken@464
   384
  IDirectFBEventBuffer    *events = NULL;
slouken@167
   385
icculus@728
   386
  HIDDEN->c2layer = NULL, HIDDEN->c2frame = NULL;
icculus@728
   387
  HIDDEN->enable_mga_crtc2 = 0;
icculus@728
   388
  HIDDEN->mga_crtc2_stretch_overscan = 1;
slouken@167
   389
slouken@167
   390
  ret = DirectFBInit (NULL, NULL);
slouken@167
   391
  if (ret)
slouken@167
   392
    {
slouken@167
   393
      SetDirectFBerror ("DirectFBInit", ret);
slouken@464
   394
      goto error;
slouken@167
   395
    }
slouken@167
   396
slouken@167
   397
  ret = DirectFBCreate (&dfb);
slouken@167
   398
  if (ret)
slouken@167
   399
    {
slouken@167
   400
      SetDirectFBerror ("DirectFBCreate", ret);
slouken@464
   401
      goto error;
slouken@167
   402
    }
slouken@167
   403
slouken@167
   404
  ret = dfb->GetDisplayLayer (dfb, DLID_PRIMARY, &layer);
slouken@167
   405
  if (ret)
slouken@167
   406
    {
slouken@167
   407
      SetDirectFBerror ("dfb->GetDisplayLayer", ret);
slouken@464
   408
      goto error;
slouken@167
   409
    }
slouken@167
   410
slouken@546
   411
  ret = dfb->CreateInputEventBuffer (dfb, DICAPS_ALL, DFB_FALSE, &events);
slouken@167
   412
  if (ret)
slouken@167
   413
    {
slouken@286
   414
      SetDirectFBerror ("dfb->CreateEventBuffer", ret);
slouken@464
   415
      goto error;
slouken@167
   416
    }
slouken@167
   417
  
slouken@167
   418
  layer->EnableCursor (layer, 1);
slouken@167
   419
slouken@167
   420
  /* Query layer configuration to determine the current mode and pixelformat */
slouken@167
   421
  layer->GetConfiguration (layer, &dlc);
slouken@167
   422
slouken@477
   423
  /* If current format is not supported use LUT8 as the default */
slouken@477
   424
  if (DFBToSDLPixelFormat (dlc.pixelformat, vformat))
slouken@477
   425
    DFBToSDLPixelFormat (DSPF_LUT8, vformat);
slouken@167
   426
slouken@167
   427
  /* Enumerate the available fullscreen modes */
slouken@167
   428
  ret = dfb->EnumVideoModes (dfb, EnumModesCallback, this);
slouken@167
   429
  if (ret)
slouken@167
   430
    {
slouken@167
   431
      SetDirectFBerror ("dfb->EnumVideoModes", ret);
slouken@464
   432
      goto error;
slouken@167
   433
    }
slouken@464
   434
slouken@464
   435
  HIDDEN->modelist = calloc (HIDDEN->nummodes + 1, sizeof(SDL_Rect *));
slouken@464
   436
  if (!HIDDEN->modelist)
slouken@167
   437
    {
slouken@464
   438
      SDL_OutOfMemory();
slouken@464
   439
      goto error;
slouken@167
   440
    }
slouken@167
   441
slouken@464
   442
  for (i = 0, rect = enumlist; rect; ++i, rect = rect->next )
slouken@464
   443
    {
slouken@464
   444
      HIDDEN->modelist[i] = &rect->r;
slouken@464
   445
    }
slouken@464
   446
slouken@464
   447
  HIDDEN->modelist[i] = NULL;
slouken@464
   448
slouken@464
   449
slouken@167
   450
  /* Query card capabilities to get the video memory size */
slouken@167
   451
  dfb->GetCardCapabilities (dfb, &caps);
slouken@167
   452
slouken@167
   453
  this->info.wm_available = 1;
slouken@167
   454
  this->info.hw_available = 1;
slouken@167
   455
  this->info.blit_hw      = 1;
slouken@167
   456
  this->info.blit_hw_CC   = 1;
slouken@167
   457
  this->info.blit_hw_A    = 1;
slouken@167
   458
  this->info.blit_fill    = 1;
slouken@167
   459
  this->info.video_mem    = caps.video_memory / 1024;
slouken@167
   460
slouken@167
   461
  HIDDEN->initialized = 1;
slouken@167
   462
  HIDDEN->dfb         = dfb;
slouken@167
   463
  HIDDEN->layer       = layer;
slouken@464
   464
  HIDDEN->eventbuffer = events;
slouken@167
   465
icculus@728
   466
  if (getenv("SDL_DIRECTFB_MGA_CRTC2") != NULL)
icculus@728
   467
    HIDDEN->enable_mga_crtc2 = 1;
icculus@728
   468
  
icculus@728
   469
  if (HIDDEN->enable_mga_crtc2)
icculus@728
   470
    {
icculus@728
   471
      ret = dfb->GetDisplayLayer (dfb, 2, &HIDDEN->c2layer);
icculus@728
   472
      if (ret)
icculus@728
   473
        {
icculus@728
   474
          SetDirectFBerror ("dfb->GetDisplayLayer(CRTC2)", ret);
icculus@728
   475
          goto error;
icculus@728
   476
        }
icculus@728
   477
icculus@728
   478
      ret = HIDDEN->layer->SetCooperativeLevel(HIDDEN->layer, DLSCL_EXCLUSIVE);
icculus@728
   479
      if (ret)
icculus@728
   480
        {
icculus@728
   481
          SetDirectFBerror ("layer->SetCooperativeLevel(CRTC2, EXCLUSIVE)", ret);
icculus@728
   482
          goto error;
icculus@728
   483
        }
icculus@728
   484
 
icculus@728
   485
      ret = HIDDEN->c2layer->SetCooperativeLevel(HIDDEN->c2layer, DLSCL_EXCLUSIVE);
icculus@728
   486
      if (ret)
icculus@728
   487
        {
icculus@728
   488
          SetDirectFBerror ("c2layer->SetCooperativeLevel(CRTC2, EXCLUSIVE)", ret);
icculus@728
   489
          goto error;
icculus@728
   490
        }
icculus@728
   491
icculus@728
   492
      HIDDEN->c2layer->SetOpacity(HIDDEN->c2layer, 0x0);
icculus@728
   493
icculus@728
   494
      /* Init the surface here as it got a fixed size */
icculus@728
   495
      DFBDisplayLayerConfig      dlc;
icculus@728
   496
      DFBDisplayLayerConfigFlags failed;
icculus@728
   497
    
icculus@728
   498
      dlc.flags      = DLCONF_PIXELFORMAT | DLCONF_BUFFERMODE | DLCONF_OPTIONS;
icculus@728
   499
      dlc.buffermode = DLBM_BACKVIDEO;
icculus@728
   500
      dlc.options    = DLOP_FLICKER_FILTERING;
icculus@728
   501
      dlc.pixelformat = DSPF_RGB32;
icculus@728
   502
      
icculus@728
   503
      ret = HIDDEN->c2layer->TestConfiguration( HIDDEN->c2layer, &dlc, &failed );
icculus@728
   504
      if (ret)
icculus@728
   505
        {
icculus@728
   506
          SetDirectFBerror ("c2layer->TestConfiguration", ret);
icculus@728
   507
          goto error;
icculus@728
   508
        }
icculus@728
   509
    
icculus@728
   510
      ret = HIDDEN->c2layer->SetConfiguration( HIDDEN->c2layer, &dlc );
icculus@728
   511
      if (ret)
icculus@728
   512
        {
icculus@728
   513
          SetDirectFBerror ("c2layer->SetConfiguration", ret);
icculus@728
   514
          goto error;
icculus@728
   515
        }
icculus@728
   516
    
icculus@728
   517
      ret = HIDDEN->c2layer->GetSurface( HIDDEN->c2layer, &HIDDEN->c2frame );
icculus@728
   518
      if (ret)
icculus@728
   519
        {
icculus@728
   520
          SetDirectFBerror ("c2layer->GetSurface", ret);
icculus@728
   521
          goto error;
icculus@728
   522
        }
icculus@728
   523
icculus@728
   524
      HIDDEN->c2framesize.x = 0;
icculus@728
   525
      HIDDEN->c2framesize.y = 0;
icculus@728
   526
      HIDDEN->c2frame->GetSize( HIDDEN->c2frame, &HIDDEN->c2framesize.w, &HIDDEN->c2framesize.h);
icculus@728
   527
icculus@728
   528
      HIDDEN->c2frame->SetBlittingFlags( HIDDEN->c2frame, DSBLIT_NOFX );
icculus@728
   529
      HIDDEN->c2frame->SetColor( HIDDEN->c2frame, 0, 0, 0, 0xff );
icculus@728
   530
    
icculus@728
   531
      /* Clear CRTC2 */
icculus@728
   532
      HIDDEN->c2frame->Clear(HIDDEN->c2frame, 0, 0, 0, 0xff );
icculus@728
   533
      HIDDEN->c2frame->Flip(HIDDEN->c2frame, NULL, 0 );
icculus@728
   534
      HIDDEN->c2frame->Clear(HIDDEN->c2frame, 0, 0, 0, 0xff );
icculus@728
   535
      HIDDEN->c2frame->Flip(HIDDEN->c2frame, NULL, 0 );
icculus@728
   536
      HIDDEN->c2frame->Clear(HIDDEN->c2frame, 0, 0, 0, 0xff );
icculus@728
   537
icculus@728
   538
      HIDDEN->c2layer->SetOpacity(HIDDEN->c2layer, 0xFF );
icculus@732
   539
    
icculus@732
   540
      /* Check if overscan is possibly set */
icculus@732
   541
      if (getenv("SDL_DIRECTFB_MGA_OVERSCAN") != NULL)
icculus@732
   542
        {
icculus@732
   543
	    float overscan = 0;
icculus@732
   544
	    if (sscanf(getenv("SDL_DIRECTFB_MGA_OVERSCAN"), "%f", &overscan) == 1)
icculus@732
   545
               if (overscan > 0 && overscan < 2)
icculus@732
   546
		  HIDDEN->mga_crtc2_stretch_overscan = overscan;
icculus@732
   547
	}
icculus@732
   548
icculus@732
   549
      #ifdef DIRECTFB_CRTC2_DEBUG
icculus@732
   550
      printf("CRTC2 overscan: %f\n", HIDDEN->mga_crtc2_stretch_overscan);
icculus@732
   551
      #endif
icculus@728
   552
    }
icculus@728
   553
slouken@167
   554
  return 0;
slouken@464
   555
slouken@464
   556
 error:
slouken@464
   557
  if (events)
slouken@464
   558
    events->Release (events);
slouken@464
   559
  
icculus@728
   560
  if (HIDDEN->c2frame)
icculus@728
   561
    HIDDEN->c2frame->Release (HIDDEN->c2frame);
icculus@728
   562
icculus@728
   563
  if (HIDDEN->c2layer)
icculus@728
   564
    HIDDEN->c2layer->Release (HIDDEN->c2layer);
icculus@728
   565
slouken@464
   566
  if (layer)
slouken@464
   567
    layer->Release (layer);
slouken@464
   568
slouken@464
   569
  if (dfb)
slouken@464
   570
    dfb->Release (dfb);
slouken@464
   571
slouken@464
   572
  return -1;
slouken@167
   573
}
slouken@167
   574
slouken@167
   575
static SDL_Rect **DirectFB_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags)
slouken@167
   576
{
slouken@167
   577
  if (flags & SDL_FULLSCREEN)
slouken@464
   578
    return HIDDEN->modelist;
slouken@167
   579
  else
slouken@167
   580
    if (SDLToDFBPixelFormat (format) != DSPF_UNKNOWN)
slouken@167
   581
      return (SDL_Rect**) -1;
slouken@167
   582
slouken@167
   583
  return NULL;
slouken@167
   584
}
slouken@167
   585
slouken@464
   586
static SDL_Surface *DirectFB_SetVideoMode(_THIS, SDL_Surface *current, int width, int height, int bpp, Uint32 flags)
slouken@167
   587
{
slouken@477
   588
  DFBResult              ret;
slouken@477
   589
  DFBSurfaceDescription  dsc;
slouken@477
   590
  DFBSurfacePixelFormat  pixelformat;
slouken@477
   591
  IDirectFBSurface      *surface;
slouken@167
   592
slouken@167
   593
  fprintf (stderr, "SDL DirectFB_SetVideoMode: %dx%d@%d, flags: 0x%08x\n",
slouken@167
   594
           width, height, bpp, flags);
slouken@167
   595
slouken@167
   596
  flags |= SDL_FULLSCREEN;
slouken@167
   597
slouken@167
   598
  /* Release previous primary surface */
slouken@167
   599
  if (current->hwdata && current->hwdata->surface)
slouken@167
   600
    {
slouken@167
   601
      current->hwdata->surface->Release (current->hwdata->surface);
slouken@167
   602
      current->hwdata->surface = NULL;
slouken@477
   603
slouken@477
   604
      /* And its palette if present */
slouken@477
   605
      if (current->hwdata->palette)
slouken@477
   606
        {
slouken@477
   607
          current->hwdata->palette->Release (current->hwdata->palette);
slouken@477
   608
          current->hwdata->palette = NULL;
slouken@477
   609
        }
slouken@167
   610
    }
slouken@167
   611
  else if (!current->hwdata)
slouken@167
   612
    {
slouken@167
   613
      /* Allocate the hardware acceleration data */
slouken@464
   614
      current->hwdata = (struct private_hwdata *) calloc (1, sizeof(*current->hwdata));
slouken@167
   615
      if (!current->hwdata)
slouken@167
   616
        {
slouken@167
   617
          SDL_OutOfMemory();
slouken@167
   618
          return NULL;
slouken@167
   619
	}
slouken@167
   620
    }
slouken@167
   621
slouken@167
   622
  /* Set cooperative level depending on flag SDL_FULLSCREEN */
slouken@167
   623
  if (flags & SDL_FULLSCREEN)
slouken@167
   624
    {
slouken@167
   625
      ret = HIDDEN->dfb->SetCooperativeLevel (HIDDEN->dfb, DFSCL_FULLSCREEN);
icculus@728
   626
      if (ret && !HIDDEN->enable_mga_crtc2)
slouken@167
   627
        {
slouken@167
   628
          DirectFBError ("dfb->SetCooperativeLevel", ret);
slouken@167
   629
          flags &= ~SDL_FULLSCREEN;
slouken@167
   630
        }
slouken@167
   631
    }
slouken@167
   632
  else
slouken@167
   633
    HIDDEN->dfb->SetCooperativeLevel (HIDDEN->dfb, DFSCL_NORMAL);
slouken@167
   634
slouken@167
   635
  /* Set video mode */
slouken@167
   636
  ret = HIDDEN->dfb->SetVideoMode (HIDDEN->dfb, width, height, bpp);
slouken@167
   637
  if (ret)
slouken@167
   638
    {
slouken@167
   639
      if (flags & SDL_FULLSCREEN)
slouken@167
   640
        {
slouken@167
   641
          flags &= ~SDL_FULLSCREEN;
slouken@167
   642
          HIDDEN->dfb->SetCooperativeLevel (HIDDEN->dfb, DFSCL_NORMAL);
slouken@167
   643
          ret = HIDDEN->dfb->SetVideoMode (HIDDEN->dfb, width, height, bpp);
slouken@167
   644
        }
slouken@167
   645
slouken@167
   646
      if (ret)
slouken@167
   647
        {
slouken@167
   648
          SetDirectFBerror ("dfb->SetVideoMode", ret);
slouken@167
   649
          return NULL;
slouken@167
   650
        }
slouken@167
   651
    }
slouken@167
   652
slouken@167
   653
  /* Create primary surface */
slouken@464
   654
  dsc.flags       = DSDESC_CAPS | DSDESC_PIXELFORMAT;
slouken@464
   655
  dsc.caps        = DSCAPS_PRIMARY | ((flags & SDL_DOUBLEBUF) ? DSCAPS_FLIPPING : 0);
slouken@464
   656
  dsc.pixelformat = GetFormatForBpp (bpp, HIDDEN->layer);
slouken@167
   657
slouken@477
   658
  ret = HIDDEN->dfb->CreateSurface (HIDDEN->dfb, &dsc, &surface);
slouken@167
   659
  if (ret && (flags & SDL_DOUBLEBUF))
slouken@167
   660
    {
slouken@167
   661
      /* Try without double buffering */
slouken@167
   662
      dsc.caps &= ~DSCAPS_FLIPPING;
slouken@477
   663
      ret = HIDDEN->dfb->CreateSurface (HIDDEN->dfb, &dsc, &surface);
slouken@167
   664
    }
slouken@167
   665
  if (ret)
slouken@167
   666
    {
slouken@167
   667
      SetDirectFBerror ("dfb->CreateSurface", ret);
slouken@167
   668
      return NULL;
slouken@167
   669
    }
slouken@167
   670
slouken@167
   671
  current->w     = width;
slouken@167
   672
  current->h     = height;
slouken@167
   673
  current->flags = SDL_HWSURFACE | SDL_PREALLOC;
slouken@167
   674
slouken@167
   675
  if (flags & SDL_FULLSCREEN)
slouken@167
   676
    {
slouken@167
   677
      current->flags |= SDL_FULLSCREEN;
slouken@167
   678
      this->UpdateRects = DirectFB_DirectUpdate;
slouken@167
   679
    }
slouken@167
   680
  else
slouken@167
   681
    this->UpdateRects = DirectFB_WindowedUpdate;
slouken@167
   682
slouken@167
   683
  if (dsc.caps & DSCAPS_FLIPPING)
slouken@167
   684
    current->flags |= SDL_DOUBLEBUF;
slouken@167
   685
slouken@477
   686
  surface->GetPixelFormat (surface, &pixelformat);
slouken@477
   687
slouken@167
   688
  DFBToSDLPixelFormat (pixelformat, current->format);
slouken@167
   689
slouken@477
   690
  /* Get the surface palette (if supported) */
slouken@477
   691
  if (DFB_PIXELFORMAT_IS_INDEXED( pixelformat ))
slouken@477
   692
    {
slouken@477
   693
      surface->GetPalette (surface, &current->hwdata->palette);
slouken@477
   694
slouken@477
   695
      current->flags |= SDL_HWPALETTE;
slouken@477
   696
    }
slouken@477
   697
slouken@477
   698
  current->hwdata->surface = surface;
slouken@477
   699
icculus@728
   700
  /* MGA CRTC2 stuff */
icculus@728
   701
  if (HIDDEN->enable_mga_crtc2)
icculus@728
   702
    {
icculus@728
   703
      /* no stretching if c2ssize == c2framesize */
icculus@728
   704
      HIDDEN->c2ssize.x = 0, HIDDEN->c2ssize.y = 0;
icculus@728
   705
      HIDDEN->c2ssize.w = width;
icculus@728
   706
      HIDDEN->c2ssize.h = height;
icculus@728
   707
icculus@728
   708
      HIDDEN->c2dsize.x = 0, HIDDEN->c2dsize.y = 0;
icculus@728
   709
      HIDDEN->c2dsize.w = width;
icculus@728
   710
      HIDDEN->c2dsize.h = height;
icculus@728
   711
icculus@728
   712
      HIDDEN->mga_crtc2_stretch = 0;
icculus@728
   713
icculus@728
   714
      if (getenv("SDL_DIRECTFB_MGA_STRETCH") != NULL)
icculus@728
   715
        {
icculus@732
   716
	    /* Normally assume a picture aspect ratio of 4:3 */
icculus@732
   717
	    int zoom_aspect_x = 4, zoom_aspect_y = 3, i, j;
icculus@732
   718
icculus@732
   719
	    for (i = 1; i < 20; i++)
icculus@732
   720
	      {
icculus@732
   721
		for (j = 1; j < 10; j++)
icculus@732
   722
		  {
icculus@732
   723
		    if ((float)width/(float)i*(float)j == height) 
icculus@732
   724
		      {
icculus@732
   725
			zoom_aspect_x = i;
icculus@732
   726
			zoom_aspect_y = j;
icculus@732
   727
			
icculus@732
   728
			/* break the loop */
icculus@732
   729
			i = 21;
icculus@732
   730
			break;
icculus@732
   731
		      }
icculus@732
   732
		  }
icculus@732
   733
	      }
icculus@732
   734
	
icculus@732
   735
            #ifdef DIRECTFB_CRTC2_DEBUG
icculus@732
   736
            printf("Source resolution: X: %d, Y: %d, Aspect ratio: %d:%d\n", width, height, zoom_aspect_x, zoom_aspect_y);
icculus@732
   737
            printf("CRTC2 resolution: X: %d, Y: %d\n", HIDDEN->c2framesize.w, HIDDEN->c2framesize.h);
icculus@732
   738
            #endif
icculus@732
   739
	
icculus@732
   740
          /* don't stretch only slightly smaller/larger images */
icculus@732
   741
          if ((float)width < (float)HIDDEN->c2framesize.w*0.95 || (float)height < (float)HIDDEN->c2framesize.h*0.95)
icculus@728
   742
            {
icculus@732
   743
              while ((float)HIDDEN->c2dsize.w < (float)HIDDEN->c2framesize.w*HIDDEN->mga_crtc2_stretch_overscan && (float)HIDDEN->c2dsize.h < (float)HIDDEN->c2framesize.h*HIDDEN->mga_crtc2_stretch_overscan)
icculus@728
   744
                {
icculus@732
   745
                   HIDDEN->c2dsize.w+=zoom_aspect_x;
icculus@732
   746
                   HIDDEN->c2dsize.h+=zoom_aspect_y;
icculus@728
   747
                }
icculus@728
   748
icculus@728
   749
              /* one step down */
icculus@732
   750
                HIDDEN->c2dsize.w-=zoom_aspect_x;
icculus@732
   751
                HIDDEN->c2dsize.h-=zoom_aspect_y;
icculus@728
   752
icculus@728
   753
              #ifdef DIRECTFB_CRTC2_DEBUG
icculus@728
   754
              printf("Stretched resolution: X: %d, Y: %d\n", HIDDEN->c2dsize.w, HIDDEN->c2dsize.h);
icculus@728
   755
              #endif
icculus@728
   756
icculus@728
   757
              HIDDEN->mga_crtc2_stretch = 1;
icculus@728
   758
            } 
icculus@732
   759
          else if ((float)width > (float)HIDDEN->c2framesize.w*0.95 || (float)height > (float)HIDDEN->c2framesize.h*0.95)
icculus@728
   760
            {
icculus@732
   761
               while ((float)HIDDEN->c2dsize.w > (float)HIDDEN->c2framesize.w*HIDDEN->mga_crtc2_stretch_overscan || (float)HIDDEN->c2dsize.h > (float)HIDDEN->c2framesize.h*HIDDEN->mga_crtc2_stretch_overscan)
icculus@728
   762
                {
icculus@732
   763
              HIDDEN->c2dsize.w-=zoom_aspect_x;
icculus@732
   764
              HIDDEN->c2dsize.h-=zoom_aspect_y;
icculus@728
   765
                }
icculus@728
   766
              
icculus@728
   767
              #ifdef DIRECTFB_CRTC2_DEBUG
icculus@728
   768
              printf("Down-Stretched resolution: X: %d, Y: %d\n", HIDDEN->c2dsize.w, HIDDEN->c2dsize.h);
icculus@728
   769
              #endif
icculus@728
   770
icculus@728
   771
              HIDDEN->mga_crtc2_stretch = 1;
icculus@732
   772
             } else {
icculus@732
   773
          #ifdef DIRECTFB_CRTC2_DEBUG
icculus@732
   774
          printf("Not stretching image\n");
icculus@732
   775
          #endif
icculus@728
   776
        }
icculus@728
   777
icculus@728
   778
      /* Panning */
icculus@728
   779
      if (HIDDEN->c2framesize.w > HIDDEN->c2dsize.w)
icculus@728
   780
        HIDDEN->c2dsize.x = (HIDDEN->c2framesize.w - HIDDEN->c2dsize.w)  / 2;
icculus@728
   781
      else
icculus@728
   782
        HIDDEN->c2dsize.x = (HIDDEN->c2dsize.w - HIDDEN->c2framesize.w)  / 2;
icculus@728
   783
icculus@728
   784
      if (HIDDEN->c2framesize.h > HIDDEN->c2dsize.h)
icculus@728
   785
        HIDDEN->c2dsize.y = (HIDDEN->c2framesize.h - HIDDEN->c2dsize.h)  / 2;
icculus@728
   786
      else
icculus@728
   787
        HIDDEN->c2dsize.y = (HIDDEN->c2dsize.h - HIDDEN->c2framesize.h)  / 2;
icculus@728
   788
icculus@728
   789
      #ifdef DIRECTFB_CRTC2_DEBUG
icculus@732
   790
    printf("CRTC2 position X: %d, Y: %d\n", HIDDEN->c2dsize.x, HIDDEN->c2dsize.y);
icculus@728
   791
      #endif
icculus@728
   792
   }
icculus@732
   793
  }
icculus@728
   794
slouken@167
   795
  return current;
slouken@167
   796
}
slouken@167
   797
slouken@167
   798
static int DirectFB_AllocHWSurface(_THIS, SDL_Surface *surface)
slouken@167
   799
{
slouken@167
   800
  DFBResult             ret;
slouken@167
   801
  DFBSurfaceDescription dsc;
slouken@167
   802
slouken@167
   803
  /*  fprintf(stderr, "SDL: DirectFB_AllocHWSurface (%dx%d@%d, flags: 0x%08x)\n",
slouken@167
   804
      surface->w, surface->h, surface->format->BitsPerPixel, surface->flags);*/
slouken@167
   805
slouken@167
   806
  if (surface->w < 8 || surface->h < 8)
slouken@167
   807
    return -1;
slouken@167
   808
slouken@167
   809
  /* fill surface description */
slouken@167
   810
  dsc.flags  = DSDESC_WIDTH | DSDESC_HEIGHT | DSDESC_PIXELFORMAT | DSDESC_CAPS;
slouken@167
   811
  dsc.width  = surface->w;
slouken@167
   812
  dsc.height = surface->h;
slouken@464
   813
  dsc.caps   = (surface->flags & SDL_DOUBLEBUF) ? DSCAPS_FLIPPING : 0;
slouken@167
   814
slouken@167
   815
  /* find the right pixelformat */
slouken@167
   816
  dsc.pixelformat = SDLToDFBPixelFormat (surface->format);
slouken@167
   817
  if (dsc.pixelformat == DSPF_UNKNOWN)
slouken@167
   818
    return -1;
slouken@167
   819
slouken@167
   820
  /* Allocate the hardware acceleration data */
slouken@464
   821
  surface->hwdata = (struct private_hwdata *) calloc (1, sizeof(*surface->hwdata));
slouken@167
   822
  if (surface->hwdata == NULL)
slouken@167
   823
    {
slouken@167
   824
      SDL_OutOfMemory();
slouken@167
   825
      return -1;
slouken@167
   826
    }
slouken@167
   827
slouken@167
   828
  /* Create the surface */
slouken@167
   829
  ret = HIDDEN->dfb->CreateSurface (HIDDEN->dfb, &dsc, &surface->hwdata->surface);
slouken@167
   830
  if (ret)
slouken@167
   831
    {
slouken@167
   832
      SetDirectFBerror ("dfb->CreateSurface", ret);
slouken@167
   833
      free (surface->hwdata);
slouken@167
   834
      surface->hwdata = NULL;
slouken@167
   835
      return -1;
slouken@167
   836
    }
slouken@167
   837
slouken@167
   838
  surface->flags |= SDL_HWSURFACE | SDL_PREALLOC;
slouken@167
   839
slouken@167
   840
  return 0;
slouken@167
   841
}
slouken@167
   842
slouken@167
   843
static void DirectFB_FreeHWSurface(_THIS, SDL_Surface *surface)
slouken@167
   844
{
slouken@167
   845
  if (surface->hwdata && HIDDEN->initialized)
slouken@167
   846
    {
slouken@167
   847
      surface->hwdata->surface->Release (surface->hwdata->surface);
slouken@167
   848
      free (surface->hwdata);
slouken@167
   849
      surface->hwdata = NULL;
slouken@167
   850
    }
slouken@167
   851
}
slouken@167
   852
slouken@167
   853
static int DirectFB_CheckHWBlit(_THIS, SDL_Surface *src, SDL_Surface *dst)
slouken@167
   854
{
slouken@167
   855
  /*  fprintf(stderr, "SDL: DirectFB_CheckHWBlit (src->hwdata: %p, dst->hwdata: %p)\n",
slouken@167
   856
      src->hwdata, dst->hwdata);*/
slouken@167
   857
slouken@167
   858
  if (!src->hwdata || !dst->hwdata)
slouken@167
   859
    return 0;
slouken@167
   860
slouken@167
   861
  src->flags |= SDL_HWACCEL;
slouken@167
   862
  src->map->hw_blit = DirectFB_HWAccelBlit;
slouken@167
   863
slouken@167
   864
  return 1;
slouken@167
   865
}
slouken@167
   866
slouken@167
   867
static int DirectFB_HWAccelBlit(SDL_Surface *src, SDL_Rect *srcrect,
slouken@167
   868
                                SDL_Surface *dst, SDL_Rect *dstrect)
slouken@167
   869
{
slouken@464
   870
  DFBSurfaceBlittingFlags flags = DSBLIT_NOFX;
slouken@167
   871
slouken@464
   872
  DFBRectangle sr = { srcrect->x, srcrect->y, srcrect->w, srcrect->h };
slouken@464
   873
  DFBRectangle dr = { dstrect->x, dstrect->y, dstrect->w, dstrect->h };
slouken@167
   874
slouken@464
   875
  IDirectFBSurface *surface = dst->hwdata->surface;
slouken@167
   876
slouken@167
   877
  if (src->flags & SDL_SRCCOLORKEY)
slouken@167
   878
    {
slouken@167
   879
      flags |= DSBLIT_SRC_COLORKEY;
slouken@219
   880
      DirectFB_SetHWColorKey (NULL, src, src->format->colorkey);
slouken@167
   881
    }
slouken@167
   882
slouken@167
   883
  if (src->flags & SDL_SRCALPHA)
slouken@167
   884
    {
slouken@167
   885
      flags |= DSBLIT_BLEND_COLORALPHA;
slouken@167
   886
      surface->SetColor (surface, 0xff, 0xff, 0xff, src->format->alpha);
slouken@167
   887
    }
slouken@167
   888
slouken@167
   889
  surface->SetBlittingFlags (surface, flags);
slouken@167
   890
slouken@167
   891
  if (sr.w == dr.w && sr.h == dr.h)
slouken@167
   892
    surface->Blit (surface, src->hwdata->surface, &sr, dr.x, dr.y);
slouken@167
   893
  else
slouken@167
   894
    surface->StretchBlit (surface, src->hwdata->surface, &sr, &dr);
slouken@167
   895
slouken@167
   896
  return 0;
slouken@167
   897
}
slouken@167
   898
slouken@167
   899
static int DirectFB_FillHWRect(_THIS, SDL_Surface *dst, SDL_Rect *dstrect, Uint32 color)
slouken@167
   900
{
slouken@167
   901
  SDL_PixelFormat  *fmt     = dst->format;
slouken@167
   902
  IDirectFBSurface *surface = dst->hwdata->surface;
slouken@167
   903
slouken@167
   904
  /* ugly */
slouken@167
   905
  surface->SetColor (surface,
slouken@167
   906
                     (color & fmt->Rmask) >> (fmt->Rshift - fmt->Rloss),
slouken@167
   907
                     (color & fmt->Gmask) >> (fmt->Gshift - fmt->Gloss),
slouken@167
   908
                     (color & fmt->Bmask) << (fmt->Bloss - fmt->Bshift), 0xFF);
slouken@167
   909
  surface->FillRectangle (surface, dstrect->x, dstrect->y, dstrect->w, dstrect->h);
slouken@167
   910
slouken@167
   911
  return 0;
slouken@167
   912
}
slouken@167
   913
slouken@219
   914
static int DirectFB_SetHWColorKey(_THIS, SDL_Surface *src, Uint32 key)
slouken@167
   915
{
slouken@219
   916
  SDL_PixelFormat  *fmt     = src->format;
slouken@219
   917
  IDirectFBSurface *surface = src->hwdata->surface;
slouken@219
   918
slouken@477
   919
  if (fmt->BitsPerPixel == 8)
slouken@477
   920
    surface->SetSrcColorKeyIndex (surface, key);
slouken@477
   921
  else
slouken@477
   922
    /* ugly */
slouken@477
   923
    surface->SetSrcColorKey (surface,
slouken@477
   924
                             (key & fmt->Rmask) >> (fmt->Rshift - fmt->Rloss),
slouken@477
   925
                             (key & fmt->Gmask) >> (fmt->Gshift - fmt->Gloss),
slouken@477
   926
                             (key & fmt->Bmask) << (fmt->Bloss - fmt->Bshift));
slouken@219
   927
slouken@167
   928
  return 0;
slouken@167
   929
}
slouken@167
   930
slouken@167
   931
static int DirectFB_SetHWAlpha(_THIS, SDL_Surface *surface, Uint8 alpha)
slouken@167
   932
{
slouken@167
   933
  return 0;
slouken@167
   934
}
slouken@167
   935
slouken@167
   936
static int DirectFB_FlipHWSurface(_THIS, SDL_Surface *surface)
slouken@167
   937
{
icculus@728
   938
  if (HIDDEN->enable_mga_crtc2)
icculus@728
   939
    {
icculus@728
   940
       int rtn = surface->hwdata->surface->Flip (surface->hwdata->surface, NULL, 0);
icculus@728
   941
       if (HIDDEN->mga_crtc2_stretch)
icculus@728
   942
         HIDDEN->c2frame->StretchBlit(HIDDEN->c2frame, surface->hwdata->surface, &HIDDEN->c2ssize, &HIDDEN->c2dsize);
icculus@728
   943
       else
icculus@728
   944
         HIDDEN->c2frame->Blit(HIDDEN->c2frame, surface->hwdata->surface, NULL, HIDDEN->c2dsize.x, HIDDEN->c2dsize.y);
icculus@728
   945
     
icculus@728
   946
       HIDDEN->c2frame->Flip(HIDDEN->c2frame, NULL, DSFLIP_WAITFORSYNC);
icculus@728
   947
       return rtn;
icculus@728
   948
    } 
icculus@728
   949
  else 
icculus@728
   950
     return surface->hwdata->surface->Flip (surface->hwdata->surface, NULL, DSFLIP_WAITFORSYNC);
slouken@167
   951
}
slouken@167
   952
slouken@167
   953
static int DirectFB_LockHWSurface(_THIS, SDL_Surface *surface)
slouken@167
   954
{
slouken@167
   955
  DFBResult  ret;
slouken@167
   956
  void      *data;
slouken@167
   957
  int        pitch;
slouken@167
   958
slouken@167
   959
  ret = surface->hwdata->surface->Lock (surface->hwdata->surface,
slouken@167
   960
                                        DSLF_WRITE, &data, &pitch);
slouken@167
   961
  if (ret)
slouken@167
   962
    {
slouken@167
   963
      SetDirectFBerror ("surface->Lock", ret);
slouken@167
   964
      return -1;
slouken@167
   965
    }
slouken@167
   966
slouken@167
   967
  surface->pixels = data;
slouken@167
   968
  surface->pitch  = pitch;
slouken@167
   969
slouken@167
   970
  return 0;
slouken@167
   971
}
slouken@167
   972
slouken@167
   973
static void DirectFB_UnlockHWSurface(_THIS, SDL_Surface *surface)
slouken@167
   974
{
slouken@167
   975
  surface->hwdata->surface->Unlock (surface->hwdata->surface);
slouken@167
   976
  surface->pixels = NULL;
slouken@167
   977
}
slouken@167
   978
slouken@167
   979
static void DirectFB_DirectUpdate(_THIS, int numrects, SDL_Rect *rects)
slouken@167
   980
{
icculus@728
   981
  if (HIDDEN->enable_mga_crtc2)
icculus@728
   982
    {
icculus@728
   983
       if (HIDDEN->mga_crtc2_stretch)
icculus@728
   984
         HIDDEN->c2frame->StretchBlit(HIDDEN->c2frame, this->screen->hwdata->surface, &HIDDEN->c2ssize, &HIDDEN->c2dsize); 
icculus@728
   985
       else
icculus@728
   986
         HIDDEN->c2frame->Blit(HIDDEN->c2frame, this->screen->hwdata->surface, NULL, HIDDEN->c2dsize.x, HIDDEN->c2dsize.y); 
icculus@728
   987
icculus@728
   988
       HIDDEN->c2frame->Flip(HIDDEN->c2frame, NULL, DSFLIP_WAITFORSYNC);
icculus@728
   989
    }
slouken@167
   990
}
slouken@167
   991
slouken@167
   992
static void DirectFB_WindowedUpdate(_THIS, int numrects, SDL_Rect *rects)
slouken@167
   993
{
slouken@286
   994
  DFBRegion         region;
slouken@286
   995
  int               i;
slouken@286
   996
  int               region_valid = 0;
slouken@167
   997
  IDirectFBSurface *surface = this->screen->hwdata->surface;
slouken@167
   998
slouken@286
   999
  for (i=0; i<numrects; ++i)
slouken@167
  1000
    {
slouken@167
  1001
      int x2, y2;
slouken@167
  1002
slouken@286
  1003
      if ( ! rects[i].w ) /* Clipped? */
slouken@286
  1004
        continue;
slouken@286
  1005
slouken@286
  1006
      x2 = rects[i].x + rects[i].w - 1;
slouken@286
  1007
      y2 = rects[i].y + rects[i].h - 1;
slouken@167
  1008
slouken@286
  1009
      if (region_valid)
slouken@286
  1010
        {
slouken@286
  1011
          if (rects[i].x < region.x1)
slouken@286
  1012
            region.x1 = rects[i].x;
slouken@167
  1013
slouken@286
  1014
          if (rects[i].y < region.y1)
slouken@286
  1015
            region.y1 = rects[i].y;
slouken@167
  1016
slouken@286
  1017
          if (x2 > region.x2)
slouken@286
  1018
            region.x2 = x2;
slouken@167
  1019
slouken@286
  1020
          if (y2 > region.y2)
slouken@286
  1021
            region.y2 = y2;
slouken@286
  1022
        }
slouken@286
  1023
      else
slouken@286
  1024
        {
slouken@286
  1025
            region.x1 = rects[i].x;
slouken@286
  1026
            region.y1 = rects[i].y;
slouken@286
  1027
            region.x2 = x2;
slouken@286
  1028
            region.y2 = y2;
slouken@167
  1029
slouken@286
  1030
            region_valid = 1;
slouken@286
  1031
        }
slouken@167
  1032
    }
slouken@167
  1033
slouken@286
  1034
  if (region_valid)
icculus@728
  1035
    {
icculus@728
  1036
      if (HIDDEN->enable_mga_crtc2)
icculus@728
  1037
        {
icculus@728
  1038
          if (HIDDEN->mga_crtc2_stretch)
icculus@728
  1039
            HIDDEN->c2frame->StretchBlit(HIDDEN->c2frame, surface, &HIDDEN->c2ssize, &HIDDEN->c2dsize);
icculus@728
  1040
          else
icculus@728
  1041
            HIDDEN->c2frame->Blit(HIDDEN->c2frame, surface, NULL, HIDDEN->c2dsize.x, HIDDEN->c2dsize.y); 
icculus@728
  1042
      
icculus@728
  1043
          HIDDEN->c2frame->Flip(HIDDEN->c2frame, NULL, DSFLIP_WAITFORSYNC);
icculus@728
  1044
        }
icculus@728
  1045
      else 
icculus@728
  1046
        surface->Flip (surface, &region, DSFLIP_WAITFORSYNC);
icculus@728
  1047
    }
slouken@167
  1048
}
slouken@167
  1049
slouken@167
  1050
int DirectFB_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors)
slouken@167
  1051
{
slouken@477
  1052
  IDirectFBPalette *palette = this->screen->hwdata->palette;
slouken@477
  1053
slouken@477
  1054
  if (!palette)
slouken@477
  1055
    return 0;
slouken@477
  1056
slouken@477
  1057
  if (firstcolor > 255)
slouken@477
  1058
    return 0;
slouken@477
  1059
slouken@477
  1060
  if (firstcolor + ncolors > 256)
slouken@477
  1061
    ncolors = 256 - firstcolor;
slouken@477
  1062
slouken@477
  1063
  if (ncolors > 0)
slouken@477
  1064
    {
slouken@477
  1065
      int      i;
slouken@477
  1066
      DFBColor entries[ncolors];
slouken@477
  1067
slouken@477
  1068
      for (i=0; i<ncolors; i++)
slouken@477
  1069
        {
slouken@477
  1070
          entries[i].a = 0xff;
slouken@477
  1071
          entries[i].r = colors[i].r;
slouken@477
  1072
          entries[i].g = colors[i].g;
slouken@477
  1073
          entries[i].b = colors[i].b;
slouken@477
  1074
        }
slouken@477
  1075
slouken@477
  1076
      palette->SetEntries (palette, entries, ncolors, firstcolor);
slouken@477
  1077
    }
slouken@477
  1078
slouken@477
  1079
  return 1;
slouken@167
  1080
}
slouken@167
  1081
	
slouken@167
  1082
void DirectFB_VideoQuit(_THIS)
slouken@167
  1083
{
slouken@477
  1084
  struct DirectFBEnumRect *rect    = enumlist;
icculus@759
  1085
icculus@759
  1086
  if (this->screen->hwdata)
icculus@759
  1087
    {
icculus@759
  1088
      IDirectFBSurface        *surface = this->screen->hwdata->surface;
icculus@759
  1089
      IDirectFBPalette        *palette = this->screen->hwdata->palette;
slouken@477
  1090
icculus@759
  1091
      if (palette)
icculus@759
  1092
        palette->Release (palette);
slouken@477
  1093
icculus@759
  1094
      if (surface)
icculus@759
  1095
        surface->Release (surface);
icculus@759
  1096
icculus@759
  1097
      this->screen->hwdata->surface = NULL;
icculus@759
  1098
      this->screen->hwdata->palette = NULL;
icculus@759
  1099
    }
slouken@477
  1100
icculus@728
  1101
  if (HIDDEN->c2frame)
icculus@728
  1102
    {
icculus@728
  1103
      HIDDEN->c2frame->Release (HIDDEN->c2frame);
icculus@728
  1104
      HIDDEN->c2frame = NULL;
icculus@728
  1105
    }
icculus@728
  1106
slouken@477
  1107
  this->screen->hwdata->surface = NULL;
slouken@477
  1108
  this->screen->hwdata->palette = NULL;
slouken@464
  1109
slouken@464
  1110
  if (HIDDEN->eventbuffer)
slouken@464
  1111
    {
slouken@464
  1112
      HIDDEN->eventbuffer->Release (HIDDEN->eventbuffer);
slouken@464
  1113
      HIDDEN->eventbuffer = NULL;
slouken@464
  1114
    }
slouken@167
  1115
icculus@728
  1116
  if (HIDDEN->c2layer)
icculus@728
  1117
    {
icculus@728
  1118
      HIDDEN->c2layer->Release (HIDDEN->c2layer);
icculus@728
  1119
      HIDDEN->c2layer = NULL;
icculus@728
  1120
    }
icculus@728
  1121
slouken@464
  1122
  if (HIDDEN->layer)
slouken@464
  1123
    {
slouken@464
  1124
      HIDDEN->layer->Release (HIDDEN->layer);
slouken@464
  1125
      HIDDEN->layer = NULL;
slouken@464
  1126
    }
slouken@167
  1127
slouken@464
  1128
  if (HIDDEN->dfb)
slouken@167
  1129
    {
slouken@464
  1130
      HIDDEN->dfb->Release (HIDDEN->dfb);
slouken@464
  1131
      HIDDEN->dfb = NULL;
slouken@464
  1132
    }
slouken@464
  1133
slouken@464
  1134
  /* Free video mode list */
slouken@464
  1135
  if (HIDDEN->modelist)
slouken@464
  1136
    {
slouken@464
  1137
      free (HIDDEN->modelist);
slouken@464
  1138
      HIDDEN->modelist = NULL;
slouken@167
  1139
    }
slouken@167
  1140
slouken@464
  1141
  /* Free mode enumeration list */
slouken@464
  1142
  while (rect)
slouken@464
  1143
    {
slouken@464
  1144
      struct DirectFBEnumRect *next = rect->next;
slouken@464
  1145
      free (rect);
slouken@464
  1146
      rect = next;
slouken@464
  1147
    }
slouken@464
  1148
  enumlist = NULL;
slouken@464
  1149
slouken@167
  1150
  HIDDEN->initialized = 0;
slouken@167
  1151
}
slouken@167
  1152
slouken@767
  1153
slouken@767
  1154
int DirectFB_ShowWMCursor(_THIS, WMcursor *cursor)
slouken@767
  1155
{
slouken@767
  1156
  /* We can only hide or show the default cursor */
slouken@767
  1157
  if ( cursor == NULL )
slouken@767
  1158
    {
slouken@767
  1159
      SetCursorOpacity(HIDDEN->layer, 0);
slouken@767
  1160
    }
slouken@767
  1161
    else
slouken@767
  1162
    {
slouken@767
  1163
      SetCursorOpacity(HIDDEN->layer, 256);
slouken@767
  1164
    }
slouken@767
  1165
  return 1;
slouken@767
  1166
}
slouken@767
  1167
slouken@167
  1168
void DirectFB_FinalQuit(void) 
slouken@167
  1169
{
slouken@167
  1170
}