doomgeneric/frosted-doom/i_video_SDL.c

757 lines
16 KiB
C

// Emacs style mode select -*- C++ -*-
//-----------------------------------------------------------------------------
//
// $Id:$
//
// Copyright (C) 1993-1996 by id Software, Inc.
//
// This source is available for distribution and/or modification
// only under the terms of the DOOM Source Code License as
// published by id Software. All rights reserved.
//
// The source is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// FITNESS FOR A PARTICULAR PURPOSE. See the DOOM Source Code License
// for more details.
//
// $Log:$
//
// DESCRIPTION:
// DOOM graphics stuff for X11, UNIX.
//
//-----------------------------------------------------------------------------
static const char
rcsid[] = "$Id: i_x.c,v 1.6 1997/02/03 22:45:10 b1 Exp $";
#include <stdlib.h>
#include <unistd.h>
#include <stdarg.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <errno.h>
#include <signal.h>
#include <SDL2/SDL.h>
#include "doomstat.h"
#include "i_system.h"
#include "v_video.h"
#include "m_argv.h"
#include "d_main.h"
#include "doomdef.h"
SDL_Window *window = NULL;
SDL_Surface *screen = NULL;
SDL_Surface *rgbsurf = NULL;
int X_width;
int X_height;
void I_ShutdownGraphics(void)
{
printf("I_ShutdownGraphics\n");
// Always be sure to clean up
SDL_Quit();
}
//
// I_StartFrame
//
void I_StartFrame (void)
{
// er?
}
void I_GetEvent(void)
{
/* An SDL_Event */
SDL_Event event;
while (SDL_PollEvent(&event))
{
/* If a quit event has been sent */
if (event.type == SDL_QUIT)
{
/* Quit the application */
I_Quit();
}
if (event.type == SDL_WINDOWEVENT)
{
switch (event.window.event)
{
case SDL_WINDOWEVENT_CLOSE:
SDL_Log("Window %d closed", event.window.windowID);
break;
default:
break;
}
}
}
/*
event_t event;
// put event-grabbing stuff in here
XNextEvent(X_display, &X_event);
switch (X_event.type)
{
case KeyPress:
event.type = ev_keydown;
event.data1 = xlatekey();
D_PostEvent(&event);
// fprintf(stderr, "k");
break;
case KeyRelease:
event.type = ev_keyup;
event.data1 = xlatekey();
D_PostEvent(&event);
// fprintf(stderr, "ku");
break;
case ButtonPress:
event.type = ev_mouse;
event.data1 =
(X_event.xbutton.state & Button1Mask)
| (X_event.xbutton.state & Button2Mask ? 2 : 0)
| (X_event.xbutton.state & Button3Mask ? 4 : 0)
| (X_event.xbutton.button == Button1)
| (X_event.xbutton.button == Button2 ? 2 : 0)
| (X_event.xbutton.button == Button3 ? 4 : 0);
event.data2 = event.data3 = 0;
D_PostEvent(&event);
// fprintf(stderr, "b");
break;
case ButtonRelease:
event.type = ev_mouse;
event.data1 =
(X_event.xbutton.state & Button1Mask)
| (X_event.xbutton.state & Button2Mask ? 2 : 0)
| (X_event.xbutton.state & Button3Mask ? 4 : 0);
// suggest parentheses around arithmetic in operand of |
event.data1 =
event.data1
^ (X_event.xbutton.button == Button1 ? 1 : 0)
^ (X_event.xbutton.button == Button2 ? 2 : 0)
^ (X_event.xbutton.button == Button3 ? 4 : 0);
event.data2 = event.data3 = 0;
D_PostEvent(&event);
// fprintf(stderr, "bu");
break;
case MotionNotify:
event.type = ev_mouse;
event.data1 =
(X_event.xmotion.state & Button1Mask)
| (X_event.xmotion.state & Button2Mask ? 2 : 0)
| (X_event.xmotion.state & Button3Mask ? 4 : 0);
event.data2 = (X_event.xmotion.x - lastmousex) << 2;
event.data3 = (lastmousey - X_event.xmotion.y) << 2;
if (event.data2 || event.data3)
{
lastmousex = X_event.xmotion.x;
lastmousey = X_event.xmotion.y;
if (X_event.xmotion.x != X_width/2 &&
X_event.xmotion.y != X_height/2)
{
D_PostEvent(&event);
// fprintf(stderr, "m");
mousemoved = false;
} else
{
mousemoved = true;
}
}
break;
case Expose:
case ConfigureNotify:
break;
default:
if (doShm && X_event.type == X_shmeventtype) shmFinished = true;
break;
}
*/
}
// Cursor
// createnullcursor
// ( Display* display,
// Window root )
// {
// Pixmap cursormask;
// XGCValues xgc;
// GC gc;
// XColor dummycolour;
// Cursor cursor;
//
// cursormask = XCreatePixmap(display, root, 1, 1, 1/*depth*/);
// xgc.function = GXclear;
// gc = XCreateGC(display, cursormask, GCFunction, &xgc);
// XFillRectangle(display, cursormask, gc, 0, 0, 1, 1);
// dummycolour.pixel = 0;
// dummycolour.red = 0;
// dummycolour.flags = 04;
// cursor = XCreatePixmapCursor(display, cursormask, cursormask,
// &dummycolour,&dummycolour, 0,0);
// XFreePixmap(display,cursormask);
// XFreeGC(display,gc);
// return cursor;
// }
//
// I_StartTic
//
void I_StartTic (void)
{
return;
/*
if (!X_display)
return;
while (XPending(X_display))
I_GetEvent();
// Warp the pointer back to the middle of the window
// or it will wander off - that is, the game will
// loose input focus within X11.
if (grabMouse)
{
if (!--doPointerWarp)
{
XWarpPointer( X_display,
None,
X_mainWindow,
0, 0,
0, 0,
X_width/2, X_height/2);
doPointerWarp = POINTER_WARP_COUNTDOWN;
}
}
mousemoved = false;
*/
}
//
// I_UpdateNoBlit
//
void I_UpdateNoBlit (void)
{
// what is this?
}
//
// I_FinishUpdate
//
void I_FinishUpdate (void)
{
static int lasttic;
int tics;
int i;
// draws little dots on the bottom of the screen
if (devparm)
{
i = I_GetTime();
tics = i - lasttic;
lasttic = i;
if (tics > 20) tics = 20;
for (i=0 ; i<tics*2 ; i+=2)
screens[0][ (SCREENHEIGHT-1)*SCREENWIDTH + i] = 0xff;
for ( ; i<20*2 ; i+=2)
screens[0][ (SCREENHEIGHT-1)*SCREENWIDTH + i] = 0x0;
}
/* DRAW SCREEN */
//if (multiply == 1)
{
unsigned char *line_out;
unsigned char *line_in;
int y;
line_in = (unsigned char *) screens[0];
line_out = (unsigned char *) rgbsurf->pixels;
y = SCREENHEIGHT;
while (y--)
{
memcpy(line_out, line_in, rgbsurf->w);
line_in += SCREENWIDTH;
line_out += rgbsurf->pitch;
}
}
/* LOCK SCREEN */
if (SDL_MUSTLOCK(screen)) {
if (SDL_LockSurface(screen) < 0) {
return;
}
}
/* BLIT to SCREEN */
SDL_BlitSurface(rgbsurf, NULL, screen, NULL); // blit it to the screen
/* UNLOCK SCREEN */
if ( SDL_MUSTLOCK(screen) ) {
SDL_UnlockSurface(screen);
}
SDL_UpdateWindowSurface(window);
}
//
// I_ReadScreen
//
void I_ReadScreen (byte* scr)
{
printf("I_ReadScreen\n");
memcpy (scr, screens[0], SCREENWIDTH*SCREENHEIGHT);
//memcpy (scr, screens[0], SCREENWIDTH*SCREENHEIGHT);
}
//
// I_SetPalette
//
void I_SetPalette (byte* palette)
{
SDL_Color colors[256];
printf("I_SetPalette\n");
for (int i=0; i<256; ++i ) {
colors[i].r = gammatable[usegamma][*palette++];
colors[i].g = gammatable[usegamma][*palette++];
colors[i].b = gammatable[usegamma][*palette++];
}
if(rgbsurf->format->BitsPerPixel!=8){
printf("Not an 8-bit surface.\n");
return;
}
int j = SDL_SetPaletteColors(rgbsurf->format->palette, colors, 0, 256);
printf("SDL_SetPaletteColors: %i\n", j);
}
void I_InitGraphics(void)
{
uint32_t video_flags = 0;
//video_flags = (SDL_SWSURFACE|SDL_HWPALETTE);
if (M_CheckParm("-fullscreen"))
video_flags |= SDL_WINDOW_FULLSCREEN;
X_width = SCREENWIDTH;
X_height = SCREENHEIGHT;
printf("I_InitGraphics: w x h: %d x %d\n", X_width, X_height);
// Initialize SDL.
if (SDL_Init(SDL_INIT_VIDEO) < 0)
{
printf("SDL_Init failed\n");
return;
}
// Create the window where we will draw.
window = SDL_CreateWindow("fDOOM v1.0",
SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
X_width, X_height,
video_flags);
screen = SDL_GetWindowSurface(window);
rgbsurf = SDL_CreateRGBSurface(0,X_width,X_height,8,0,0,0,0);
screens[0] = (unsigned char *)screen->pixels;
/* Blit shit to the screen */
// image = SDL_LoadBMP("box.bmp"); // loads image
// SDL_BlitSurface(image, NULL, screen, NULL); // blit it to the screen
// SDL_FreeSurface(image);
// SDL_UpdateWindowSurface(window);
signal(SIGINT, (void (*)(int)) I_Quit);
return;
/*
char* displayname;
char* d;
int n;
int pnum;
int x=0;
int y=0;
// warning: char format, different type arg
char xsign=' ';
char ysign=' ';
int oktodraw;
unsigned long attribmask;
XSetWindowAttributes attribs;
XGCValues xgcvalues;
int valuemask;
static int firsttime=1;
if (!firsttime)
return;
firsttime = 0;
signal(SIGINT, (void (*)(int)) I_Quit);
if (M_CheckParm("-2"))
multiply = 2;
if (M_CheckParm("-3"))
multiply = 3;
if (M_CheckParm("-4"))
multiply = 4;
X_width = SCREENWIDTH * multiply;
X_height = SCREENHEIGHT * multiply;
// check for command-line display name
if ( (pnum=M_CheckParm("-disp")) ) // suggest parentheses around assignment
displayname = myargv[pnum+1];
else
displayname = 0;
// check if the user wants to grab the mouse (quite unnice)
grabMouse = !!M_CheckParm("-grabmouse");
// check for command-line geometry
if ( (pnum=M_CheckParm("-geom")) ) // suggest parentheses around assignment
{
// warning: char format, different type arg 3,5
n = sscanf(myargv[pnum+1], "%c%d%c%d", &xsign, &x, &ysign, &y);
if (n==2)
x = y = 0;
else if (n==6)
{
if (xsign == '-')
x = -x;
if (ysign == '-')
y = -y;
}
else
I_Error("bad -geom parameter");
}
// open the display
X_display = XOpenDisplay(displayname);
if (!X_display)
{
if (displayname)
I_Error("Could not open display [%s]", displayname);
else
I_Error("Could not open display (DISPLAY=[%s])", getenv("DISPLAY"));
}
// use the default visual
X_screen = DefaultScreen(X_display);
if (!XMatchVisualInfo(X_display, X_screen, 8, PseudoColor, &X_visualinfo))
I_Error("xdoom currently only supports 256-color PseudoColor screens");
X_visual = X_visualinfo.visual;
// check for the MITSHM extension
doShm = XShmQueryExtension(X_display);
// even if it's available, make sure it's a local connection
if (doShm)
{
if (!displayname) displayname = (char *) getenv("DISPLAY");
if (displayname)
{
d = displayname;
while (*d && (*d != ':')) d++;
if (*d) *d = 0;
if (!(!strcasecmp(displayname, "unix") || !*displayname)) doShm = false;
}
}
fprintf(stderr, "Using MITSHM extension\n");
// create the colormap
X_cmap = XCreateColormap(X_display, RootWindow(X_display,
X_screen), X_visual, AllocAll);
// setup attributes for main window
attribmask = CWEventMask | CWColormap | CWBorderPixel;
attribs.event_mask =
KeyPressMask
| KeyReleaseMask
// | PointerMotionMask | ButtonPressMask | ButtonReleaseMask
| ExposureMask;
attribs.colormap = X_cmap;
attribs.border_pixel = 0;
// create the main window
X_mainWindow = XCreateWindow( X_display,
RootWindow(X_display, X_screen),
x, y,
X_width, X_height,
0, // borderwidth
8, // depth
InputOutput,
X_visual,
attribmask,
&attribs );
XDefineCursor(X_display, X_mainWindow,
createnullcursor( X_display, X_mainWindow ) );
// create the GC
valuemask = GCGraphicsExposures;
xgcvalues.graphics_exposures = False;
X_gc = XCreateGC( X_display,
X_mainWindow,
valuemask,
&xgcvalues );
// map the window
XMapWindow(X_display, X_mainWindow);
// wait until it is OK to draw
oktodraw = 0;
while (!oktodraw)
{
XNextEvent(X_display, &X_event);
if (X_event.type == Expose
&& !X_event.xexpose.count)
{
oktodraw = 1;
}
}
// grabs the pointer so it is restricted to this window
if (grabMouse)
XGrabPointer(X_display, X_mainWindow, True,
ButtonPressMask|ButtonReleaseMask|PointerMotionMask,
GrabModeAsync, GrabModeAsync,
X_mainWindow, None, CurrentTime);
if (doShm)
{
X_shmeventtype = XShmGetEventBase(X_display) + ShmCompletion;
// create the image
image = XShmCreateImage( X_display,
X_visual,
8,
ZPixmap,
0,
&X_shminfo,
X_width,
X_height );
grabsharedmemory(image->bytes_per_line * image->height);
// UNUSED
// create the shared memory segment
// X_shminfo.shmid = shmget (IPC_PRIVATE,
// image->bytes_per_line * image->height, IPC_CREAT | 0777);
// if (X_shminfo.shmid < 0)
// {
// perror("");
// I_Error("shmget() failed in InitGraphics()");
// }
// fprintf(stderr, "shared memory id=%d\n", X_shminfo.shmid);
// attach to the shared memory segment
// image->data = X_shminfo.shmaddr = shmat(X_shminfo.shmid, 0, 0);
if (!image->data)
{
perror("");
I_Error("shmat() failed in InitGraphics()");
}
// get the X server to attach to it
if (!XShmAttach(X_display, &X_shminfo))
I_Error("XShmAttach() failed in InitGraphics()");
}
else
{
image = XCreateImage( X_display,
X_visual,
8,
ZPixmap,
0,
(char*)malloc(X_width * X_height),
X_width, X_height,
8,
X_width );
}
if (multiply == 1)
screens[0] = (unsigned char *) (image->data);
else
screens[0] = (unsigned char *) malloc (SCREENWIDTH * SCREENHEIGHT);
*/
}
void InitExpand (void)
{
/*
int i;
for (i=0 ; i<256 ; i++)
exptable[i] = i | (i<<8) | (i<<16) | (i<<24);
*/
}
void InitExpand2 (void)
{
return;
/*
int i;
int j;
// UNUSED unsigned iexp, jexp;
double* exp;
union
{
double d;
unsigned u[2];
} pixel;
printf ("building exptable2...\n");
exp = exptable2;
for (i=0 ; i<256 ; i++)
{
pixel.u[0] = i | (i<<8) | (i<<16) | (i<<24);
for (j=0 ; j<256 ; j++)
{
pixel.u[1] = j | (j<<8) | (j<<16) | (j<<24);
*exp++ = pixel.d;
}
}
printf ("done.\n");
*/
}
int inited;
void
Expand4
( unsigned* lineptr,
double* xline )
{
return;
/*
double dpixel;
unsigned x;
unsigned y;
unsigned fourpixels;
unsigned step;
double* exp;
exp = exptable2;
if (!inited)
{
inited = 1;
InitExpand2 ();
}
step = 3*SCREENWIDTH/2;
y = SCREENHEIGHT-1;
do
{
x = SCREENWIDTH;
do
{
fourpixels = lineptr[0];
dpixel = *(double *)( (int)exp + ( (fourpixels&0xffff0000)>>13) );
xline[0] = dpixel;
xline[160] = dpixel;
xline[320] = dpixel;
xline[480] = dpixel;
dpixel = *(double *)( (int)exp + ( (fourpixels&0xffff)<<3 ) );
xline[1] = dpixel;
xline[161] = dpixel;
xline[321] = dpixel;
xline[481] = dpixel;
fourpixels = lineptr[1];
dpixel = *(double *)( (int)exp + ( (fourpixels&0xffff0000)>>13) );
xline[2] = dpixel;
xline[162] = dpixel;
xline[322] = dpixel;
xline[482] = dpixel;
dpixel = *(double *)( (int)exp + ( (fourpixels&0xffff)<<3 ) );
xline[3] = dpixel;
xline[163] = dpixel;
xline[323] = dpixel;
xline[483] = dpixel;
fourpixels = lineptr[2];
dpixel = *(double *)( (int)exp + ( (fourpixels&0xffff0000)>>13) );
xline[4] = dpixel;
xline[164] = dpixel;
xline[324] = dpixel;
xline[484] = dpixel;
dpixel = *(double *)( (int)exp + ( (fourpixels&0xffff)<<3 ) );
xline[5] = dpixel;
xline[165] = dpixel;
xline[325] = dpixel;
xline[485] = dpixel;
fourpixels = lineptr[3];
dpixel = *(double *)( (int)exp + ( (fourpixels&0xffff0000)>>13) );
xline[6] = dpixel;
xline[166] = dpixel;
xline[326] = dpixel;
xline[486] = dpixel;
dpixel = *(double *)( (int)exp + ( (fourpixels&0xffff)<<3 ) );
xline[7] = dpixel;
xline[167] = dpixel;
xline[327] = dpixel;
xline[487] = dpixel;
lineptr+=4;
xline+=8;
} while (x-=16);
xline += step;
} while (y--);
*/
}