src/video/wscons/SDL_wsconsvideo.c
author Ryan C. Gordon <icculus@icculus.org>
Fri, 06 Jan 2006 13:20:10 +0000
changeset 1234 73676c1f56ee
parent 1187 19d8949b4584
child 1312 c9b51268668f
permissions -rw-r--r--
For sanity's sake, removed the '&' when passing copy_row array to asm.
icculus@1187
     1
/*
icculus@1187
     2
    SDL - Simple DirectMedia Layer
icculus@1187
     3
    Copyright (C) 1997-2004 Sam Lantinga
icculus@1187
     4
icculus@1187
     5
    This library is free software; you can redistribute it and/or
icculus@1187
     6
    modify it under the terms of the GNU Library General Public
icculus@1187
     7
    License as published by the Free Software Foundation; either
icculus@1187
     8
    version 2 of the License, or (at your option) any later version.
icculus@1187
     9
icculus@1187
    10
    This library is distributed in the hope that it will be useful,
icculus@1187
    11
    but WITHOUT ANY WARRANTY; without even the implied warranty of
icculus@1187
    12
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
icculus@1187
    13
    Library General Public License for more details.
icculus@1187
    14
icculus@1187
    15
    You should have received a copy of the GNU Library General Public
icculus@1187
    16
    License along with this library; if not, write to the Free
icculus@1187
    17
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
icculus@1187
    18
icculus@1187
    19
    Sam Lantinga
icculus@1187
    20
    slouken@libsdl.org
icculus@1187
    21
*/
icculus@1187
    22
icculus@1187
    23
#ifdef SAVE_RCSID
icculus@1187
    24
static char rcsid =
icculus@1187
    25
 "@(#) $Id$";
icculus@1187
    26
#endif
icculus@1187
    27
icculus@1187
    28
#include <sys/time.h>
icculus@1187
    29
#include <sys/mman.h>
icculus@1187
    30
#include <sys/ioctl.h>
icculus@1187
    31
#include <dev/wscons/wsdisplay_usl_io.h>
icculus@1187
    32
#include <fcntl.h>
icculus@1187
    33
#include <unistd.h>
icculus@1187
    34
#include <stdio.h>
icculus@1187
    35
#include <stdlib.h>
icculus@1187
    36
#include <string.h>
icculus@1187
    37
#include <stdarg.h>
icculus@1187
    38
#include <errno.h>
icculus@1187
    39
icculus@1187
    40
#include "SDL.h"
icculus@1187
    41
#include "SDL_error.h"
icculus@1187
    42
#include "SDL_video.h"
icculus@1187
    43
#include "SDL_mouse.h"
icculus@1187
    44
#include "SDL_sysvideo.h"
icculus@1187
    45
#include "SDL_pixels_c.h"
icculus@1187
    46
#include "SDL_events_c.h"
icculus@1187
    47
icculus@1187
    48
#include "SDL_wsconsvideo.h"
icculus@1187
    49
#include "SDL_wsconsevents_c.h"
icculus@1187
    50
#include "SDL_wsconsmouse_c.h"
icculus@1187
    51
icculus@1187
    52
#define WSCONSVID_DRIVER_NAME "wscons"
icculus@1187
    53
enum {
icculus@1187
    54
  WSCONS_ROTATE_NONE = 0,
icculus@1187
    55
  WSCONS_ROTATE_CCW = 90,
icculus@1187
    56
  WSCONS_ROTATE_UD = 180,
icculus@1187
    57
  WSCONS_ROTATE_CW = 270
icculus@1187
    58
};
icculus@1187
    59
icculus@1187
    60
#define min(a,b) ((a)<(b)?(a):(b))
icculus@1187
    61
icculus@1187
    62
/* Initialization/Query functions */
icculus@1187
    63
static int WSCONS_VideoInit(_THIS, SDL_PixelFormat *vformat);
icculus@1187
    64
static SDL_Rect **WSCONS_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags);
icculus@1187
    65
static SDL_Surface *WSCONS_SetVideoMode(_THIS, SDL_Surface *current, int width, int height, int bpp, Uint32 flags);
icculus@1187
    66
static int WSCONS_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors);
icculus@1187
    67
static void WSCONS_VideoQuit(_THIS);
icculus@1187
    68
icculus@1187
    69
/* Hardware surface functions */
icculus@1187
    70
static int WSCONS_AllocHWSurface(_THIS, SDL_Surface *surface);
icculus@1187
    71
static int WSCONS_LockHWSurface(_THIS, SDL_Surface *surface);
icculus@1187
    72
