[Scummvm-cvs-logs] CVS: scummvm/backends/sdl fb2opengl.h,1.1.1.1,1.2 sdl_gl.cpp,1.7,1.8

Max Horn fingolfin at users.sourceforge.net
Mon Oct 21 17:59:03 CEST 2002


Update of /cvsroot/scummvm/scummvm/backends/sdl
In directory usw-pr-cvs1:/tmp/cvs-serv7295/backends/sdl

Modified Files:
	fb2opengl.h sdl_gl.cpp 
Log Message:
patch #626629: add overlay support to SDL_g+OpenGL backend (still buggy!)

Index: fb2opengl.h
===================================================================
RCS file: /cvsroot/scummvm/scummvm/backends/sdl/fb2opengl.h,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -u -d -r1.1.1.1 -r1.2
--- fb2opengl.h	21 Aug 2002 16:07:15 -0000	1.1.1.1
+++ fb2opengl.h	22 Oct 2002 00:58:48 -0000	1.2
@@ -58,7 +58,6 @@
     char flags;
     void maketex();
     void makedlist(int xf, int yf);
-    void display();
 
   public:
     SDL_Surface *screen;
@@ -70,6 +69,8 @@
     void update(void *fb, int width, int height, int pitch, int xskip, int yskip);
     void palette(int index, int r, int g, int b);
     void setPalette(int first, int ncolors);
+    void update_scummvm_screen(void *fb, int width, int height, int pitch, int x, int y);
+    void display();
 };
 
 void FB2GL::maketex()
@@ -207,6 +208,11 @@
   maketex();
   makedlist(xfix, yfix);
 
+/*  glEnable(GL_ALPHA_TEST);
+  glEnable(GL_BLEND);
+  glAlphaFunc(GL_GREATER,0);
+  glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);*/
+  
   return 1;
 }
 
@@ -236,11 +242,13 @@
 	    ogl_fb1[y][x][0] = ogl_ctable[*(fb1+x)][0];
 	    ogl_fb1[y][x][1] = ogl_ctable[*(fb1+x)][1]; 
 	    ogl_fb1[y][x][2] = ogl_ctable[*(fb1+x)][2]; 
+	    ogl_fb1[y][x][3] = 255;
 	  }
 	  else {
 	    ogl_fb2[y][x-256][0] = ogl_ctable[*(fb1+x)][0]; 
 	    ogl_fb2[y][x-256][1] = ogl_ctable[*(fb1+x)][1]; 
 	    ogl_fb2[y][x-256][2] = ogl_ctable[*(fb1+x)][2]; 
+	    ogl_fb2[y][x-256][3] = 255;
 	  }
 	}
 	fb1 += scr_pitch;
@@ -307,6 +315,47 @@
 
   display();
 
