src/video/vgl/SDL_vglvideo.c
author Edgar Simo <bobbens@gmail.com>
Sun, 06 Jul 2008 17:06:37 +0000
branchgsoc2008_force_feedback
changeset 2498 ab567bd667bf
parent 1895 c121d94672cb
child 2698 e1da92da346c
permissions -rw-r--r--
Fixed various mistakes in the doxygen.
slouken@75
     1
/*
slouken@75
     2
    SDL - Simple DirectMedia Layer
slouken@1312
     3
    Copyright (C) 1997-2006 Sam Lantinga
slouken@75
     4
slouken@75
     5
    This library is free software; you can redistribute it and/or
slouken@1312
     6
    modify it under the terms of the GNU Lesser General Public
slouken@75
     7
    License as published by the Free Software Foundation; either
slouken@1312
     8
    version 2.1 of the License, or (at your option) any later version.
slouken@75
     9
slouken@75
    10
    This library is distributed in the hope that it will be useful,
slouken@75
    11
    but WITHOUT ANY WARRANTY; without even the implied warranty of
slouken@75
    12
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
slouken@1312
    13
    Lesser General Public License for more details.
slouken@75
    14
slouken@1312
    15
    You should have received a copy of the GNU Lesser General Public
slouken@1312
    16
    License along with this library; if not, write to the Free Software
slouken@1312
    17
    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
slouken@75
    18
slouken@75
    19
    Sam Lantinga
slouken@252
    20
    slouken@libsdl.org
slouken@75
    21
*/
slouken@1402
    22
#include "SDL_config.h"
slouken@75
    23
slouken@75
    24
/* libvga based SDL video driver implementation.
slouken@75
    25
*/
slouken@75
    26
slouken@75
    27
#include <err.h>
slouken@75
    28
#include <osreldate.h>
slouken@75
    29
#include <unistd.h>
slouken@75
    30
#include <sys/stat.h>
slouken@75
    31
slouken@75
    32
#include <sys/fbio.h>
slouken@75
    33
#include <sys/consio.h>
slouken@75
    34
#include <sys/kbio.h>
slouken@75
    35
#include <vgl.h>
slouken@75
    36
slouken@75
    37
#include "SDL_video.h"
slouken@75
    38
#include "SDL_mouse.h"
slouken@1361
    39
#include "../SDL_sysvideo.h"
slouken@1361
    40
#include "../SDL_pixels_c.h"
slouken@1361
    41
#include "../../events/SDL_events_c.h"
slouken@75
    42
#include "SDL_vglvideo.h"
slouken@75
    43
#include "SDL_vglevents_c.h"
slouken@75
    44
#include "SDL_vglmouse_c.h"
slouken@75
    45
slouken@75
    46
slouken@75
    47
/* Initialization/Query functions */
slouken@1895
    48
static int VGL_VideoInit(_THIS, SDL_PixelFormat * vformat);
slouken@1895
    49
static SDL_Rect **VGL_ListModes(_THIS, SDL_PixelFormat * format,
slouken@1895
    50
                                Uint32 flags);
slouken@1895
    51
static SDL_Surface *VGL_SetVideoMode(_THIS, SDL_Surface * current, int width,
slouken@1895
    52
                                     int height, int bpp, Uint32 flags);
slouken@75
    53
static int VGL_SetColors(_THIS, int firstcolor, int ncolors,
slouken@1895
    54
                         SDL_Color * colors);
slouken@75
    55
static void VGL_VideoQuit(_THIS);
slouken@75
    56
slouken@75
    57
/* Hardware surface functions */
slouken@1895
    58
static int VGL_AllocHWSurface(_THIS, SDL_Surface * surface);
slouken@1895
    59
static int VGL_LockHWSurface(_THIS, SDL_Surface * surface);
slouken@1895
    60
static int VGL_FlipHWSurface(_THIS, SDL_Surface * surface);
slouken@1895
    61
static void VGL_UnlockHWSurface(_THIS, SDL_Surface * surface);
slouken@1895
    62
static void VGL_FreeHWSurface(_THIS, SDL_Surface * surface);
slouken@75
    63
slouken@75
    64
/* Misc function */
slouken@1895
    65
static VGLMode **VGLListModes(int depth, int mem_model);
slouken@75
    66
static void VGLWaitRetrace(void);
slouken@75
    67
slouken@75
    68
/* VGL driver bootstrap functions */
slouken@75
    69
slouken@1895
    70
static int
slouken@1895
    71