static void WSCONS_UnlockHWSurface(_THIS, SDL_Surface *surface);
icculus@1187
    73
static void WSCONS_FreeHWSurface(_THIS, SDL_Surface *surface);
icculus@1187
    74
icculus@1187
    75
/* etc. */
icculus@1187
    76
static WSCONS_bitBlit WSCONS_blit16;
icculus@1187
    77
static WSCONS_bitBlit WSCONS_blit16blocked;
icculus@1187
    78
static void WSCONS_UpdateRects(_THIS, int numrects, SDL_Rect *rects);
icculus@1187
    79
icculus@1187
    80
void WSCONS_ReportError(char *fmt, ...)
icculus@1187
    81
{
icculus@1187
    82
  char message[200];
icculus@1187
    83
  
icculus@1187
    84
  message[199] = '\0';
icculus@1187
    85
  
icculus@1187
    86
  va_list vaArgs;
icculus@1187
    87
  va_start(vaArgs, fmt);
icculus@1187
    88
  vsnprintf(message, 199, fmt, vaArgs);
icculus@1187
    89
  va_end(vaArgs);
icculus@1187
    90
icculus@1187
    91
  SDL_SetError(message); 
icculus@1187
    92
  fprintf(stderr, "WSCONS error: %s\n", message);
icculus@1187
    93
}
icculus@1187
    94
icculus@1187
    95
/* WSCONS driver bootstrap functions */
icculus@1187
    96
icculus@1187
    97
static int WSCONS_Available(void)
icculus@1187
    98
{
icculus@1187
    99
  return 1;
icculus@1187
   100
}
icculus@1187
   101
icculus@1187
   102
static void WSCONS_DeleteDevice(SDL_VideoDevice *device)
icculus@1187
   103
{
icculus@1187
   104
  free(device->hidden);
icculus@1187
   105
  free(device);
icculus@1187
   106
}
icculus@1187
   107
icculus@1187
   108
static SDL_VideoDevice *WSCONS_CreateDevice(int devindex)
icculus@1187
   109
{
icculus@1187
   110
  SDL_VideoDevice *device;
icculus@1187
   111
  
icculus@1187
   112
  /* Initialize all variables that we clean on shutdown */
icculus@1187
   113
  device = (SDL_VideoDevice *)malloc(sizeof(SDL_VideoDevice));
icculus@1187
   114
  if (device == NULL) {
icculus@1187
   115
    SDL_OutOfMemory();
icculus@1187
   116
    return 0;
icculus@1187
   117
  }
icculus@1187
   118
  memset(device, 0, (sizeof *device));
icculus@1187
   119
  device->hidden = 
icculus@1187
   120
    (struct SDL_PrivateVideoData *)malloc((sizeof *device->hidden));
icculus@1187
   121
  if (device->hidden == NULL) {
icculus@1187
   122
    SDL_OutOfMemory();
icculus@1187
   123
    free(device);
icculus@1187
   124
    return(0);
icculus@1187
   125
  }
icculus@1187
   126
  memset(device->hidden, 0, (sizeof *device->hidden));
icculus@1187
   127
  device->hidden->fd = -1;
icculus@1187
   128
  
icculus@1187
   129
  /* Set the function pointers */
icculus@1187
   130
  device->VideoInit = WSCONS_VideoInit;
icculus@1187
   131
  device->ListModes = WSCONS_ListModes;
icculus@1187
   132
  device->SetVideoMode = WSCONS_SetVideoMode;
icculus@1187
   133
  device->SetColors = WSCONS_SetColors;
icculus@1187
   134
  device->UpdateRects = WSCONS_UpdateRects;
icculus@1187
   135
  device->VideoQuit = WSCONS_VideoQuit;
icculus@1187
   136
  device->AllocHWSurface = WSCONS_AllocHWSurface;
icculus@1187
   137
  device->LockHWSurface = WSCONS_LockHWSurface;
icculus@1187
   138
  device->UnlockHWSurface = WSCONS_UnlockHWSurface;
icculus@1187
   139
  device->FreeHWSurface = WSCONS_FreeHWSurface;
icculus@1187
   140
  device->InitOSKeymap = WSCONS_InitOSKeymap;
icculus@1187
   141
  device->PumpEvents = WSCONS_PumpEvents;
icculus@1187
   142
  device->free = WSCONS_DeleteDevice;
icculus@1187
   143
  
icculus@1187
   144
  return device;
icculus@1187
   145
}
icculus@1187
   146
icculus@1187
   147
