mirror of
https://github.com/libretro/scummvm.git
synced 2024-12-03 15:41:41 +00:00
changed OSystem to allow RBG<->16bit color conversion to be done in the backend; after all, the backend 'knows' best what format the overlay uses. Default implementations of RBGToColor and colorToRBG assume 565 mode, backends other than SDL may want to provide alternate implementations (SDL backend already does the right thing for non-565 modes)
svn-id: r5931
This commit is contained in:
parent
7bcbcde994
commit
4bf96d1c8b
@ -22,8 +22,8 @@
|
||||
// Andre Souza <asouza@olinux.com.br>
|
||||
|
||||
#include <SDL.h>
|
||||
//#include <SDL_opengl.h>
|
||||
#include <GL/gl.h>
|
||||
#include <SDL_opengl.h>
|
||||
//#include <GL/gl.h> NOTE! Before anybody comments out SDL_opengl.h and enables this again, talk to Fingolfin first! GL/gl.h is NOT portable!
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
|
@ -45,6 +45,10 @@ public:
|
||||
virtual void grab_overlay(int16 *buf, int pitch);
|
||||
virtual void copy_rect_overlay(const int16 *buf, int pitch, int x, int y, int w, int h);
|
||||
|
||||
// Methods that convert RBG to/from colors suitable for the overlay.
|
||||
virtual int16 RBGToColor(uint8 r, uint8 g, uint8 b);
|
||||
virtual void colorToRBG(int16 color, uint8 &r, uint8 &g, uint8 &b);
|
||||
|
||||
protected:
|
||||
typedef void ScalerProc(uint8 *srcPtr, uint32 srcPitch, uint8 *deltaPtr,
|
||||
uint8 *dstPtr, uint32 dstPitch, int width, int height);
|
||||
@ -153,7 +157,7 @@ void OSystem_SDL_Normal::draw_mouse() {
|
||||
*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 = RBGToColor(_currentPalette[color].r, _currentPalette[color].g, _currentPalette[color].b);
|
||||
dst++;
|
||||
width--;
|
||||
}
|
||||
@ -466,14 +470,20 @@ uint32 OSystem_SDL_Normal::property(int param, Property *value) {
|
||||
}
|
||||
#endif
|
||||
return 1;
|
||||
} else if (param == PROP_OVERLAY_IS_565) {
|
||||
assert(_tmpscreen != 0);
|
||||
return (_tmpscreen->format->Rmask != 0x7C00);
|
||||
}
|
||||
|
||||
return OSystem_SDL_Common::property(param, value);
|
||||
}
|
||||
|
||||
int16 OSystem_SDL_Normal::RBGToColor(uint8 r, uint8 g, uint8 b)
|
||||
{
|
||||
return SDL_MapRGB(_tmpscreen->format, r, g, b);
|
||||
}
|
||||
|
||||
void OSystem_SDL_Normal::colorToRBG(int16 color, uint8 &r, uint8 &g, uint8 &b)
|
||||
{
|
||||
SDL_GetRGB(color, _tmpscreen->format, &r, &g, &b);
|
||||
}
|
||||
|
||||
void OSystem_SDL_Normal::show_overlay()
|
||||
{
|
||||
|
@ -34,7 +34,7 @@ int glGetColorTable(int, int, int, void *) { return 0; }
|
||||
|
||||
class OSystem_SDL_Normal : public OSystem_SDL_Common {
|
||||
public:
|
||||
OSystem_SDL_Normal() : sdl_tmpscreen(0), sdl_hwscreen(0), _overlay_visible(false) { _glScreenStart = 0; _glBilinearFilter = true; }
|
||||
OSystem_SDL_Normal() : _tmpscreen(0), _overlay_visible(false) { _glScreenStart = 0; _glBilinearFilter = true; }
|
||||
|
||||
// Set colors of the palette
|
||||
void set_palette(const byte *colors, uint start, uint num);
|
||||
@ -63,12 +63,9 @@ protected:
|
||||
typedef void ScalerProc(uint8 *srcPtr, uint32 srcPitch, uint8 *deltaPtr,
|
||||
uint8 *dstPtr, uint32 dstPitch, int width, int height);
|
||||
|
||||
SDL_Surface *sdl_tmpscreen; // temporary screen (for scalers/overlay)
|
||||
SDL_Surface *sdl_hwscreen; // hardware screen
|
||||
SDL_Surface *_tmpscreen; // temporary screen (for scalers/overlay)
|
||||
bool _overlay_visible;
|
||||
|
||||
ScalerProc *_scaler_proc;
|
||||
|
||||
virtual void draw_mouse();
|
||||
virtual void undraw_mouse();
|
||||
|
||||
@ -148,17 +145,20 @@ void OSystem_SDL_Normal::draw_mouse() {
|
||||
|
||||
// Draw the mouse cursor; backup the covered area in "bak"
|
||||
|
||||
if (SDL_LockSurface(sdl_tmpscreen) == -1)
|
||||
if (SDL_LockSurface(_tmpscreen) == -1)
|
||||
error("SDL_LockSurface failed: %s.\n", SDL_GetError());
|
||||
|
||||
dst = (uint16 *)sdl_tmpscreen->pixels + (y+1) * TMP_SCREEN_WIDTH + (x+1);
|
||||
// Mark as dirty
|
||||
add_dirty_rect(x, y, w, h);
|
||||
|
||||
dst = (uint16 *)_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 = RBGToColor(_currentPalette[color].r, _currentPalette[color].g, _currentPalette[color].b);
|
||||
dst++;
|
||||
width--;
|
||||
}
|
||||
@ -168,11 +168,8 @@ void OSystem_SDL_Normal::draw_mouse() {
|
||||
h--;
|
||||
}
|
||||
|
||||
SDL_UnlockSurface(sdl_tmpscreen);
|
||||
SDL_UnlockSurface(_tmpscreen);
|
||||
|
||||
// Mark as dirty
|
||||
add_dirty_rect(x, y, w, h);
|
||||
|
||||
// Finally, set the flag to indicate the mouse has been drawn
|
||||
_mouseDrawn = true;
|
||||
}
|
||||
@ -186,7 +183,7 @@ void OSystem_SDL_Normal::undraw_mouse() {
|
||||
return;
|
||||
_mouseDrawn = false;
|
||||
|
||||
if (SDL_LockSurface(sdl_tmpscreen) == -1)
|
||||
if (SDL_LockSurface(_tmpscreen) == -1)
|
||||
error("SDL_LockSurface failed: %s.\n", SDL_GetError());
|
||||
|
||||
uint16 *dst, *bak = (uint16 *)_mouseBackup;
|
||||
@ -198,7 +195,7 @@ void OSystem_SDL_Normal::undraw_mouse() {
|
||||
|
||||
// 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);
|
||||
dst = (uint16 *)_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];
|
||||
@ -207,7 +204,7 @@ void OSystem_SDL_Normal::undraw_mouse() {
|
||||
|
||||
add_dirty_rect(old_mouse_x, old_mouse_y, old_mouse_w, old_mouse_h);
|
||||
|
||||
SDL_UnlockSurface(sdl_tmpscreen);
|
||||
SDL_UnlockSurface(_tmpscreen);
|
||||
}
|
||||
|
||||
void OSystem_SDL_Normal::load_gfx_mode() {
|
||||
@ -223,7 +220,7 @@ void OSystem_SDL_Normal::load_gfx_mode() {
|
||||
_mode_flags = DF_WANT_RECT_OPTIM | DF_UPDATE_EXPAND_1_PIXEL;
|
||||
_scaleFactor = 2;
|
||||
|
||||
sdl_tmpscreen = NULL;
|
||||
_tmpscreen = NULL;
|
||||
TMP_SCREEN_WIDTH = (_screenWidth + 3);
|
||||
|
||||
//
|
||||
@ -255,7 +252,7 @@ void OSystem_SDL_Normal::load_gfx_mode() {
|
||||
|
||||
// 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,
|
||||
_tmpscreen = SDL_CreateRGBSurfaceFrom(tmp_screen,
|
||||
TMP_SCREEN_WIDTH, _screenHeight + 3, 16, TMP_SCREEN_WIDTH*2,
|
||||
Rmask,
|
||||
Gmask,
|
||||
@ -276,8 +273,8 @@ void OSystem_SDL_Normal::load_gfx_mode() {
|
||||
tmpBlackRect.w = _screenWidth;
|
||||
tmpBlackRect.h = 256-_screenHeight-_glScreenStart;
|
||||
|
||||
if (sdl_tmpscreen == NULL)
|
||||
error("sdl_tmpscreen failed");
|
||||
if (_tmpscreen == NULL)
|
||||
error("_tmpscreen failed");
|
||||
|
||||
// keyboard cursor control, some other better place for it?
|
||||
km.x_max = _screenWidth * _scaleFactor - 1;
|
||||
@ -293,10 +290,10 @@ void OSystem_SDL_Normal::unload_gfx_mode() {
|
||||
_screen = NULL;
|
||||
}
|
||||
|
||||
if (sdl_tmpscreen) {
|
||||
free((uint16*)sdl_tmpscreen->pixels);
|
||||
SDL_FreeSurface(sdl_tmpscreen);
|
||||
sdl_tmpscreen = NULL;
|
||||
if (_tmpscreen) {
|
||||
free((uint16*)_tmpscreen->pixels);
|
||||
SDL_FreeSurface(_tmpscreen);
|
||||
_tmpscreen = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
@ -352,13 +349,13 @@ void OSystem_SDL_Normal::update_screen() {
|
||||
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)
|
||||
if (SDL_BlitSurface(_screen, r, _tmpscreen, &dst) != 0)
|
||||
error("SDL_BlitSurface failed: %s", SDL_GetError());
|
||||
}
|
||||
}
|
||||
|
||||
// Almost the same thing as SDL_UpdateRects
|
||||
fb2gl.blit16(sdl_tmpscreen,_num_dirty_rects,_dirty_rect_list,0,
|
||||
fb2gl.blit16(_tmpscreen,_num_dirty_rects,_dirty_rect_list,0,
|
||||
_currentShakePos+_glScreenStart);
|
||||
|
||||
tmpBlackRect.h = 256-_screenHeight-_glScreenStart-_currentShakePos;
|
||||
@ -403,9 +400,6 @@ uint32 OSystem_SDL_Normal::property(int param, Property *value) {
|
||||
|
||||
SDL_WM_ToggleFullScreen(fb2gl.screen);
|
||||
return 1;
|
||||
} else if (param == PROP_OVERLAY_IS_565) {
|
||||
assert(sdl_tmpscreen != 0);
|
||||
return (sdl_tmpscreen->format->Rmask != 0x7C00);
|
||||
}
|
||||
else if (param == PROP_SET_GFX_MODE) {
|
||||
SDL_Rect full = {0,0,_screenWidth,_screenHeight};
|
||||
@ -455,7 +449,7 @@ uint32 OSystem_SDL_Normal::property(int param, Property *value) {
|
||||
1.0+(double)(value->gfx_mode-1)/10,
|
||||
0);
|
||||
};
|
||||
fb2gl.blit16(sdl_tmpscreen,1,&full,0,_glScreenStart);
|
||||
fb2gl.blit16(_tmpscreen,1,&full,0,_glScreenStart);
|
||||
fb2gl.display();
|
||||
|
||||
return 1;
|
||||
@ -499,7 +493,7 @@ void OSystem_SDL_Normal::clear_overlay()
|
||||
dst.x = dst.y = 0;
|
||||
src.w = dst.w = _screenWidth;
|
||||
src.h = dst.h = _screenHeight;
|
||||
if (SDL_BlitSurface(_screen, &src, sdl_tmpscreen, &dst) != 0)
|
||||
if (SDL_BlitSurface(_screen, &src, _tmpscreen, &dst) != 0)
|
||||
error("SDL_BlitSurface failed: %s", SDL_GetError());
|
||||
|
||||
_forceFull = true;
|
||||
@ -510,16 +504,16 @@ void OSystem_SDL_Normal::grab_overlay(int16 *buf, int pitch)
|
||||
if (!_overlay_visible)
|
||||
return;
|
||||
|
||||
if (sdl_tmpscreen == NULL)
|
||||
if (_tmpscreen == NULL)
|
||||
return;
|
||||
|
||||
// hide the mouse
|
||||
undraw_mouse();
|
||||
|
||||
if (SDL_LockSurface(sdl_tmpscreen) == -1)
|
||||
if (SDL_LockSurface(_tmpscreen) == -1)
|
||||
error("SDL_LockSurface failed: %s.\n", SDL_GetError());
|
||||
|
||||
int16 *src = (int16 *)sdl_tmpscreen->pixels + TMP_SCREEN_WIDTH + 1;
|
||||
int16 *src = (int16 *)_tmpscreen->pixels + TMP_SCREEN_WIDTH + 1;
|
||||
int h = _screenHeight;
|
||||
do {
|
||||
memcpy(buf, src, _screenWidth*2);
|
||||
@ -527,7 +521,7 @@ void OSystem_SDL_Normal::grab_overlay(int16 *buf, int pitch)
|
||||
buf += pitch;
|
||||
} while (--h);
|
||||
|
||||
SDL_UnlockSurface(sdl_tmpscreen);
|
||||
SDL_UnlockSurface(_tmpscreen);
|
||||
}
|
||||
|
||||
void OSystem_SDL_Normal::copy_rect_overlay(const int16 *buf, int pitch, int x, int y, int w, int h)
|
||||
@ -535,7 +529,7 @@ void OSystem_SDL_Normal::copy_rect_overlay(const int16 *buf, int pitch, int x, i
|
||||
if (!_overlay_visible)
|
||||
return;
|
||||
|
||||
if (sdl_tmpscreen == NULL)
|
||||
if (_tmpscreen == NULL)
|
||||
return;
|
||||
|
||||
// Clip the coordinates
|
||||
@ -553,17 +547,17 @@ void OSystem_SDL_Normal::copy_rect_overlay(const int16 *buf, int pitch, int x, i
|
||||
/* FIXME: undraw mouse only if the draw rect intersects with the mouse rect */
|
||||
undraw_mouse();
|
||||
|
||||
if (SDL_LockSurface(sdl_tmpscreen) == -1)
|
||||
if (SDL_LockSurface(_tmpscreen) == -1)
|
||||
error("SDL_LockSurface failed: %s.\n", SDL_GetError());
|
||||
|
||||
int16 *dst = (int16 *)sdl_tmpscreen->pixels + (y+1) * TMP_SCREEN_WIDTH + (x+1);
|
||||
int16 *dst = (int16 *)_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);
|
||||
SDL_UnlockSurface(_tmpscreen);
|
||||
}
|
||||
|
||||
|
||||
|
@ -71,8 +71,7 @@ public:
|
||||
PROP_SET_GFX_MODE = 4,
|
||||
PROP_SHOW_DEFAULT_CURSOR = 5,
|
||||
PROP_GET_SAMPLE_RATE = 6,
|
||||
PROP_GET_FULLSCREEN = 7,
|
||||
PROP_OVERLAY_IS_565 = 8
|
||||
PROP_GET_FULLSCREEN = 7
|
||||
};
|
||||
union Property {
|
||||
const char *caption;
|
||||
@ -168,6 +167,19 @@ public:
|
||||
virtual void clear_overlay() = 0;
|
||||
virtual void grab_overlay(int16 *buf, int pitch) = 0;
|
||||
virtual void copy_rect_overlay(const int16 *buf, int pitch, int x, int y, int w, int h) = 0;
|
||||
|
||||
// Methods that convert RBG to/from colors suitable for the overlay.
|
||||
// Default implementation assumes 565 mode.
|
||||
virtual int16 RBGToColor(uint8 r, uint8 g, uint8 b)
|
||||
{
|
||||
return ((((r>>3)&0x1F) << 11) | (((g>>2)&0x3F) << 5) | ((b>>3)&0x1F));
|
||||
}
|
||||
virtual void colorToRBG(int16 color, uint8 &r, uint8 &g, uint8 &b)
|
||||
{
|
||||
r = (((color>>11)&0x1F) << 3);
|
||||
g = (((color>>5)&0x3F) << 2);
|
||||
b = ((color&0x1F) << 3);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
@ -38,28 +38,6 @@
|
||||
static inline void SWAP(int &a, int &b) { int tmp=a; a=b; b=tmp; }
|
||||
#define ARRAYSIZE(x) (sizeof(x)/sizeof(x[0]))
|
||||
|
||||
#if USE_555_FORMAT
|
||||
// Assume the 16 bit graphics data is in 5-5-5 format
|
||||
#define RGB_TO_16(r,g,b) (((((r)>>3)&0x1F) << 10) | ((((g)>>3)&0x1F) << 5) | (((b)>>3)&0x1F))
|
||||
#define RED_FROM_16(x) ((((x)>>10)&0x1F) << 3)
|
||||
#define GREEN_FROM_16(x) ((((x)>>5)&0x1F) << 3)
|
||||
#define BLUE_FROM_16(x) (((x)&0x1F) << 3)
|
||||
|
||||
#elif defined(__GP32__) //ph0x
|
||||
// GP32 format 5-5-5-1 (first bit means intensity)
|
||||
#define RGB_TO_16(r,g,b) (((((r)>>3)&0x1F) << 11) | ((((g)>>3)&0x1F) << 6) | (((b)>>3)&0x1F)<<1)
|
||||
#define RED_FROM_16(x) ((((x)>>11)&0x1F) << 3)
|
||||
#define GREEN_FROM_16(x) ((((x)>>6) &0x1F) << 3)
|
||||
#define BLUE_FROM_16(x) ((((x)>>1) &0x1F) << 3)
|
||||
|
||||
#else
|
||||
// Assume the 16 bit graphics data is in 5-6-5 format
|
||||
#define RGB_TO_16(r,g,b) (((((r)>>3)&0x1F) << 11) | ((((g)>>2)&0x3F) << 5) | (((b)>>3)&0x1F))
|
||||
#define RED_FROM_16(x) ((((x)>>11)&0x1F) << 3)
|
||||
#define GREEN_FROM_16(x) ((((x)>>5)&0x3F) << 2)
|
||||
#define BLUE_FROM_16(x) (((x)&0x1F) << 3)
|
||||
#endif
|
||||
|
||||
int RGBMatch(byte *palette, int r, int g, int b);
|
||||
int Blend(int src, int dst, byte *palette);
|
||||
void ClearBlendCache(byte *palette, int weight);
|
||||
|
@ -84,14 +84,6 @@ static byte guifont[] = {
|
||||
NewGui::NewGui(OSystem *system) : _system(system), _screen(0), _needRedraw(false),
|
||||
_stateIsSaved(false), _cursorAnimateCounter(0), _cursorAnimateTimer(0)
|
||||
{
|
||||
// Setup some default GUI colors.
|
||||
// TODO - either use nicer values, or maybe make this configurable?
|
||||
_bgcolor = RGB_TO_16(0, 0, 0);
|
||||
_color = RGB_TO_16(96, 96, 96);
|
||||
_shadowcolor = RGB_TO_16(64, 64, 64);
|
||||
_textcolor = RGB_TO_16(32, 160, 32);
|
||||
_textcolorhi = RGB_TO_16(0, 255, 0);
|
||||
|
||||
// Clear the cursor
|
||||
memset(_cursor, 0xFF, sizeof(_cursor));
|
||||
|
||||
@ -107,6 +99,18 @@ void NewGui::runLoop()
|
||||
if (activeDialog == 0)
|
||||
return;
|
||||
|
||||
// Setup some default GUI colors. This has to be done here to ensure the
|
||||
// overlay has been created already. Even then, one can get wrong colors, namely
|
||||
// if the GUI is up and then the user toggles to full screen mode - on some system
|
||||
// different color modes (555 vs 565) might be used depending on the resolution
|
||||
// (e.g. that's the case on my system), so we still end up with wrong colors in those
|
||||
// sitauations. At least now the user can fix it by closing and reopening the GUI.
|
||||
_bgcolor = _system->RBGToColor(0, 0, 0);
|
||||
_color = _system->RBGToColor(96, 96, 96);
|
||||
_shadowcolor = _system->RBGToColor(64, 64, 64);
|
||||
_textcolor = _system->RBGToColor(32, 160, 32);
|
||||
_textcolorhi = _system->RBGToColor(0, 255, 0);
|
||||
|
||||
if (!_stateIsSaved) {
|
||||
saveState();
|
||||
didSaveState = true;
|
||||
@ -313,16 +317,18 @@ void NewGui::line(int x, int y, int x2, int y2, int16 color)
|
||||
|
||||
void NewGui::blendRect(int x, int y, int w, int h, int16 color)
|
||||
{
|
||||
int r = RED_FROM_16(color) * 3;
|
||||
int g = GREEN_FROM_16(color) * 3;
|
||||
int b = BLUE_FROM_16(color) * 3;
|
||||
uint8 r, g, b;
|
||||
uint8 ar, ag, ab;
|
||||
_system->colorToRBG(color, r, g, b);
|
||||
r *= 3;
|
||||
g *= 3;
|
||||
b *= 3;
|
||||
int16 *ptr = getBasePtr(x, y);
|
||||
|
||||
while (h--) {
|
||||
for (int i = 0; i < w; i++) {
|
||||
ptr[i] = RGB_TO_16((RED_FROM_16(ptr[i])+r)/4,
|
||||
(GREEN_FROM_16(ptr[i])+g)/4,
|
||||
(BLUE_FROM_16(ptr[i])+b)/4);
|
||||
_system->colorToRBG(ptr[i], ar, ag, ab);
|
||||
ptr[i] = _system->RBGToColor((ar+r)/4, (ag+g)/4, (ab+b)/4);
|
||||
}
|
||||
ptr += _screenPitch;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user