VGL_Available(void)
slouken@75
    72
{
slouken@1895
    73
    /*
slouken@1895
    74
     * Check to see if we are root and stdin is a
slouken@1895
    75
     * virtual console. Also try to ensure that
slouken@1895
    76
     * modes other than 320x200 are available
slouken@1895
    77
     */
slouken@1895
    78
    int console, hires_available, i;
slouken@1895
    79
    VGLMode **modes;
slouken@75
    80
slouken@1895
    81
    console = STDIN_FILENO;
slouken@1895
    82
    if (console >= 0) {
slouken@1895
    83
        struct stat sb;
slouken@1895
    84
        struct vt_mode dummy;
slouken@75
    85
slouken@1895
    86
        if ((fstat(console, &sb) < 0) ||
slouken@1895
    87
            (ioctl(console, VT_GETMODE, &dummy) < 0)) {
slouken@1895
    88
            console = -1;
slouken@1895
    89
        }
slouken@1895
    90
    }
slouken@1895
    91
    if (geteuid() != 0 && console == -1)
slouken@1895
    92
        return 0;
slouken@75
    93
slouken@1895
    94
    modes = VGLListModes(8, V_INFO_MM_DIRECT | V_INFO_MM_PACKED);
slouken@1895
    95
    hires_available = 0;
slouken@1895
    96
    for (i = 0; modes[i] != NULL; i++) {
slouken@1895
    97
        if ((modes[i]->ModeInfo.Xsize > 320) &&
slouken@1895
    98
            (modes[i]->ModeInfo.Ysize > 200) &&
slouken@1895
    99
            ((modes[i]->ModeInfo.Type == VIDBUF8) ||
slouken@1895
   100
             (modes[i]->ModeInfo.Type == VIDBUF16) ||
slouken@1895
   101
             (modes[i]->ModeInfo.Type == VIDBUF32))) {
slouken@1895
   102
            hires_available = 1;
slouken@1895
   103
            break;
slouken@1895
   104
        }
slouken@1895
   105
    }
slouken@1895
   106
    return hires_available;
slouken@75
   107
}
slouken@75
   108
slouken@1895
   109
static void
slouken@1895
   110
VGL_DeleteDevice(SDL_VideoDevice * device)
slouken@75
   111
{
slouken@1895
   112
    SDL_free(device->hidden);
slouken@1895
   113
    SDL_free(device);
slouken@75
   114
}
slouken@75
   115
slouken@1895
   116
static SDL_VideoDevice *
slouken@1895
   117
VGL_CreateDevice(int devindex)
slouken@75
   118
{
slouken@1895
   119
    SDL_VideoDevice *device;
slouken@75
   120
slouken@1895
   121
    /* Initialize all variables that we clean on shutdown */
slouken@1895
   122
    device = (SDL_VideoDevice *) SDL_malloc(sizeof(SDL_VideoDevice));
slouken@1895
   123
    if (device) {
slouken@1895
   124
        SDL_memset(device, 0, (sizeof *device));
slouken@1895
   125
        device->hidden = (struct SDL_PrivateVideoData *)
slouken@1895
   126
            SDL_malloc((sizeof *device->hidden));
slouken@1895
   127
    }
slouken@1895
   128
    if ((device == NULL) || (device->hidden == NULL)) {
slouken@1895
   129
        SDL_OutOfMemory();
slouken@1895
   130
        if (device) {
slouken@1895
   131
            SDL_free(device);
slouken@1895
   132
        }
slouken@1895
   133
        return (0);
slouken@1895
   134
    }
slouken@1895
   135
    SDL_memset(device->hidden, 0, (sizeof *device->hidden));
slouken@75
   136
slouken@1895
   137
    /* Set the function pointers */
slouken@1895
   138
    device->VideoInit = VGL_VideoInit;
slouken@1895
   139
    device->ListModes = VGL_ListModes;
slouken@1895
   140
    device->SetVideoMode = VGL_SetVideoMode;
slouken@1895
   141
    device->SetColors = VGL_SetColors;
slouken@1895
   142
    device->UpdateRects = NULL;
slouken@1895
   143
    device->VideoQuit = VGL_VideoQuit;
slouken@1895
   144
    device->AllocHWSurface = VGL_AllocHWSurface;
slouken@1895
   145
    device->CheckHWBlit = NULL;
slouken@1895
   146
    device->FillHWRect = NULL;
slouken@1895
   147
    device->SetHWColorKey = NULL;
slouken@1895
   148
    device->SetHWAlpha = NULL;
slouken@1895
   149
    device->LockHWSurface = VGL_LockHWSurface;
slouken@1895
   150
    device->UnlockHWSurface = VGL_UnlockHWSurface;
slouken@1895
   151
    device->FlipHWSurface = VGL_FlipHWSurface;
slouken@1895
   152
    device->FreeHWSurface = VGL_FreeHWSurface;
slouken@1895
   153
    device->SetIcon = NULL;
slouken@1895
   154
    device->SetCaption = NULL;
slouken@1895
   155
    device->GetWMInfo = NULL;
slouken@1895
   156
    device->FreeWMCursor = VGL_FreeWMCursor;
slouken@1895
   157
    device->CreateWMCursor = VGL_CreateWMCursor;
slouken@1895
   158
    device->ShowWMCursor = VGL_ShowWMCursor;
slouken@1895
   159
    device->WarpWMCursor = VGL_WarpWMCursor;
slouken@1895
   160
    device->InitOSKeymap = VGL_InitOSKeymap;
slouken@1895
   161
    device->PumpEvents = VGL_PumpEvents;
slouken@75
   162
slouken@1895
   163
    device->free = VGL_DeleteDevice;
slouken@75
   164
slouken@1895
   165
    return device;
slouken@75
   166
}
slouken@75
   167