VideoBootStrap WSCONS_bootstrap = {
icculus@1187
   148
  WSCONSVID_DRIVER_NAME,
icculus@1187
   149
  "SDL wscons video driver",
icculus@1187
   150
  WSCONS_Available,
icculus@1187
   151
  WSCONS_CreateDevice
icculus@1187
   152
};
icculus@1187
   153
icculus@1187
   154
#define WSCONSDEV_FORMAT "/dev/ttyC%01x"
icculus@1187
   155
icculus@1187
   156
int WSCONS_VideoInit(_THIS, SDL_PixelFormat *vformat)
icculus@1187
   157
{
icculus@1187
   158
  char devnamebuf[30];
icculus@1187
   159
  char *devname;
icculus@1187
   160
  char *rotation;
icculus@1187
   161
  int wstype;
icculus@1187
   162
  int wsmode = WSDISPLAYIO_MODE_DUMBFB;
icculus@1187
   163
  size_t len, mapsize;
icculus@1187
   164
  int pagemask;
icculus@1187
   165
  int width, height;
icculus@1187
   166
  
icculus@1187
   167
  devname = getenv("SDL_WSCONSDEV");
icculus@1187
   168
  if (devname == NULL) {
icculus@1187
   169
    int activeVT;
icculus@1187
   170
    if (ioctl(STDIN_FILENO, VT_GETACTIVE, &activeVT) == -1) {
icculus@1187
   171
      WSCONS_ReportError("Unable to determine active terminal: %s", 
icculus@1187
   172
			 strerror(errno));
icculus@1187
   173
      return -1;
icculus@1187
   174
    }
icculus@1187
   175
    snprintf(devnamebuf, sizeof(devnamebuf), WSCONSDEV_FORMAT, activeVT - 1);
icculus@1187
   176
    devname = devnamebuf;
icculus@1187
   177
  }
icculus@1187
   178
icculus@1187
   179
  private->fd = open(devname, O_RDWR | O_NONBLOCK, 0);
icculus@1187
   180
  if (private->fd == -1) {
icculus@1187
   181
    WSCONS_ReportError("open %s: %s", devname, strerror(errno));
icculus@1187
   182
    return -1;
icculus@1187
   183
  }
icculus@1187
   184
  if (ioctl(private->fd, WSDISPLAYIO_GINFO, &private->info) == -1) {
icculus@1187
   185
    WSCONS_ReportError("ioctl WSDISPLAY_GINFO: %s", strerror(errno));
icculus@1187
   186
    return -1;
icculus@1187
   187
  }
icculus@1187
   188
  if (ioctl(private->fd, WSDISPLAYIO_GTYPE, &wstype) == -1) {
icculus@1187
   189
    WSCONS_ReportError("ioctl WSDISPLAY_GTYPE: %s", strerror(errno));
icculus@1187
   190
    return -1;
icculus@1187
   191
  }
icculus@1187
   192
  if (ioctl(private->fd, WSDISPLAYIO_LINEBYTES, &private->physlinebytes) == -1) {
icculus@1187
   193
    WSCONS_ReportError("ioctl WSDISPLAYIO_LINEBYTES: %s", strerror(errno));
icculus@1187
   194
    return -1;
icculus@1187
   195
  }
icculus@1187
   196
  if (private->info.depth > 8) {
icculus@1187
   197
    if (wstype == WSDISPLAY_TYPE_SUN24 ||
icculus@1187
   198
	wstype == WSDISPLAY_TYPE_SUNCG12 ||
icculus@1187
   199
	wstype == WSDISPLAY_TYPE_SUNCG14 ||
icculus@1187
   200
	wstype == WSDISPLAY_TYPE_SUNTCX ||
icculus@1187
   201
	wstype == WSDISPLAY_TYPE_SUNFFB) {
icculus@1187
   202
      private->redMask = 0x0000ff;
icculus@1187
   203
      private->greenMask = 0x00ff00;
icculus@1187
   204
      private->blueMask = 0xff0000;
icculus@1187
   205
    } else if (wstype == WSDISPLAY_TYPE_PXALCD) {
icculus@1187
   206
      private->redMask = 0x1f << 11;
icculus@1187
   207
      private->greenMask = 0x3f << 5;
icculus@1187
   208
      private->blueMask = 0x1f;
icculus@1187
   209
    } else {
icculus@1187
   210
      WSCONS_ReportError("Unknown video hardware");
icculus@1187
   211
      return -1;
icculus@1187
   212
    }
icculus@1187
   213
  } else {
icculus@1187
   214
    WSCONS_ReportError("Displays with 8 bpp or less are not supported");
icculus@1187
   215
    return -1;
icculus@1187
   216
  }
icculus@1187
   217
  
icculus@1187
   218
  private->rotate = WSCONS_ROTATE_NONE;
icculus@1187
   219
  rotation = getenv("SDL_VIDEO_WSCONS_ROTATION");
icculus@1187
   220
  if (rotation != NULL) {
icculus@1187
   221
    if (strlen(rotation) == 0) {
icculus@1187
   222
      private->shadowFB = 0;
icculus@1187
   223
      private->rotate = WSCONS_ROTATE_NONE;
icculus@1187
   224
      printf("Not rotating, no shadow\n");
icculus@1187
   225
    } else if (!strcmp(rotation, "NONE")) {
icculus@1187
   226
      private->shadowFB = 1;
icculus@1187
   227
      private->rotate = WSCONS_ROTATE_NONE;
icculus@1187
   228
      printf("Not rotating, but still using shadow\n");
icculus@1187
   229
    } else if (!strcmp(rotation, "CW")) {
icculus@1187
   230
      private->shadowFB = 1;
icculus@1187
   231
      private->rotate = WSCONS_ROTATE_CW;
icculus@1187
   232
      printf("Rotating screen clockwise\n");
icculus@1187
   233
    } else if (!strcmp(rotation, "CCW")) {
icculus@1187
   234
      private->shadowFB = 1;
icculus@1187
   235
      private->rotate = WSCONS_ROTATE_CCW;
icculus@1187
   236
      printf("Rotating screen counter clockwise\n");
icculus@1187
   237
    } else if (!strcmp(rotation, "UD")) {
icculus@1187
   238
      private->shadowFB = 1;
icculus@1187
   239
      private->rotate = WSCONS_ROTATE_UD;
icculus@1187
   240
      printf("Rotating screen upside down\n");
icculus@1187
   241
    } else {
icculus@1187
   242
      WSCONS_ReportError("\"%s\" is not a valid value for "
icculus@1187
   243
			 "SDL_VIDEO_WSCONS_ROTATION", rotation);
icculus@1187
   244
      return -1;
icculus@1187
   245
    }
icculus@1187
   246
  }
icculus@1187
   247
icculus@1187
   248
  switch (private->info.depth) {
icculus@1187
   249
    case 1:
icculus@1187
   250
    case 4:
icculus@1187
   251
    case 8:
icculus@1187
   252
      len = private->physlinebytes * private->info.height;
icculus@1187
   253
      break;
icculus@1187
   254
    case 16:
icculus@1187
   255
      if (private->physlinebytes == private->info.width) {
icculus@1187
   256
	len = private->info.width * private->info.height * sizeof(short);
icculus@1187
   257
      } else {
icculus@1187
   258
	len = private->physlinebytes * private->info.height;
icculus@1187
   259
      }
icculus@1187
   260
      if (private->rotate == WSCONS_ROTATE_NONE ||
icculus@1187
   261
	  private->rotate == WSCONS_ROTATE_UD) {
icculus@1187
   262
	private->blitFunc = WSCONS_blit16;
icculus@1187
   263
      } else {
icculus@1187
   264
	private->blitFunc = WSCONS_blit16blocked;
icculus@1187
   265
      }
icculus@1187
   266
      break;
icculus@1187
   267
    case 32:
icculus@1187
   268
      if (private->physlinebytes == private->info.width) {
icculus@1187
   269
	len = private->info.width * private->info.height * sizeof(int);
icculus@1187
   270
      } else {
icculus@1187
   271
	len = private->physlinebytes * private->info.height;
icculus@1187
   272
      }
icculus@1187
   273
      break;
icculus@1187
   274
    default:
icculus@1187
   275
      WSCONS_ReportError("unsupported depth %d", private->info.depth);
icculus@1187
   276
      return -1;
icculus@1187
   277
  }
icculus@1187
   278
icculus@1187
   279
  if (private->shadowFB && private->blitFunc == NULL) {
icculus@1187
   280
    WSCONS_ReportError("Using software buffer, but no blitter function is "
icculus@1187
   281
		       "available for this %d bpp.", private->info.depth);
icculus@1187
   282
    return -1;
icculus@1187
   283
  }
icculus@1187
   284
icculus@1187
   285
  if (ioctl(private->fd, WSDISPLAYIO_SMODE, &wsmode) == -1) {
icculus@1187
   286
    WSCONS_ReportError("ioctl SMODE");
icculus@1187
   287
    return -1;
icculus@1187
   288
  }
icculus@1187
   289
icculus@1187
   290
  pagemask = getpagesize() - 1;
icculus@1187
   291
  mapsize = ((int)len + pagemask) & ~pagemask;
icculus@1187
   292
  private->physmem = (Uint8 *)mmap(NULL, mapsize,
icculus@1187
   293
				   PROT_READ | PROT_WRITE, MAP_SHARED,
icculus@1187
   294
				   private->fd, (off_t)0);
icculus@1187
   295
  if (private->physmem == (Uint8 *)MAP_FAILED) {
icculus@1187
   296
    private->physmem = NULL;
icculus@1187
   297
    WSCONS_ReportError("mmap: %s", strerror(errno));
icculus@1187
   298
    return -1;
icculus@1187
   299
  }
icculus@1187
   300
  private->fbmem_len = len;
icculus@1187
   301
icculus@1187
   302
  if (private->rotate == WSCONS_ROTATE_CW || 
icculus@1187
   303
      private->rotate == WSCONS_ROTATE_CCW) {
icculus@1187
   304
    width = private->info.height;
icculus@1187
   305
    height = private->info.width;
icculus@1187
   306
  } else {
icculus@1187
   307
    width = private->info.width;
icculus@1187
   308
    height = private->info.height;
icculus@1187
   309
  }
icculus@1187
   310
icculus@1187
   311
  if (private->shadowFB) {
icculus@1187
   312
    private->shadowmem = (Uint8 *)malloc(len);
icculus@1187
   313
    if (private->shadowmem == NULL) {
icculus@1187
   314
      WSCONS_ReportError("No memory for shadow");
icculus@1187
   315
      return -1;
icculus@1187
   316
    }
icculus@1187
   317
    private->fbstart = private->shadowmem;
icculus@1187
   318
    private->fblinebytes = width * ((private->info.depth + 7) / 8);
icculus@1187
   319
  } else { 
icculus@1187
   320
    private->fbstart = private->physmem;
icculus@1187
   321
    private->fblinebytes = private->physlinebytes;
icculus@1187
   322
  }
icculus@1187
   323
  
icculus@1187
   324
  private->SDL_modelist[0] = (SDL_Rect *)malloc(sizeof(SDL_Rect));
icculus@1187
   325
  private->SDL_modelist[0]->w = width;
icculus@1187
   326
  private->SDL_modelist[0]->h = height;
icculus@1187
   327
icculus@1187
   328
  vformat->BitsPerPixel = private->info.depth;
icculus@1187
   329
  vformat->BytesPerPixel = private->info.depth / 8;
icculus@1187
   330
  
icculus@1187
   331
  if (WSCONS_InitKeyboard(this) == -1) {
icculus@1187
   332
    return -1;
icculus@1187
   333
  }
icculus@1187
   334
  
icculus@1187
   335
  return 0;
icculus@1187
   336
}
icculus@1187
   337