+}
+
+void FB2GL::update_scummvm_screen(void *fb, int w, int h, int pitch, int xpos, int ypos) {
+  uint16 *fb1 = (uint16 *)(((SDL_Surface *)fb)->pixels);
+  int x, y;
+  unsigned char r, g, b, a;
+
+  for (y=0; y<h; y++) {
+    for (x=0; x<w; x++) {
+      
+      SDL_GetRGBA(fb1[x],((SDL_Surface *)fb)->format,&r,&g,&b,&a);
+      
+      if (x<256) { 
+	ogl_fb1[y][x][0] = r;
+	ogl_fb1[y][x][1] = g;
+	ogl_fb1[y][x][2] = b;
+	ogl_fb1[y][x][3] = a; // Alpha
+      }
+      else {
+	ogl_fb2[y][x-256][0] = r;
+	ogl_fb2[y][x-256][1] = g;
+	ogl_fb2[y][x-256][2] = b;
+	ogl_fb2[y][x-256][3] = a; // Alpha
+      }
+    }
+    fb1 += pitch;
+  }
+
+  // Update 256x256 texture
+  glBindTexture(GL_TEXTURE_2D,texture);
+  glFlush();
+  glTexSubImage2D(GL_TEXTURE_2D,0,xpos,ypos,256-xpos,256-ypos,GL_RGBA,
+    GL_UNSIGNED_BYTE,ogl_fb1);
+
+  // Update 64x256 texture
+  glBindTexture(GL_TEXTURE_2D,textureb);
+  glFlush();
+  glTexSubImage2D(GL_TEXTURE_2D,0,xpos,ypos,64-xpos,256-ypos,GL_RGBA,
+    GL_UNSIGNED_BYTE,ogl_fb2);
+ 
+  display();
 }
 
 void FB2GL::palette(int i, int r, int g, int b) {

Index: sdl_gl.cpp
===================================================================
RCS file: /cvsroot/scummvm/scummvm/backends/sdl/sdl_gl.cpp,v
retrieving revision 1.7
retrieving revision 1.8
diff -u -d -r1.7 -r1.8
--- sdl_gl.cpp	14 Oct 2002 11:02:27 -0000	1.7
+++ sdl_gl.cpp	22 Oct 2002 00:58:48 -0000	1.8
@@ -22,22 +22,20 @@
 
 #include "sdl-common.h"
 #include "common/scaler.h"
+#include "common/util.h"
 #include "common/engine.h"	// Only #included for error() and warning()
 
 #ifdef WIN32
 int glColorTable(int, int, int, int, int, void *) { return 0; }
 int glGetColorTable(int, int, int, void *) { return 0; }
-/* Use OpenGL 1.1 */
-bool OGL_1_1 = true;
-#else
-bool OGL_1_1 = false;
 #endif
 
 #include "fb2opengl.h"
 
-
-class OSystem_SDL_GL : public OSystem_SDL_Common {
+class OSystem_SDL_Normal : public OSystem_SDL_Common {
 public:
+	OSystem_SDL_Normal() : sdl_tmpscreen(0), sdl_hwscreen(0), _overlay_visible(false) {}
+
 	// Set colors of the palette
 	void set_palette(const byte *colors, uint start, uint num);
 
@@ -56,23 +54,38 @@
 
 protected:
 	FB2GL fb2gl;
+	typedef void ScalerProc(uint8 *srcPtr, uint32 srcPitch, uint8 *deltaPtr,
+								uint8 *dstPtr, uint32 dstPitch, int width, int height);
 
-	void load_gfx_mode();
-	void unload_gfx_mode();
+	SDL_Surface *sdl_tmpscreen;   // temporary screen (for scalers/overlay)
+	SDL_Surface *sdl_hwscreen;    // hardware screen
+	bool _overlay_visible;
+
+	ScalerProc *_scaler_proc;
+
+	virtual void draw_mouse();
+	virtual void undraw_mouse();
+
+	virtual void load_gfx_mode();
+	virtual void unload_gfx_mode();
 	void hotswap_gfx_mode();
+	
+	int TMP_SCREEN_WIDTH;
 };
 
 OSystem_SDL_Common *OSystem_SDL_Common::create() {
-	return new OSystem_SDL_GL();
+	return new OSystem_SDL_Normal();
 }
 
-void OSystem_SDL_GL::set_palette(const byte *colors, uint start, uint num) {
+void OSystem_SDL_Normal::set_palette(const byte *colors, uint start, uint num) {
 	const byte *b = colors;
 	uint i;
-
-	for(i=0;i!=num;i++) {
-	    fb2gl.palette(i+start,b[0],b[1],b[2]);
-	    b += 4;
+	SDL_Color *base = _currentPalette + start;
+	for(i = 0; i < num; i++) {
+		base[i].r = b[0];
+		base[i].g = b[1];
+		base[i].b = b[2];
+		b += 4;
 	}
 
 	if (start < _paletteDirtyStart)
@@ -82,74 +95,252 @@
 		_paletteDirtyEnd = start + num;
 }
 
-void OSystem_SDL_GL::load_gfx_mode() {
-	int gl_flags =  FB2GL_320 | FB2GL_PITCH; 
+void OSystem_SDL_Normal::draw_mouse() {
+	if (!_overlay_visible) {
+		OSystem_SDL_Common::draw_mouse();
+	}
+
+	if (_mouseDrawn || !_mouseVisible)
+		return;
+
+	int x = _mouse_cur_state.x - _mouseHotspotX;
+	int y = _mouse_cur_state.y - _mouseHotspotY;
+	int w = _mouse_cur_state.w;
+	int h = _mouse_cur_state.h;
+	byte color;
+	byte *src = _mouseData;		// Image representing the mouse
+	uint16 *bak = (uint16*)_mouseBackup;	// Surface used to backup the area obscured by the mouse
+	uint16 *dst;					// Surface we are drawing into
+
+	// clip the mouse rect, and addjust the src pointer accordingly
+	if (x < 0) {
+		w += x;
+		src -= x;
+		x = 0;
+	}
+	if (y < 0) {
+		h += y;
+		src -= y * _mouse_cur_state.w;
+		y = 0;
+	}
+
+	// Quick check to see if anything has to be drawn at all
+	if (w <= 0 || h <= 0)
+		return;
+
+	if (w > _screenWidth - x)
+		w = _screenWidth - x;
+	if (h > _screenHeight - y)
+		h = _screenHeight - y;
+
+	// Store the bounding box so that undraw mouse can restore the area the
+	// mouse currently covers to its original content.
+	_mouse_old_state.x = x;
+	_mouse_old_state.y = y;
+	_mouse_old_state.w = w;
+	_mouse_old_state.h = h;
+
+	// Draw the mouse cursor; backup the covered area in "bak"
+
+	if (SDL_LockSurface(sdl_tmpscreen) == -1)
+		error("SDL_LockSurface failed: %s.\n", SDL_GetError());
+
+	dst = (uint16 *)sdl_tmpscreen->pixels + (y+1) * TMP_SCREEN_WIDTH + (x+1);
+	while (h > 0) {
+		int width = w;
+		while (width > 0) {
+			*bak++ = *dst;
+			color = *src++;
+			if (color != 0xFF)	// 0xFF = transparent, don't draw
+				*dst = RGB_TO_16(_currentPalette[color].r, _currentPalette[color].g, _currentPalette[color].b);
+			dst++;
+			width--;
+		}
+		src += _mouse_cur_state.w - w;
+		bak += MAX_MOUSE_W - w;
+		dst += TMP_SCREEN_WIDTH - w;
+		h--;
+	}
+
+	SDL_UnlockSurface(sdl_tmpscreen);
+	
+	// Mark as dirty
+	add_dirty_rect(x, y, w, h);
+
+	// Finally, set the flag to indicate the mouse has been drawn
+	_mouseDrawn = true;
+}
+
+void OSystem_SDL_Normal::undraw_mouse() {
+	if (!_overlay_visible) {
+		OSystem_SDL_Common::undraw_mouse();
+	}
+
+	if (!_mouseDrawn)
+		return;
+	_mouseDrawn = false;
+
+	if (SDL_LockSurface(sdl_tmpscreen) == -1)
+		error("SDL_LockSurface failed: %s.\n", SDL_GetError());
+
+	uint16 *dst, *bak = (uint16 *)_mouseBackup;
+	const int old_mouse_x = _mouse_old_state.x;
+	const int old_mouse_y = _mouse_old_state.y;
+	const int old_mouse_w = _mouse_old_state.w;
+	const int old_mouse_h = _mouse_old_state.h;
+	int x, y;
+
+	// No need to do clipping here, since draw_mouse() did that already
+
+	dst = (uint16 *)sdl_tmpscreen->pixels + (old_mouse_y+1) * TMP_SCREEN_WIDTH + (old_mouse_x+1);
+	for (y = 0; y < old_mouse_h; ++y, bak += MAX_MOUSE_W, dst += TMP_SCREEN_WIDTH) {
+		for (x = 0; x < old_mouse_w; ++x) {
+			dst[x] = bak[x];
+		}
+	}
+
+	add_dirty_rect(old_mouse_x, old_mouse_y, old_mouse_w, old_mouse_h);
+
+	SDL_UnlockSurface(sdl_tmpscreen);
+}
+
+void OSystem_SDL_Normal::load_gfx_mode() {
 	_forceFull = true;
+	_mode_flags = DF_WANT_RECT_OPTIM | DF_UPDATE_EXPAND_1_PIXEL;
 	_scaleFactor = 2;
-	_mode_flags = 0;
+
+	sdl_tmpscreen = NULL;
+	TMP_SCREEN_WIDTH = (_screenWidth + 3);
 	
+	//
+	// Create the surface that contains the 8 bit game data
+	//
 	_screen = SDL_CreateRGBSurface(SDL_SWSURFACE, _screenWidth, _screenHeight, 8, 0, 0, 0, 0);
 	if (_screen == NULL)
-		error("_screen failed failed");
+		error("_screen failed");
 
-	_mode_flags = DF_WANT_RECT_OPTIM;
 
-	if (_full_screen) gl_flags |= (FB2GL_FS);
-	
-	if (OGL_1_1) { // OpenGL 1.1
-	  gl_flags |= (FB2GL_RGBA | FB2GL_EXPAND);
-	  fb2gl.init(640,480,0,70,gl_flags );
-	}
-	else { // OpenGL 1.2
-	  if (!fb2gl.init(640,480,0,70,gl_flags)) { // Try to use 8bpp textures
-	    gl_flags |= (FB2GL_RGBA | FB2GL_EXPAND); // using RGBA textures
-	    fb2gl.init(640,480,0,70,gl_flags);	
-	  }
-	}
+	//
+	// Create the surface that contains the scaled graphics in 16 bit mode
+	//
+
+	int gl_flags =  FB2GL_320 | FB2GL_PITCH | FB2GL_RGBA | FB2GL_EXPAND;
+        if (_full_screen) gl_flags |= (FB2GL_FS);
+	fb2gl.init(640,480,0,70,gl_flags); // 640x480 screen resolution
 
 	SDL_SetGamma(1.25,1.25,1.25);
+
+	
+	//
+	// Create the surface used for the graphics in 16 bit before scaling, and also the overlay
+	//
+
+	// Need some extra bytes around when using 2xSaI
+	uint16 *tmp_screen = (uint16*)calloc(TMP_SCREEN_WIDTH*(_screenHeight+3),sizeof(uint16));
+	sdl_tmpscreen = SDL_CreateRGBSurfaceFrom(tmp_screen,
+						TMP_SCREEN_WIDTH, _screenHeight + 3, 16, TMP_SCREEN_WIDTH*2,
+						fb2gl.screen->format->Rmask,
+						fb2gl.screen->format->Gmask,
+						fb2gl.screen->format->Bmask,
+						fb2gl.screen->format->Amask);
+
+	
+	if (sdl_tmpscreen == NULL)
+		error("sdl_tmpscreen failed");
+	
+	// keyboard cursor control, some other better place for it?
+	km.x_max = _screenWidth * _scaleFactor - 1;
+	km.y_max = _screenHeight * _scaleFactor - 1;
+	km.delay_time = 25;
+	km.last_time = 0;
+
 }
 
-void OSystem_SDL_GL::unload_gfx_mode() {
+void OSystem_SDL_Normal::unload_gfx_mode() {
 	if (_screen) {
 		SDL_FreeSurface(_screen);
 		_screen = NULL; 
 	}
-}
 
-void OSystem_SDL_GL::update_screen() {
+	if (sdl_hwscreen) {
+		SDL_FreeSurface(sdl_hwscreen); 
+		sdl_hwscreen = NULL;
+	}
+	
+	if (sdl_tmpscreen) {
+		free((uint16*)sdl_tmpscreen->pixels);
+		SDL_FreeSurface(sdl_tmpscreen);
+		sdl_tmpscreen = NULL;
+	}
+}
 
-	/* First make sure the mouse is drawn, if it should be drawn. */
-	draw_mouse();
+void OSystem_SDL_Normal::update_screen() {
 	
-	/* If the shake position changed, fill the dirty area with blackness */
+	// If the shake position changed, fill the dirty area with blackness
 	if (_currentShakePos != _newShakePos) {
+//		SDL_Rect blackrect = {0, 0, _screenWidth*_scaleFactor, _newShakePos*_scaleFactor};
+//		SDL_FillRect(sdl_hwscreen, &blackrect, 0);
 
 		_currentShakePos = _newShakePos;
 
+		_forceFull = true;
 	}
 
-	/* Palette update in case we are in "real" 8 bit color mode.
-	 * Must take place after the screen data was updated, since with
-	 * "real" 8bit mode, palatte changes may be visible immediatly,
-	 * and we want to avoid any ugly effects.
-	 */
+	// Make sure the mouse is drawn, if it should be drawn.
+	draw_mouse();
+	
+	// Check whether the palette was changed in the meantime and update the
+	// screen surface accordingly. 
 	if (_paletteDirtyEnd != 0) {
-                fb2gl.setPalette(_paletteDirtyStart, 
-		    _paletteDirtyEnd - _paletteDirtyStart);
+		SDL_SetColors(_screen, _currentPalette + _paletteDirtyStart, 
+			_paletteDirtyStart,
+			_paletteDirtyEnd - _paletteDirtyStart);
 		
 		_paletteDirtyEnd = 0;
+
+		_forceFull = true;
 	}
 
-	// FIXME - this seems to be tied to 320x200 - what about Zak256 which needs 320x240 ?
-	fb2gl.update(_screen->pixels,320,200,320,0,_currentShakePos);
+	// Force a full redraw if requested
+	if (_forceFull) {
+		_num_dirty_rects = 1;
 
+		_dirty_rect_list[0].x = 0;
+		_dirty_rect_list[0].y = 0;
+		_dirty_rect_list[0].w = _screenWidth;
+		_dirty_rect_list[0].h = _screenHeight;
+	}
+
+	// Only draw anything if necessary
+	if (_num_dirty_rects > 0) {
+	
+		SDL_Rect *r; 
+		SDL_Rect *last_rect = _dirty_rect_list + _num_dirty_rects;
+	
+		// Convert appropriate parts of the 8bpp image into 16bpp
+		if (!_overlay_visible) {
+			SDL_Rect dst;
+			for(r = _dirty_rect_list; r != last_rect; ++r) {
+				dst = *r;
+				dst.x++;	// Shift rect by one since 2xSai needs to acces the data around
+				dst.y++;	// any pixel to scale it, and we want to avoid mem access crashes.
+				if (SDL_BlitSurface(_screen, r, sdl_tmpscreen, &dst) != 0)
+					error("SDL_BlitSurface failed: %s", SDL_GetError());
+			}
+		}
+	
+		fb2gl.update_scummvm_screen((void *)sdl_tmpscreen,TMP_SCREEN_WIDTH,_screenHeight,TMP_SCREEN_WIDTH,0,_currentShakePos);
+		       
+	}
+
+	_num_dirty_rects = 0;
+	_forceFull = false;
 }
 
-void OSystem_SDL_GL::hotswap_gfx_mode() {
-	/* hmm, need to allocate a 320x200 bitmap
-	 * which will contain the "backup" of the screen during the change.
-	 * then draw that to the new screen right after it's setup.
+void OSystem_SDL_Normal::hotswap_gfx_mode() {
+	/* We allocate a screen sized bitmap which contains a "backup"
+	 * of the screen data during the change. Then we draw that to
+	 * the new screen right after it's setup.
 	 */
 	
 	byte *bak_mem = (byte*)malloc(_screenWidth*_screenHeight);
@@ -159,24 +350,135 @@
 	unload_gfx_mode();
 	load_gfx_mode();
 
-	fb2gl.setPalette(0,256);
-	// FIXME - this seems to be tied to 320x200 - what about Zak256 which needs 320x240 ?
-	fb2gl.update(_screen->pixels,320,200,320,0,_currentShakePos);
+	// reset palette
+	SDL_SetColors(_screen, _currentPalette, 0, 256);
 
-	/* blit image */
+	// blit image
 	copy_rect(bak_mem, _screenWidth, 0, 0, _screenWidth, _screenHeight);
 	free(bak_mem);
 
 	update_screen();
 }
 
-uint32 OSystem_SDL_GL::property(int param, Property *value) {
+uint32 OSystem_SDL_Normal::property(int param, Property *value) {
 
 	if (param == PROP_TOGGLE_FULLSCREEN) {
+//		assert(sdl_hwscreen != 0);
 		_full_screen ^= true;
+
+//		if (!SDL_WM_ToggleFullScreen(sdl_hwscreen)) {
+			// if ToggleFullScreen fails, achieve the same effect with hotswap gfx mode
+//			hotswap_gfx_mode();
+		  
+//		}
 		SDL_WM_ToggleFullScreen(fb2gl.screen);
 		return 1;
+	} else if (param == PROP_OVERLAY_IS_565) {
+		assert(sdl_tmpscreen != 0);
+		return (sdl_tmpscreen->format->Rmask != 0x7C00);
 	}
 	
 	return OSystem_SDL_Common::property(param, value);
 }
+
+
+void OSystem_SDL_Normal::show_overlay()
+{
+	// hide the mouse
+	undraw_mouse();
+
+	_overlay_visible = true;
+	clear_overlay();
+}
+
+void OSystem_SDL_Normal::hide_overlay()
+{
+	// hide the mouse
+	undraw_mouse();
+
+	_overlay_visible = false;
+	_forceFull = true;
+}
+
+void OSystem_SDL_Normal::clear_overlay()
+{
+	if (!_overlay_visible)
+		return;
+	
+	// hide the mouse
+	undraw_mouse();
+
+	// Clear the overlay by making the game screen "look through" everywhere.
+	SDL_Rect src, dst;
+	src.x = src.y = 0;
+	dst.x = dst.y = 1;
+	src.w = dst.w = _screenWidth;
+	src.h = dst.h = _screenHeight;
+	if (SDL_BlitSurface(_screen, &src, sdl_tmpscreen, &dst) != 0)
+		error("SDL_BlitSurface failed: %s", SDL_GetError());
+
+	_forceFull = true;
+}
+
+void OSystem_SDL_Normal::grab_overlay(int16 *buf, int pitch)
+{
+	if (!_overlay_visible)
+		return;
+
+	if (sdl_tmpscreen == NULL)
+		return;
+
+	// hide the mouse
+	undraw_mouse();
+
+	if (SDL_LockSurface(sdl_tmpscreen) == -1)
+		error("SDL_LockSurface failed: %s.\n", SDL_GetError());
+
+	int16 *src = (int16 *)sdl_tmpscreen->pixels + TMP_SCREEN_WIDTH + 1;
+	int h = _screenHeight;
+	do {
+		memcpy(buf, src, _screenWidth*2);
+		src += TMP_SCREEN_WIDTH;
+		buf += pitch;
+	} while (--h);
+
+	SDL_UnlockSurface(sdl_tmpscreen);
+}
+
+void OSystem_SDL_Normal::copy_rect_overlay(const int16 *buf, int pitch, int x, int y, int w, int h)
+{
+	if (!_overlay_visible)
+		return;
+
+	if (sdl_tmpscreen == NULL)
+		return;
+
+	// Clip the coordinates
+	if (x < 0) { w+=x; buf-=x; x = 0; }
+	if (y < 0) { h+=y; buf-=y*pitch; y = 0; }
+	if (w > _screenWidth-x) { w = _screenWidth - x; }
+	if (h > _screenHeight-y) { h = _screenHeight - y; }
+	if (w <= 0 || h <= 0)
+		return;
+	
+	// Mark the modified region as dirty
+	cksum_valid = false;
+	add_dirty_rect(x, y, w, h);
+
+	/* FIXME: undraw mouse only if the draw rect intersects with the mouse rect */
+	undraw_mouse();
+
+	if (SDL_LockSurface(sdl_tmpscreen) == -1)
+		error("SDL_LockSurface failed: %s.\n", SDL_GetError());
+
+	int16 *dst = (int16 *)sdl_tmpscreen->pixels + (y+1) * TMP_SCREEN_WIDTH + (x+1);
+	do {
+		memcpy(dst, buf, w*2);
+		dst += TMP_SCREEN_WIDTH;
+		buf += pitch;
+	} while (--h);
+
+	SDL_UnlockSurface(sdl_tmpscreen);
+}
+
+





More information about the Scummvm-git-logs mailing list