slouken@75
   168
VideoBootStrap VGL_bootstrap = {
slouken@1895
   169
    "vgl", "FreeBSD libVGL",
slouken@1895
   170
    VGL_Available, VGL_CreateDevice
slouken@75
   171
};
slouken@75
   172
slouken@1895
   173
static int
slouken@1895
   174
VGL_AddMode(_THIS, VGLMode * inmode)
slouken@75
   175
{
slouken@1895
   176
    SDL_Rect *mode;
slouken@75
   177
slouken@1895
   178
    int i, index;
slouken@1895
   179
    int next_mode;
slouken@75
   180
slouken@1895
   181
    /* Check to see if we already have this mode */
slouken@1895
   182
    if (inmode->Depth < 8) {    /* Not supported */
slouken@1895
   183
        return 0;
slouken@1895
   184
    }
slouken@1895
   185
    index = ((inmode->Depth + 7) / 8) - 1;
slouken@1895
   186
    for (i = 0; i < SDL_nummodes[index]; ++i) {
slouken@1895
   187
        mode = SDL_modelist[index][i];
slouken@1895
   188
        if ((mode->w == inmode->ModeInfo.Xsize) &&
slouken@1895
   189
            (mode->h == inmode->ModeInfo.Ysize))
slouken@1895
   190
            return 0;
slouken@1895
   191
    }
slouken@75
   192
slouken@1895
   193
    /* Set up the new video mode rectangle */
slouken@1895
   194
    mode = (SDL_Rect *) SDL_malloc(sizeof *mode);
slouken@1895
   195
    if (mode == NULL) {
slouken@1895
   196
        SDL_OutOfMemory();
slouken@1895
   197
        return -1;
slouken@1895
   198
    }
slouken@1895
   199
    mode->x = 0;
slouken@1895
   200
    mode->y = 0;
slouken@1895
   201
    mode->w = inmode->ModeInfo.Xsize;
slouken@1895
   202
    mode->h = inmode->ModeInfo.Ysize;
slouken@75
   203
slouken@1895
   204
    /* Allocate the new list of modes, and fill in the new mode */
slouken@1895
   205
    next_mode = SDL_nummodes[index];
slouken@1895
   206
    SDL_modelist[index] = (SDL_Rect **)
slouken@1895
   207
        SDL_realloc(SDL_modelist[index],
slouken@1895
   208
                    (1 + next_mode + 1) * sizeof(SDL_Rect *));
slouken@1895
   209
    if (SDL_modelist[index] == NULL) {
slouken@1895
   210
        SDL_OutOfMemory();
slouken@1895
   211
        SDL_nummodes[index] = 0;
slouken@1895
   212
        SDL_free(mode);
slouken@1895
   213
        return -1;
slouken@1895
   214
    }
slouken@1895
   215
    SDL_modelist[index][next_mode] = mode;
slouken@1895
   216
    SDL_modelist[index][next_mode + 1] = NULL;
slouken@1895
   217
    SDL_nummodes[index]++;
slouken@75
   218
slouken@1895
   219
    return 0;
slouken@75
   220
}
slouken@75
   221
slouken@1895
   222
static void
slouken@1895
   223
VGL_UpdateVideoInfo(_THIS)
slouken@75
   224
{
slouken@1895
   225
    this->info.wm_available = 0;
slouken@1895
   226
    this->info.hw_available = 1;
slouken@1895
   227
    this->info.video_mem = 0;
slouken@1895
   228
    if (VGLCurMode == NULL) {
slouken@1895
   229
        return;
slouken@1895
   230
    }
slouken@1895
   231
    if (VGLCurMode->ModeInfo.PixelBytes > 0) {
slouken@1895
   232
        this->info.video_mem = VGLCurMode->ModeInfo.PixelBytes *
slouken@1895
   233
            VGLCurMode->ModeInfo.Xsize * VGLCurMode->ModeInfo.Ysize;
slouken@1895
   234
    }
slouken@75
   235
}
slouken@75
   236
slouken@1895
   237
int
slouken@1895
   238