icculus@1187
   338
SDL_Rect **WSCONS_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags)
icculus@1187
   339
{
icculus@1187
   340
  if (format->BitsPerPixel == private->info.depth) {
icculus@1187
   341
    return private->SDL_modelist;
icculus@1187
   342
  } else {
icculus@1187
   343
    return NULL;
icculus@1187
   344
  }
icculus@1187
   345
}
icculus@1187
   346
icculus@1187
   347
SDL_Surface *WSCONS_SetVideoMode(_THIS, SDL_Surface *current,
icculus@1187
   348
				 int width, int height, int bpp, Uint32 flags)
icculus@1187
   349
{
icculus@1187
   350
  if (width != private->SDL_modelist[0]->w || 
icculus@1187
   351
      height != private->SDL_modelist[0]->h) {
icculus@1187
   352
    WSCONS_ReportError("Requested video mode %dx%d not supported.",
icculus@1187
   353
		       width, height);
icculus@1187
   354
    return NULL;
icculus@1187
   355
  }
icculus@1187
   356
  if (bpp != private->info.depth) {
icculus@1187
   357
    WSCONS_ReportError("Requested video depth %d bpp not supported.", bpp);
icculus@1187
   358
    return NULL;
icculus@1187
   359
  }
icculus@1187
   360
icculus@1187
   361
  if (!SDL_ReallocFormat(current, 
icculus@1187
   362
			 bpp, 
icculus@1187
   363
			 private->redMask,
icculus@1187
   364
			 private->greenMask,
icculus@1187
   365
			 private->blueMask,
icculus@1187
   366
			 0)) {
icculus@1187
   367
    WSCONS_ReportError("Couldn't allocate new pixel format");
icculus@1187
   368
    return NULL;
icculus@1187
   369
  }
icculus@1187
   370
icculus@1187
   371
  current->flags &= SDL_FULLSCREEN;
icculus@1187
   372
  if (private->shadowFB) {
icculus@1187
   373
    current->flags |= SDL_SWSURFACE;
icculus@1187
   374
  } else {
icculus@1187
   375
    current->flags |= SDL_HWSURFACE;
icculus@1187
   376
  }
icculus@1187
   377
  current->w = width;
icculus@1187
   378
  current->h = height;
icculus@1187
   379
  current->pitch = private->fblinebytes;
icculus@1187
   380
  current->pixels = private->fbstart;
icculus@1187
   381
icculus@1187
   382
  memset(private->fbstart, 0, private->fbmem_len);
icculus@1187
   383
icculus@1187
   384
  return current;
icculus@1187
   385
}
icculus@1187
   386