VGL_VideoInit(_THIS, SDL_PixelFormat * vformat)
slouken@75
   239
{
slouken@1895
   240
    int i;
slouken@1895
   241
    int total_modes;
slouken@1895
   242
    VGLMode **modes;
slouken@75
   243
slouken@1895
   244
    /* Initialize all variables that we clean on shutdown */
slouken@1895
   245
    for (i = 0; i < NUM_MODELISTS; ++i) {
slouken@1895
   246
        SDL_nummodes[i] = 0;
slouken@1895
   247
        SDL_modelist[i] = NULL;
slouken@1895
   248
    }
slouken@75
   249
slouken@1895
   250
    /* Enable mouse and keyboard support */
slouken@1895
   251
    if (SDL_getenv("SDL_NO_RAWKBD") == NULL) {
slouken@1895
   252
        if (VGLKeyboardInit(VGL_CODEKEYS) != 0) {
slouken@1895
   253
            SDL_SetError("Unable to initialize keyboard");
slouken@1895
   254
            return -1;
slouken@1895
   255
        }
slouken@1895
   256
    } else {
slouken@1895
   257
        warnx("Requiest to put keyboard into a raw mode ignored");
slouken@1895
   258
    }
slouken@1895
   259
    if (VGL_initkeymaps(STDIN_FILENO) != 0) {
slouken@1895
   260
        SDL_SetError("Unable to initialize keymap");
slouken@1895
   261
        return -1;
slouken@1895
   262
    }
slouken@1895
   263
    if (VGL_initmouse(STDIN_FILENO) != 0) {
slouken@1895
   264
        SDL_SetError("Unable to initialize mouse");
slouken@1895
   265
        return -1;
slouken@1895
   266
    }
slouken@1545
   267
slouken@1895
   268
    /* Determine the current screen size */
slouken@1895
   269
    if (VGLCurMode != NULL) {
slouken@1895
   270
        this->info.current_w = VGLCurMode->ModeInfo.Xsize;
slouken@1895
   271
        this->info.current_h = VGLCurMode->ModeInfo.Ysize;
slouken@1895
   272
    }
slouken@1895
   273
slouken@1895
   274
    /* Determine the screen depth */
slouken@1895
   275
    if (VGLCurMode != NULL)
slouken@1895
   276
        vformat->BitsPerPixel = VGLCurMode->Depth;
slouken@1895
   277
    else
slouken@1895
   278
        vformat->BitsPerPixel = 16;     /* Good default */
slouken@75
   279
slouken@1895
   280
    /* Query for the list of available video modes */
slouken@1895
   281
    total_modes = 0;
slouken@1895
   282
    modes = VGLListModes(-1, V_INFO_MM_DIRECT | V_INFO_MM_PACKED);
slouken@1895
   283
    for (i = 0; modes[i] != NULL; i++) {
slouken@1895
   284
        if ((modes[i]->ModeInfo.Type == VIDBUF8) ||
slouken@1895
   285
            (modes[i]->ModeInfo.Type == VIDBUF16) ||
slouken@1895
   286
            (modes[i]->ModeInfo.Type == VIDBUF32)) {
slouken@1895
   287
            VGL_AddMode(this, modes[i]);
slouken@1895
   288
            total_modes++;
slouken@1895
   289
        }
slouken@1895
   290
    }
slouken@1895
   291
    if (total_modes == 0) {
slouken@1895
   292
        SDL_SetError("No linear video modes available");
slouken@1895
   293
        return -1;
slouken@1895
   294
    }
slouken@75
   295
slouken@1895
   296
    /* Fill in our hardware acceleration capabilities */
slouken@1895
   297
    VGL_UpdateVideoInfo(this);
slouken@75
   298
slouken@1895
   299
    /* Create the hardware surface lock mutex */
slouken@1895
   300
    hw_lock = SDL_CreateMutex();
slouken@1895
   301
    if (hw_lock == NULL) {
slouken@1895
   302
        SDL_SetError("Unable to create lock mutex");
slouken@1895
   303
        VGL_VideoQuit(this);
slouken@1895
   304
        return -1;
slouken@1895
   305
    }
slouken@75
   306
slouken@1895
   307
    /* We're done! */
slouken@1895
   308
    return 0;
slouken@75
   309
}
slouken@75
   310
slouken@1895
   311
SDL_Rect **
slouken@1895
   312
VGL_ListModes(_THIS, SDL_PixelFormat * format, Uint32 flags)
slouken@75
   313
{
slouken@1895
   314
    return SDL_modelist[((format->BitsPerPixel + 7) / 8) - 1];
slouken@75
   315
}
slouken@75
   316
slouken@75
   317
/* Various screen update functions available */
slouken@1895
   318
static void VGL_DirectUpdate(_THIS, int numrects, SDL_Rect * rects);
slouken@1895
   319
static void VGL_BankedUpdate(_THIS, int numrects, SDL_Rect * rects);
slouken@75
   320
slouken@1895
   321
SDL_Surface *
slouken@1895
   322
VGL_SetVideoMode(_THIS, SDL_Surface * current,
slouken@1895
   323
                 int width, int height, int bpp, Uint32 flags)
slouken@75
   324
{
slouken@1895
   325
    int mode_found;
slouken@1895
   326
    int i;
slouken@1895
   327
    VGLMode **modes;
slouken@75
   328
slouken@1895
   329
    modes = VGLListModes(bpp, V_INFO_MM_DIRECT | V_INFO_MM_PACKED);
slouken@1895
   330
    mode_found = 0;
slouken@1895
   331
    for (i = 0; modes[i] != NULL; i++) {
slouken@1895
   332
        if ((modes[i]->ModeInfo.Xsize == width) &&
slouken@1895
   333
            (modes[i]->ModeInfo.Ysize == height) &&
slouken@1895
   334
            ((modes[i]->ModeInfo.Type == VIDBUF8) ||
slouken@1895
   335
             (modes[i]->ModeInfo.Type == VIDBUF16) ||
slouken@1895
   336
             (modes[i]->ModeInfo.Type == VIDBUF32))) {
slouken@1895
   337
            mode_found = 1;
slouken@1895
   338
            break;
slouken@1895
   339
        }
slouken@1895
   340
    }
slouken@1895
   341
    if (mode_found == 0) {
slouken@1895
   342
        SDL_SetError("No matching video mode found");
slouken@1895
   343
        return NULL;
slouken@1895
   344
    }
slouken@75
   345
slouken@1895
   346
    /* Shutdown previous videomode (if any) */
slouken@1895
   347
    if (VGLCurMode != NULL)
slouken@1895
   348
        VGLEnd();
slouken@75
   349
slouken@1895
   350
    /* Try to set the requested linear video mode */
slouken@1895
   351
    if (VGLInit(modes[i]->ModeId) != 0) {
slouken@1895
   352
        SDL_SetError("Unable to switch to requested mode");
slouken@1895
   353
        return NULL;
slouken@1895
   354
    }
slouken@75
   355
slouken@1895
   356
    VGLCurMode = SDL_realloc(VGLCurMode, sizeof(VGLMode));
slouken@1895
   357
    VGLCurMode->ModeInfo = *VGLDisplay;
slouken@1895
   358
    VGLCurMode->Depth = modes[i]->Depth;
slouken@1895
   359
    VGLCurMode->ModeId = modes[i]->ModeId;
slouken@1895
   360
    VGLCurMode->Rmask = modes[i]->Rmask;
slouken@1895
   361
    VGLCurMode->Gmask = modes[i]->Gmask;
slouken@1895
   362
    VGLCurMode->Bmask = modes[i]->Bmask;
slouken@75
   363
slouken@1895
   364
    /* Workaround a bug in libvgl */
slouken@1895
   365
    if (VGLCurMode->ModeInfo.PixelBytes == 0)
slouken@1895
   366
        (VGLCurMode->ModeInfo.PixelBytes = 1);
slouken@75
   367
slouken@1895
   368
    current->w = VGLCurMode->ModeInfo.Xsize;
slouken@1895
   369
    current->h = VGLCurMode->ModeInfo.Ysize;
slouken@1895
   370
    current->pixels = VGLCurMode->ModeInfo.Bitmap;
slouken@1895
   371
    current->pitch = VGLCurMode->ModeInfo.Xsize *
slouken@1895
   372
        VGLCurMode->ModeInfo.PixelBytes;
slouken@1895
   373
    current->flags = (SDL_FULLSCREEN | SDL_HWSURFACE);
slouken@75
   374
slouken@1895
   375
    /* Check if we are in a pseudo-color mode */
slouken@1895
   376
    if (VGLCurMode->ModeInfo.Type == VIDBUF8)
slouken@1895
   377
        current->flags |= SDL_HWPALETTE;
slouken@75
   378
slouken@1895
   379
    /* Check if we can do doublebuffering */
slouken@1895
   380
    if (flags & SDL_DOUBLEBUF) {
slouken@1895
   381
        if (VGLCurMode->ModeInfo.Xsize * 2 <= VGLCurMode->ModeInfo.VYsize) {
slouken@1895
   382
            current->flags |= SDL_DOUBLEBUF;
slouken@1895
   383
            flip_page = 0;
slouken@1895
   384
            flip_address[0] = (byte *) current->pixels;
slouken@1895
   385
            flip_address[1] = (byte *) current->pixels +
slouken@1895
   386
                current->h * current->pitch;
slouken@1895
   387
            VGL_FlipHWSurface(this, current);
slouken@1895
   388
        }
slouken@1895
   389
    }
slouken@75
   390
slouken@1895
   391
    if (!SDL_ReallocFormat(current, modes[i]->Depth, VGLCurMode->Rmask,
slouken@1895
   392
                           VGLCurMode->Gmask, VGLCurMode->Bmask, 0)) {
slouken@1895
   393
        return NULL;
slouken@1895
   394
    }
slouken@75
   395
slouken@1895
   396
    /* Update hardware acceleration info */
slouken@1895
   397
    VGL_UpdateVideoInfo(this);
slouken@75
   398
slouken@1895
   399
    /* Set the blit function */
slouken@1895
   400
    this->UpdateRects = VGL_DirectUpdate;
slouken@75
   401
slouken@1895
   402
    /* We're done */
slouken@1895
   403
    return current;
slouken@75
   404
}
slouken@75
   405