icculus@1187
   387
static int WSCONS_AllocHWSurface(_THIS, SDL_Surface *surface)
icculus@1187
   388
{
icculus@1187
   389
  return -1;
icculus@1187
   390
}
icculus@1187
   391
static void WSCONS_FreeHWSurface(_THIS, SDL_Surface *surface)
icculus@1187
   392
{
icculus@1187
   393
}
icculus@1187
   394
icculus@1187
   395
static int WSCONS_LockHWSurface(_THIS, SDL_Surface *surface)
icculus@1187
   396
{
icculus@1187
   397
  return 0;
icculus@1187
   398
}
icculus@1187
   399
icculus@1187
   400
static void WSCONS_UnlockHWSurface(_THIS, SDL_Surface *surface)
icculus@1187
   401
{
icculus@1187
   402
}
icculus@1187
   403
icculus@1187
   404
static void WSCONS_blit16(Uint8 *byte_src_pos,
icculus@1187
   405
			  int srcRightDelta, 
icculus@1187
   406
			  int srcDownDelta, 
icculus@1187
   407
			  Uint8 *byte_dst_pos,
icculus@1187
   408
			  int dst_linebytes,
icculus@1187
   409
			  int width,
icculus@1187
   410
			  int height)
icculus@1187
   411
{
icculus@1187
   412
  int w;
icculus@1187
   413
  Uint16 *src_pos = (Uint16 *)byte_src_pos;
icculus@1187
   414
  Uint16 *dst_pos = (Uint16 *)byte_dst_pos;
icculus@1187
   415
icculus@1187
   416
  while (height) {
icculus@1187
   417
    Uint16 *src = src_pos;
icculus@1187
   418
    Uint16 *dst = dst_pos;
icculus@1187
   419
    for (w = width; w != 0; w--) {
icculus@1187
   420
      *dst = *src;
icculus@1187
   421
      src += srcRightDelta;
icculus@1187
   422
      dst++;
icculus@1187
   423
    }
icculus@1187
   424
    dst_pos = (Uint16 *)((Uint8 *)dst_pos + dst_linebytes);
icculus@1187
   425
    src_pos += srcDownDelta;
icculus@1187
   426
    height--;
icculus@1187
   427
  }
icculus@1187
   428
}
icculus@1187
   429