slouken@75
   406
/* We don't actually allow hardware surfaces other than the main one */
slouken@1895
   407
static int
slouken@1895
   408
VGL_AllocHWSurface(_THIS, SDL_Surface * surface)
slouken@75
   409
{
slouken@1895
   410
    return -1;
slouken@75
   411
}
slouken@1895
   412
static void
slouken@1895
   413
VGL_FreeHWSurface(_THIS, SDL_Surface * surface)
slouken@75
   414
{
slouken@1895
   415
    return;
slouken@75
   416
}
slouken@75
   417
slouken@75
   418
/* We need to wait for vertical retrace on page flipped displays */
slouken@1895
   419
static int
slouken@1895
   420
VGL_LockHWSurface(_THIS, SDL_Surface * surface)
slouken@75
   421
{
slouken@1895
   422
    if (surface == SDL_VideoSurface) {
slouken@1895
   423
        SDL_mutexP(hw_lock);
slouken@1895
   424
    }
slouken@1895
   425
    return 0;
slouken@75
   426
}
slouken@1895
   427
static void
slouken@1895
   428
VGL_UnlockHWSurface(_THIS, SDL_Surface * surface)
slouken@75
   429
{
slouken@1895
   430
    if (surface == SDL_VideoSurface) {
slouken@1895
   431
        SDL_mutexV(hw_lock);
slouken@1895
   432
    }
slouken@75
   433
}
slouken@75
   434
slouken@1895
   435
static int
slouken@1895
   436
VGL_FlipHWSurface(_THIS, SDL_Surface * surface)
slouken@75
   437
{
slouken@1895
   438
//      VGLWaitRetrace();
slouken@1895
   439
    if (VGLPanScreen(VGLDisplay, 0, flip_page * surface->h) < 0) {
slouken@1895
   440
        SDL_SetError("VGLPanSreen() failed");
slouken@1895
   441
        return -1;
slouken@1895
   442
    }
slouken@75
   443
slouken@1895
   444
    flip_page = !flip_page;
slouken@1895
   445
    surface->pixels = flip_address[flip_page];
slouken@75
   446
slouken@1895
   447
    return 0;
slouken@75
   448
}
slouken@75
   449
slouken@1895
   450
static void
slouken@1895
   451
VGL_DirectUpdate(_THIS, int numrects, SDL_Rect * rects)
slouken@75
   452
{
slouken@1895
   453
    return;
slouken@75
   454
}
slouken@75
   455
slouken@1895
   456
static void
slouken@1895
   457
VGL_BankedUpdate(_THIS, int numrects, SDL_Rect * rects)
slouken@75
   458
{
slouken@1895
   459
    return;
slouken@75
   460
}
slouken@75
   461
slouken@1895
   462
int
slouken@1895
   463
VGL_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color * colors)
slouken@75
   464
{
slouken@1895
   465
    int i;
slouken@75
   466
slouken@1895
   467
    for (i = 0; i < ncolors; i++) {
slouken@1895
   468
        VGLSetPaletteIndex(firstcolor + i,
slouken@1895
   469
                           colors[i].r >> 2,
slouken@1895
   470
                           colors[i].g >> 2, colors[i].b >> 2);
slouken@1895
   471
    }
slouken@1895
   472
    return 1;
slouken@75
   473
}
slouken@75
   474
slouken@75
   475
/* Note:  If we are terminated, this could be called in the middle of
slouken@75
   476
   another SDL video routine -- notably UpdateRects.
slouken@75
   477
*/
slouken@1895
   478
void
slouken@1895
   479