icculus@1187
   430
#define BLOCKSIZE_W 32
icculus@1187
   431
#define BLOCKSIZE_H 32
icculus@1187
   432
icculus@1187
   433
static void WSCONS_blit16blocked(Uint8 *byte_src_pos,
icculus@1187
   434
				 int srcRightDelta, 
icculus@1187
   435
				 int srcDownDelta, 
icculus@1187
   436
				 Uint8 *byte_dst_pos,
icculus@1187
   437
				 int dst_linebytes,
icculus@1187
   438
				 int width,
icculus@1187
   439
				 int height)
icculus@1187
   440
{
icculus@1187
   441
  int w;
icculus@1187
   442
  Uint16 *src_pos = (Uint16 *)byte_src_pos;
icculus@1187
   443
  Uint16 *dst_pos = (Uint16 *)byte_dst_pos;
icculus@1187
   444
icculus@1187
   445
  while (height > 0) {
icculus@1187
   446
    Uint16 *src = src_pos;
icculus@1187
   447
    Uint16 *dst = dst_pos;
icculus@1187
   448
    for (w = width; w > 0; w -= BLOCKSIZE_W) {
icculus@1187
   449
      WSCONS_blit16((Uint8 *)src,
icculus@1187
   450
		    srcRightDelta,
icculus@1187
   451
		    srcDownDelta,
icculus@1187
   452
		    (Uint8 *)dst,
icculus@1187
   453
		    dst_linebytes,
icculus@1187
   454
		    min(w, BLOCKSIZE_W),
icculus@1187
   455
		    min(height, BLOCKSIZE_H));
icculus@1187
   456
      src += srcRightDelta * BLOCKSIZE_W;
icculus@1187
   457
      dst += BLOCKSIZE_W;
icculus@1187
   458
    }
icculus@1187
   459
    dst_pos = (Uint16 *)((Uint8 *)dst_pos + dst_linebytes * BLOCKSIZE_H);
icculus@1187
   460
    src_pos += srcDownDelta * BLOCKSIZE_H;
icculus@1187
   461
    height -= BLOCKSIZE_H;
icculus@1187
   462
  }
icculus@1187
   463
}
icculus@1187
   464
icculus@1187
   465
static void WSCONS_UpdateRects(_THIS, int numrects, SDL_Rect *rects)
icculus@1187
   466
{
icculus@1187
   467
  int width = private->SDL_modelist[0]->w;
icculus@1187
   468
  int height = private->SDL_modelist[0]->h;
icculus@1187
   469
  int bytesPerPixel = (private->info.depth + 7) / 8;
icculus@1187
   470
  int i;
icculus@1187
   471
icculus@1187
   472
  if (!private->shadowFB) {
icculus@1187
   473
    return;
icculus@1187
   474
  }
icculus@1187
   475
icculus@1187
   476
  if (private->info.depth != 16) {
icculus@1187
   477
    WSCONS_ReportError("Shadow copy only implemented for 16 bpp");
icculus@1187
   478
    return;
icculus@1187
   479
  }
icculus@1187
   480
icculus@1187
   481
  for (i = 0; i < numrects; i++) {
icculus@1187
   482
    int x1, y1, x2, y2;
icculus@1187
   483
    int scr_x1, scr_y1, scr_x2, scr_y2;
icculus@1187
   484
    int sha_x1, sha_y1;
icculus@1187
   485
    int shadowRightDelta;  /* Address change when moving right in dest */
icculus@1187
   486
    int shadowDownDelta;   /* Address change when moving down in dest */
icculus@1187
   487
    Uint8 *src_start;
icculus@1187
   488
    Uint8 *dst_start;
icculus@1187
   489
icculus@1187
   490
    x1 = rects[i].x; 
icculus@1187
   491
    y1 = rects[i].y;
icculus@1187
   492
    x2 = x1 + rects[i].w; 
icculus@1187
   493
    y2 = y1 + rects[i].h;
icculus@1187
   494
icculus@1187
   495
    if (x1 < 0) {
icculus@1187
   496
      x1 = 0;
icculus@1187
   497
    } else if (x1 > width) {
icculus@1187
   498
      x1 = width;
icculus@1187
   499
    }
icculus@1187
   500
    if (x2 < 0) {
icculus@1187
   501
      x2 = 0;
icculus@1187
   502
    } else if (x2 > width) {
icculus@1187
   503
      x2 = width;
icculus@1187
   504
    }
icculus@1187
   505
    if (y1 < 0) {
icculus@1187
   506
      y1 = 0;
icculus@1187
   507
    } else if (y1 > height) {
icculus@1187
   508
      y1 = height;
icculus@1187
   509
    }
icculus@1187
   510
    if (y2 < 0) {
icculus@1187
   511
      y2 = 0;
icculus@1187
   512
    } else if (y2 > height) {
icculus@1187
   513
      y2 = height;
icculus@1187
   514
    }
icculus@1187
   515
    if (x2 <= x1 || y2 <= y1) {
icculus@1187
   516
      continue;
icculus@1187
   517
    }
icculus@1187
   518
icculus@1187
   519
    switch (private->rotate) {
icculus@1187
   520
      case WSCONS_ROTATE_NONE:
icculus@1187
   521
	sha_x1 = scr_x1 = x1;
icculus@1187
   522
	sha_y1 = scr_y1 = y1;
icculus@1187
   523
	scr_x2 = x2;
icculus@1187
   524
	scr_y2 = y2;
icculus@1187
   525
	shadowRightDelta = 1;
icculus@1187
   526
	shadowDownDelta = width;
icculus@1187
   527
	break;
icculus@1187
   528
      case WSCONS_ROTATE_CCW:
icculus@1187
   529
	scr_x1 = y1;
icculus@1187
   530
	scr_y1 = width - x2;
icculus@1187
   531
	scr_x2 = y2;
icculus@1187
   532
	scr_y2 = width - x1;
icculus@1187
   533
	sha_x1 = x2 - 1;
icculus@1187
   534
	sha_y1 = y1;
icculus@1187
   535
	shadowRightDelta = width;
icculus@1187
   536
	shadowDownDelta = -1;
icculus@1187
   537
	break;
icculus@1187
   538
      case WSCONS_ROTATE_UD:
icculus@1187
   539
	scr_x1 = width - x2;
icculus@1187
   540
	scr_y1 = height - y2;
icculus@1187
   541
	scr_x2 = width - x1;
icculus@1187
   542
	scr_y2 = height - y1;
icculus@1187
   543
	sha_x1 = x2 - 1;
icculus@1187
   544
	sha_y1 = y2 - 1;
icculus@1187
   545
	shadowRightDelta = -1;
icculus@1187
   546
	shadowDownDelta = -width;
icculus@1187
   547
	break;
icculus@1187
   548
      case WSCONS_ROTATE_CW:
icculus@1187
   549
	scr_x1 = height - y2;
icculus@1187
   550
	scr_y1 = x1;
icculus@1187
   551
	scr_x2 = height - y1;
icculus@1187
   552
	scr_y2 = x2;
icculus@1187
   553
	sha_x1 = x1;
icculus@1187
   554
	sha_y1 = y2 - 1;
icculus@1187
   555
	shadowRightDelta = -width;
icculus@1187
   556
	shadowDownDelta = 1;
icculus@1187
   557
	break;
icculus@1187
   558
      default:
icculus@1187
   559
	WSCONS_ReportError("Unknown rotation");
icculus@1187
   560
	return;
icculus@1187
   561
    }
icculus@1187
   562
icculus@1187
   563
    src_start = private->shadowmem + (sha_y1 * width + sha_x1) * bytesPerPixel;
icculus@1187
   564
    dst_start = private->physmem + scr_y1 * private->physlinebytes + 
icculus@1187
   565
      scr_x1 * bytesPerPixel;
icculus@1187
   566
icculus@1187
   567
    private->blitFunc(src_start,
icculus@1187
   568
		      shadowRightDelta, 
icculus@1187
   569
		      shadowDownDelta, 
icculus@1187
   570
		      dst_start,
icculus@1187
   571
		      private->physlinebytes,
icculus@1187
   572
		      scr_x2 - scr_x1,
icculus@1187
   573
		      scr_y2 - scr_y1);
icculus@1187
   574
  }
icculus@1187
   575
}
icculus@1187
   576