VGL_VideoQuit(_THIS)
slouken@75
   480
{
slouken@1895
   481
    int i, j;
slouken@75
   482
slouken@1895
   483
    /* Return the keyboard to the normal state */
slouken@1895
   484
    VGLKeyboardEnd();
slouken@1895
   485
slouken@1895
   486
    /* Reset the console video mode if we actually initialised one */
slouken@1895
   487
    if (VGLCurMode != NULL) {
slouken@1895
   488
        VGLEnd();
slouken@1895
   489
        SDL_free(VGLCurMode);
slouken@1895
   490
        VGLCurMode = NULL;
slouken@1895
   491
    }
slouken@75
   492
slouken@1895
   493
    /* Clear the lock mutex */
slouken@1895
   494
    if (hw_lock != NULL) {
slouken@1895
   495
        SDL_DestroyMutex(hw_lock);
slouken@1895
   496
        hw_lock = NULL;
slouken@1895
   497
    }
slouken@75
   498
slouken@1895
   499
    /* Free video mode lists */
slouken@1895
   500
    for (i = 0; i < NUM_MODELISTS; i++) {
slouken@1895
   501
        if (SDL_modelist[i] != NULL) {
slouken@1895
   502
            for (j = 0; SDL_modelist[i][j] != NULL; ++j) {
slouken@1895
   503
                SDL_free(SDL_modelist[i][j]);
slouken@1895
   504
            }
slouken@1895
   505
            SDL_free(SDL_modelist[i]);
slouken@1895
   506
            SDL_modelist[i] = NULL;
slouken@1895
   507
        }
slouken@1895
   508
    }
slouken@75
   509
slouken@1895
   510
    if (this->screen && (this->screen->flags & SDL_HWSURFACE)) {
slouken@1895
   511
        /* Direct screen access, not a memory buffer */
slouken@1895
   512
        this->screen->pixels = NULL;
slouken@1895
   513
    }
slouken@75
   514
}
slouken@75
   515
slouken@75
   516
#define VGL_RED_INDEX	0
slouken@75
   517
#define VGL_GREEN_INDEX	1
slouken@75
   518
#define VGL_BLUE_INDEX	2
slouken@75
   519
slouken@75
   520
static VGLMode **
slouken@75
   521