icculus@1187
   577
int WSCONS_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors)
icculus@1187
   578
{
icculus@1187
   579
  return 0;
icculus@1187
   580
}
icculus@1187
   581
icculus@1187
   582
/*
icculus@1187
   583
 * Note: If we are terminated, this could be called in the middle of
icculus@1187
   584
 * another SDL video routine -- notably UpdateRects.
icculus@1187
   585
 */
icculus@1187
   586
void WSCONS_VideoQuit(_THIS)
icculus@1187
   587
{
icculus@1187
   588
  int mode = WSDISPLAYIO_MODE_EMUL;
icculus@1187
   589
icculus@1187
   590
  if (private->shadowmem != NULL) {
icculus@1187
   591
    free(private->shadowmem);
icculus@1187
   592
    private->shadowmem = NULL;
icculus@1187
   593
  }
icculus@1187
   594
  private->fbstart = NULL;
icculus@1187
   595
  if (this->screen != NULL) {
icculus@1187
   596
    this->screen->pixels = NULL;
icculus@1187
   597
  }
icculus@1187
   598
icculus@1187
   599
  if (private->SDL_modelist[0] != NULL) {
icculus@1187
   600
    free(private->SDL_modelist[0]);
icculus@1187
   601
    private->SDL_modelist[0] = NULL;
icculus@1187
   602
  }
icculus@1187
   603
icculus@1187
   604
  if (ioctl(private->fd, WSDISPLAYIO_SMODE, &mode) == -1) {
icculus@1187
   605
    WSCONS_ReportError("ioctl SMODE");
icculus@1187
   606
  }
icculus@1187
   607
icculus@1187
   608
  WSCONS_ReleaseKeyboard(this);
icculus@1187
   609
icculus@1187
   610
  if (private->fd != -1) {
icculus@1187
   611
    close(private->fd);
icculus@1187
   612
    private->fd = -1;
icculus@1187
   613
  }
icculus@1187
   614
}