VGLListModes(int depth, int mem_model)
slouken@75
   522
{
slouken@1895
   523
    static VGLMode **modes = NULL;
slouken@75
   524
slouken@1895
   525
    VGLBitmap *vminfop;
slouken@1895
   526
    VGLMode **modesp, *modescp;
slouken@1895
   527
    video_info_t minfo;
slouken@1895
   528
    int adptype, i, modenum;
slouken@75
   529
slouken@1895
   530
    if (modes == NULL) {
slouken@1895
   531
        modes = SDL_malloc(sizeof(VGLMode *) * M_VESA_MODE_MAX);
slouken@1895
   532
        bzero(modes, sizeof(VGLMode *) * M_VESA_MODE_MAX);
slouken@1895
   533
    }
slouken@1895
   534
    modesp = modes;
slouken@75
   535
slouken@1895
   536
    for (modenum = 0; modenum < M_VESA_MODE_MAX; modenum++) {
slouken@1895
   537
        minfo.vi_mode = modenum;
slouken@1895
   538
        if (ioctl(0, CONS_MODEINFO, &minfo)
slouken@1895
   539
            || ioctl(0, CONS_CURRENT, &adptype))
slouken@1895
   540
            continue;
slouken@1895
   541
        if (minfo.vi_mode != modenum)
slouken@1895
   542
            continue;
slouken@1895
   543
        if ((minfo.vi_flags & V_INFO_GRAPHICS) == 0)
slouken@1895
   544
            continue;
slouken@1895
   545
        if ((mem_model != -1) && ((minfo.vi_mem_model & mem_model) == 0))
slouken@1895
   546
            continue;
slouken@1895
   547
        if ((depth > 1) && (minfo.vi_depth != depth))
slouken@1895
   548
            continue;
slouken@75
   549
slouken@1895
   550
        /* reallocf can fail */
slouken@1895
   551
        if ((*modesp = reallocf(*modesp, sizeof(VGLMode))) == NULL)
slouken@1895
   552
            return NULL;
slouken@1895
   553
        modescp = *modesp;
slouken@75
   554
slouken@1895
   555
        vminfop = &(modescp->ModeInfo);
slouken@1895
   556
        bzero(vminfop, sizeof(VGLBitmap));
slouken@75
   557
slouken@1895
   558
        vminfop->Type = NOBUF;
slouken@75
   559
slouken@1895
   560
        vminfop->PixelBytes = 1;        /* Good default value */
slouken@1895
   561
        switch (minfo.vi_mem_model) {
slouken@1895
   562
        case V_INFO_MM_PLANAR:
slouken@1895
   563
            /* we can handle EGA/VGA planar modes only */
slouken@1895
   564
            if (!(minfo.vi_depth != 4 || minfo.vi_planes != 4
slouken@1895
   565
                  || (adptype != KD_EGA && adptype != KD_VGA)))
slouken@1895
   566
                vminfop->Type = VIDBUF4;
slouken@1895
   567
            break;
slouken@1895
   568
        case V_INFO_MM_PACKED:
slouken@1895
   569
            /* we can do only 256 color packed modes */
slouken@1895
   570
            if (minfo.vi_depth == 8)
slouken@1895
   571
                vminfop->Type = VIDBUF8;
slouken@1895
   572
            break;
slouken@1895
   573
        case V_INFO_MM_VGAX:
slouken@1895
   574
            vminfop->Type = VIDBUF8X;
slouken@1895
   575
            break;
slouken@1565
   576
#if defined(__FREEBSD__) && (defined(__DragonFly__) || __FreeBSD_version >= 500000)
slouken@1895
   577
        case V_INFO_MM_DIRECT:
slouken@1895
   578
            vminfop->PixelBytes = minfo.vi_pixel_size;
slouken@1895
   579
            switch (vminfop->PixelBytes) {
slouken@1895
   580
            case 2:
slouken@1895
   581
                vminfop->Type = VIDBUF16;
slouken@1895
   582
                break;
slouken@75
   583
#if notyet
slouken@1895
   584
            case 3:
slouken@1895
   585
                vminfop->Type = VIDBUF24;
slouken@1895
   586
                break;
slouken@75
   587
#endif
slouken@1895
   588
            case 4:
slouken@1895
   589
                vminfop->Type = VIDBUF32;
slouken@1895
   590
                break;
slouken@1895
   591
            default:
slouken@1895
   592
                break;
slouken@1895
   593
            }
slouken@75
   594
#endif
slouken@1895
   595
        default:
slouken@1895
   596
            break;
slouken@1895
   597
        }
slouken@1895
   598
        if (vminfop->Type == NOBUF)
slouken@1895
   599
            continue;
slouken@1895
   600
slouken@1895
   601
        switch (vminfop->Type) {
slouken@1895
   602
        case VIDBUF16:
slouken@1895
   603
        case VIDBUF32:
slouken@1895
   604
            modescp->Rmask =
slouken@1895
   605
                ((1 << minfo.vi_pixel_fsizes[VGL_RED_INDEX]) -
slouken@1895
   606
                 1) << minfo.vi_pixel_fields[VGL_RED_INDEX];
slouken@1895
   607
            modescp->Gmask =
slouken@1895
   608
                ((1 << minfo.vi_pixel_fsizes[VGL_GREEN_INDEX]) -
slouken@1895
   609
                 1) << minfo.vi_pixel_fields[VGL_GREEN_INDEX];
slouken@1895
   610
            modescp->Bmask =
slouken@1895
   611
                ((1 << minfo.vi_pixel_fsizes[VGL_BLUE_INDEX]) -
slouken@1895
   612
                 1) << minfo.vi_pixel_fields[VGL_BLUE_INDEX];
slouken@1895
   613
            break;
slouken@1895
   614
slouken@1895
   615
        default:
slouken@1895
   616
            break;
slouken@1895
   617
        }
slouken@75
   618
slouken@1895
   619
        vminfop->Xsize = minfo.vi_width;
slouken@1895
   620
        vminfop->Ysize = minfo.vi_height;
slouken@1895
   621
        modescp->Depth = minfo.vi_depth;
slouken@1895
   622
slouken@1895
   623
        /* XXX */
slouken@1895
   624
        if (minfo.vi_mode >= M_VESA_BASE)
slouken@1895
   625
            modescp->ModeId = _IO('V', minfo.vi_mode - M_VESA_BASE);
slouken@1895
   626
        else
slouken@1895
   627
            modescp->ModeId = _IO('S', minfo.vi_mode);
slouken@75
   628
slouken@1895
   629
        /* Sort list */
slouken@1895
   630
        for (i = 0; modes + i < modesp; i++) {
slouken@1895
   631
            if (modes[i]->ModeInfo.Xsize * modes[i]->ModeInfo.Ysize >
slouken@1895
   632
                vminfop->Xsize * modes[i]->ModeInfo.Ysize)
slouken@1895
   633
                continue;
slouken@1895
   634
            if ((modes[i]->ModeInfo.Xsize * modes[i]->ModeInfo.Ysize ==
slouken@1895
   635
                 vminfop->Xsize * vminfop->Ysize) &&
slouken@1895
   636
                (modes[i]->Depth >= modescp->Depth))
slouken@1895
   637
                continue;
slouken@1895
   638
            *modesp = modes[i];
slouken@1895
   639
            modes[i] = modescp;
slouken@1895
   640
            modescp = *modesp;
slouken@1895
   641
            vminfop = &(modescp->ModeInfo);
slouken@1895
   642
        }
slouken@1895
   643
slouken@1895
   644
        modesp++;
slouken@75
   645
    }
slouken@75
   646
slouken@1895
   647
    if (*modesp != NULL) {
slouken@1895
   648
        SDL_free(*modesp);
slouken@1895
   649
        *modesp = NULL;
slouken@75
   650
    }
slouken@75
   651
slouken@1895
   652
    return modes;
slouken@75
   653
}
slouken@75
   654
slouken@75
   655
static void
slouken@75
   656
VGLWaitRetrace(void)
slouken@75
   657
{
slouken@1895
   658
    while (!(inb(0x3DA) & 8));
slouken@1895
   659
    while (inb(0x3DA) & 8);
slouken@75
   660
}
slouken@75
   661
slouken@1895
   662
/* vi: set ts=4 sw=4 expandtab: */