aboutsummaryrefslogtreecommitdiff
path: root/backends/x11/x11.cpp
diff options
context:
space:
mode:
authorLionel Ulmer2002-11-02 15:13:08 +0000
committerLionel Ulmer2002-11-02 15:13:08 +0000
commitffebcc826be7127816fa37c6ce96af56cfa38a58 (patch)
tree389c5b1b01d45633686fd6ff009ce266be55a585 /backends/x11/x11.cpp
parent65029389832572f2fa7e4e36b303c57e2b9b6d56 (diff)
downloadscummvm-rg350-ffebcc826be7127816fa37c6ce96af56cfa38a58.tar.gz
scummvm-rg350-ffebcc826be7127816fa37c6ce96af56cfa38a58.tar.bz2
scummvm-rg350-ffebcc826be7127816fa37c6ce96af56cfa38a58.zip
Make X11 driver work with overlays and all the stuff. Rework by the
same occasion the mouse code. RFH: if anyone has a DOTT save game just before the car cleaning in the past, I would like to have it to test the (untested) code to move the screen. svn-id: r5383
Diffstat (limited to 'backends/x11/x11.cpp')
-rw-r--r--backends/x11/x11.cpp280
1 files changed, 147 insertions, 133 deletions
diff --git a/backends/x11/x11.cpp b/backends/x11/x11.cpp
index bf7b01e278..a1a9ee3858 100644
--- a/backends/x11/x11.cpp
+++ b/backends/x11/x11.cpp
@@ -22,9 +22,11 @@
/* The bare pure X11 port done by Lionel 'BBrox' Ulmer */
-#include "stdafx.h"
-#include "scumm.h"
-#include "gameDetector.h"
+#include "common/util.h"
+#include "common/engine.h" // Only #included for error() and warning()
+
+#include <stdio.h>
+#include <assert.h>
#include <sys/time.h>
#include <unistd.h>
@@ -35,10 +37,6 @@
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/extensions/XShm.h>
-#ifdef USE_XV_SCALING
-#include <X11/extensions/Xv.h>
-#include <X11/extensions/Xvlib.h>
-#endif
#include <linux/soundcard.h>
#include <sched.h>
@@ -123,6 +121,14 @@ public:
void unlock_mutex(void *mutex);
void delete_mutex(void *mutex);
+ // Overlay handling for the new menu system
+ void show_overlay();
+ void hide_overlay();
+ void clear_overlay();
+ void grab_overlay(int16 *, int);
+ void copy_rect_overlay(const int16 *, int, int, int, int, int);
+
+
static OSystem *create(int gfx_mode, bool full_screen);
private:
@@ -133,31 +139,26 @@ private:
} dirty_square;
void create_empty_cursor();
+ void draw_mouse(dirty_square *dout);
void undraw_mouse();
- void draw_mouse();
void update_screen_helper(const dirty_square * d, dirty_square * dout);
+ void blit_convert(const dirty_square * d, uint16 *dst, int pitch);
- unsigned char *local_fb;
+ uint8 *local_fb;
+ uint16 *local_fb_overlay;
+ bool _overlay_visible;
int window_width, window_height;
int fb_width, fb_height;
int scumm_x, scumm_y;
-#ifdef USE_XV_SCALING
- unsigned int *palette;
-#else
- unsigned short *palette;
-#endif
+ uint16 *palette;
bool _palette_changed;
Display *display;
int screen;
Window window;
GC black_gc;
-#ifdef USE_XV_SCALING
- XvImage *image;
-#else
XImage *image;
-#endif
pthread_t sound_thread;
int fake_right_mouse;
@@ -167,9 +168,7 @@ private:
struct timeval start_time;
enum {
- MAX_NUMBER_OF_DIRTY_SQUARES = 32,
- BAK_WIDTH = 40,
- BAK_HEIGHT = 40
+ MAX_NUMBER_OF_DIRTY_SQUARES = 32
};
dirty_square ds[MAX_NUMBER_OF_DIRTY_SQUARES];
int num_of_dirty_square;
@@ -181,11 +180,10 @@ private:
} mouse_state;
mouse_state old_state, cur_state;
const byte *_ms_buf;
- byte _ms_backup[BAK_WIDTH * BAK_HEIGHT];
- bool _mouse_drawn;
bool _mouse_visible;
+ bool _mouse_state_changed;
- unsigned int _timer_duration, _timer_next_expiry;
+ uint32 _timer_duration, _timer_next_expiry;
bool _timer_active;
int (*_timer_callback) (int);
};
@@ -203,7 +201,7 @@ static void *sound_and_music_thread(void *params)
{
/* Init sound */
int sound_fd, param, frag_size;
- unsigned char sound_buffer[FRAG_SIZE];
+ uint8 sound_buffer[FRAG_SIZE];
OSystem::SoundProc *sound_proc = ((THREAD_PARAM *) params)->sound_proc;
void *proc_param = ((THREAD_PARAM *) params)->param;
@@ -263,7 +261,7 @@ static void *sound_and_music_thread(void *params)
sched_yield();
while (1) {
- unsigned char *buf = (unsigned char *)sound_buffer;
+ uint8 *buf = (uint8 *)sound_buffer;
int size, written;
sound_proc(proc_param, (byte *)sound_buffer, FRAG_SIZE);
@@ -325,7 +323,9 @@ OSystem_X11::OSystem_X11()
new_shake_pos = 0;
_palette_changed = false;
num_of_dirty_square = MAX_NUMBER_OF_DIRTY_SQUARES;
-
+ _overlay_visible = false;
+ _mouse_state_changed = true;
+
/* For the window title */
sprintf(buf, "ScummVM");
@@ -351,13 +351,13 @@ OSystem_X11::OSystem_X11()
wm_hints->initial_state = NormalState;
XStringListToTextProperty(&name, 1, &window_name);
XSetWMProperties(display, window, &window_name, &window_name,
- NULL /* argv */ , 0 /* argc */ , NULL /* size hints */ ,
- wm_hints, NULL /* class hints */ );
+ NULL /* argv */ , 0 /* argc */ , NULL /* size hints */ ,
+ wm_hints, NULL /* class hints */ );
XFree(wm_hints);
XSelectInput(display, window,
- ExposureMask | KeyPressMask | KeyReleaseMask |
- PointerMotionMask | ButtonPressMask | ButtonReleaseMask | StructureNotifyMask);
+ ExposureMask | KeyPressMask | KeyReleaseMask |
+ PointerMotionMask | ButtonPressMask | ButtonReleaseMask | StructureNotifyMask);
values.foreground = BlackPixel(display, screen);
black_gc = XCreateGC(display, window, GCForeground, &values);
@@ -388,7 +388,7 @@ uint32 OSystem_X11::get_msecs()
struct timeval current_time;
gettimeofday(&current_time, NULL);
return (uint32)(((current_time.tv_sec - start_time.tv_sec) * 1000) +
- ((current_time.tv_usec - start_time.tv_usec) / 1000));
+ ((current_time.tv_usec - start_time.tv_usec) / 1000));
}
void OSystem_X11::init_size(uint w, uint h)
@@ -407,15 +407,8 @@ void OSystem_X11::init_size(uint w, uint h)
XConfigureWindow(display, window, CWWidth | CWHeight, &new_values);
}
-#ifdef USE_XV_SCALING
- image = XvShmCreateImage(display, 65, 0x03, 0, fb_width, fb_height, &shminfo);
- shminfo.shmid = shmget(IPC_PRIVATE, image->data_size, IPC_CREAT | 0700);
-#else
- image =
- XShmCreateImage(display, DefaultVisual(display, screen), 16, ZPixmap, NULL, &shminfo, fb_width,
- fb_height);
+ image = XShmCreateImage(display, DefaultVisual(display, screen), 16, ZPixmap, NULL, &shminfo, fb_width, fb_height);
shminfo.shmid = shmget(IPC_PRIVATE, fb_width * fb_height * 2, IPC_CREAT | 0700);
-#endif
shminfo.shmaddr = (char *)shmat(shminfo.shmid, 0, 0);
image->data = shminfo.shmaddr;
shminfo.readOnly = False;
@@ -426,12 +419,9 @@ void OSystem_X11::init_size(uint w, uint h)
shmctl(shminfo.shmid, IPC_RMID, 0);
/* Initialize the 'local' frame buffer and the palette */
- local_fb = (unsigned char *)calloc(fb_width * fb_height, sizeof(unsigned char));
-#ifdef USE_XV_SCALING
- palette = (unsigned int *)calloc(256, sizeof(unsigned int));
-#else
- palette = (unsigned short *)calloc(256, sizeof(unsigned short));
-#endif
+ local_fb = (uint8 *)calloc(fb_width * fb_height, sizeof(uint8));
+ local_fb_overlay = (uint16 *)calloc(fb_width * fb_height, sizeof(uint16));
+ palette = (uint16 *)calloc(256, sizeof(uint16));
}
bool OSystem_X11::set_sound_proc(void *param, SoundProc *proc, byte format)
@@ -454,18 +444,10 @@ bool OSystem_X11::set_sound_proc(void *param, SoundProc *proc, byte format)
void OSystem_X11::set_palette(const byte *colors, uint start, uint num)
{
const byte *data = colors;
-#ifdef USE_XV_SCALING
- unsigned int *pal = &(palette[start]);
-#else
- unsigned short *pal = &(palette[start]);
-#endif
+ uint16 *pal = &(palette[start]);
do {
-#ifdef USE_XV_SCALING
- *pal++ = (data[0] << 16) | (data[1] << 8) | data[2];
-#else
*pal++ = ((data[0] & 0xF8) << 8) | ((data[1] & 0xFC) << 3) | (data[2] >> 3);
-#endif
data += 4;
num--;
} while (num > 0);
@@ -484,7 +466,7 @@ void OSystem_X11::set_palette(const byte *colors, uint start, uint num)
void OSystem_X11::copy_rect(const byte *buf, int pitch, int x, int y, int w, int h)
{
- unsigned char *dst;
+ uint8 *dst;
if (y < 0) {
h += y;
@@ -500,9 +482,6 @@ void OSystem_X11::copy_rect(const byte *buf, int pitch, int x, int y, int w, int
if (h <= 0)
return;
- if (_mouse_drawn)
- undraw_mouse();
-
AddDirtyRec(x, y, w, h);
while (h-- > 0) {
memcpy(dst, buf, w);
@@ -548,24 +527,36 @@ void OSystem_X11::move_screen(int dx, int dy, int height) {
}
}
-
-void OSystem_X11::update_screen_helper(const dirty_square * d, dirty_square * dout)
+void OSystem_X11::blit_convert(const dirty_square * d, uint16 *dst, int pitch)
{
+ uint8 *ptr_src = local_fb + (fb_width * d->y) + d->x;
+ uint16 *ptr_dst = dst + (fb_width * d->y) + d->x;
int x, y;
- unsigned char *ptr_src = local_fb + (fb_width * d->y) + d->x;
-#ifdef USE_XV_SCALING
- unsigned int *ptr_dst = ((unsigned int *)image->data) + (fb_width * d->y) + d->x;
-#else
- unsigned short *ptr_dst = ((unsigned short *)image->data) + (fb_width * d->y) + d->x;
-#endif
for (y = 0; y < d->h; y++) {
for (x = 0; x < d->w; x++) {
*ptr_dst++ = palette[*ptr_src++];
}
- ptr_dst += fb_width - d->w;
+ ptr_dst += pitch - d->w;
ptr_src += fb_width - d->w;
}
+}
+
+void OSystem_X11::update_screen_helper(const dirty_square * d, dirty_square * dout)
+{
+ if (_overlay_visible == false) {
+ blit_convert(d, (uint16 *) image->data, fb_width);
+ } else {
+ uint16 *ptr_src = local_fb_overlay + (fb_width * d->y) + d->x;
+ uint16 *ptr_dst = ((uint16 *)image->data) + (fb_width * d->y) + d->x;
+ int y;
+
+ for (y = 0; y < d->h; y++) {
+ memcpy(ptr_dst, ptr_src, d->w * sizeof(uint16));
+ ptr_dst += fb_width;
+ ptr_src += fb_width;
+ }
+ }
if (d->x < dout->x)
dout->x = d->x;
if (d->y < dout->y)
@@ -582,10 +573,7 @@ void OSystem_X11::update_screen()
bool need_redraw = false;
static const dirty_square ds_full = { 0, 0, fb_width, fb_height };
dirty_square dout = { fb_width, fb_height, 0, 0 };
-
- /* First make sure the mouse is drawn, if it should be drawn. */
- draw_mouse();
-
+
if (_palette_changed) {
full_redraw = true;
num_of_dirty_square = 0;
@@ -598,7 +586,7 @@ void OSystem_X11::update_screen()
if (full_redraw) {
update_screen_helper(&ds_full, &dout);
need_redraw = true;
- } else if (num_of_dirty_square > 0) {
+ } else if ((num_of_dirty_square > 0) || (_mouse_state_changed == true)) {
need_redraw = true;
while (num_of_dirty_square > 0) {
num_of_dirty_square--;
@@ -606,27 +594,23 @@ void OSystem_X11::update_screen()
}
}
+ /* Then 'overlay' the mouse on the image */
+ draw_mouse(&dout);
+
if (current_shake_pos != new_shake_pos) {
/* Redraw first the 'black borders' in case of resize */
if (current_shake_pos < new_shake_pos)
XFillRectangle(display, window, black_gc, 0, current_shake_pos, window_width, new_shake_pos);
else
XFillRectangle(display, window, black_gc, 0, window_height - current_shake_pos,
- window_width, window_height - new_shake_pos);
-#ifndef USE_XV_SCALING
+ window_width, window_height - new_shake_pos);
XShmPutImage(display, window, DefaultGC(display, screen), image,
- 0, 0, scumm_x, scumm_y + new_shake_pos, fb_width, fb_height, 0);
-#endif
+ 0, 0, scumm_x, scumm_y + new_shake_pos, fb_width, fb_height, 0);
current_shake_pos = new_shake_pos;
} else if (need_redraw == true) {
-#ifdef USE_XV_SCALING
- XvShmPutImage(display, 65, window, DefaultGC(display, screen), image,
- 0, 0, fb_width, fb_height, 0, 0, window_width, window_height, 0);
-#else
XShmPutImage(display, window, DefaultGC(display, screen), image,
- dout.x, dout.y, scumm_x + dout.x, scumm_y + dout.y + current_shake_pos,
- dout.w - dout.x, dout.h - dout.y, 0);
-#endif
+ dout.x, dout.y, scumm_x + dout.x, scumm_y + dout.y + current_shake_pos,
+ dout.w - dout.x, dout.h - dout.y, 0);
XFlush(display);
}
}
@@ -639,10 +623,10 @@ bool OSystem_X11::show_mouse(bool visible)
bool last = _mouse_visible;
_mouse_visible = visible;
- if (visible)
- draw_mouse();
- else
+ if ((visible == false) && (_mouse_state_changed == false)) {
undraw_mouse();
+ }
+ _mouse_state_changed = true;
return last;
}
@@ -652,11 +636,17 @@ void OSystem_X11::quit()
exit(0);
}
-void OSystem_X11::draw_mouse()
+void OSystem_X11::undraw_mouse()
{
- if (_mouse_drawn || !_mouse_visible)
+ AddDirtyRec(old_state.x, old_state.y, old_state.w, old_state.h);
+}
+
+void OSystem_X11::draw_mouse(dirty_square *dout)
+{
+ _mouse_state_changed = false;
+
+ if (_mouse_visible == false)
return;
- _mouse_drawn = true;
int xdraw = cur_state.x - cur_state.hot_x;
int ydraw = cur_state.y - cur_state.hot_y;
@@ -664,14 +654,9 @@ void OSystem_X11::draw_mouse()
int h = cur_state.h;
int real_w;
int real_h;
- int real_h_2;
- byte *dst;
- byte *dst2;
+ uint16 *dst;
const byte *buf = _ms_buf;
- byte *bak = _ms_backup;
-
- assert(w <= BAK_WIDTH && h <= BAK_HEIGHT);
if (ydraw < 0) {
real_h = h + ydraw;
@@ -688,71 +673,53 @@ void OSystem_X11::draw_mouse()
real_w = (xdraw + w) > fb_width ? (fb_width - xdraw) : w;
}
- dst = local_fb + (ydraw * fb_width) + xdraw;
- dst2 = dst;
+ dst = ((uint16 *) image->data) + (ydraw * fb_width) + xdraw;
if ((real_h == 0) || (real_w == 0)) {
- _mouse_drawn = false;
return;
}
- AddDirtyRec(xdraw, ydraw, real_w, real_h);
+
+ if (xdraw < dout->x)
+ dout->x = xdraw;
+ if (ydraw < dout->y)
+ dout->y = ydraw;
+ if ((xdraw + real_w) > dout->w)
+ dout->w = xdraw + real_w;
+ if ((ydraw + real_h) > dout->h)
+ dout->h = ydraw + real_h;
+
old_state.x = xdraw;
old_state.y = ydraw;
old_state.w = real_w;
old_state.h = real_h;
- real_h_2 = real_h;
- while (real_h_2 > 0) {
- memcpy(bak, dst, real_w);
- bak += BAK_WIDTH;
- dst += fb_width;
- real_h_2--;
- }
while (real_h > 0) {
int width = real_w;
while (width > 0) {
byte color = *buf;
if (color != 0xFF) {
- *dst2 = color;
+ *dst = palette[color];
}
buf++;
- dst2++;
+ dst++;
width--;
}
buf += w - real_w;
- dst2 += fb_width - real_w;
+ dst += fb_width - real_w;
real_h--;
}
}
-void OSystem_X11::undraw_mouse()
-{
- if (!_mouse_drawn)
- return;
- _mouse_drawn = false;
-
- int old_h = old_state.h;
-
- AddDirtyRec(old_state.x, old_state.y, old_state.w, old_state.h);
-
- byte *dst = local_fb + (old_state.y * fb_width) + old_state.x;
- byte *bak = _ms_backup;
-
- while (old_h > 0) {
- memcpy(dst, bak, old_state.w);
- bak += BAK_WIDTH;
- dst += fb_width;
- old_h--;
- }
-}
-
void OSystem_X11::set_mouse_pos(int x, int y)
{
if ((x != cur_state.x) || (y != cur_state.y)) {
cur_state.x = x;
cur_state.y = y;
- undraw_mouse();
+ if (_mouse_state_changed == false) {
+ undraw_mouse();
+ }
+ _mouse_state_changed = true;
}
}
@@ -764,11 +731,20 @@ void OSystem_X11::set_mouse_cursor(const byte *buf, uint w, uint h, int hotspot_
cur_state.hot_y = hotspot_y;
_ms_buf = (byte *)buf;
- undraw_mouse();
+ if (_mouse_state_changed == false) {
+ undraw_mouse();
+ }
+ _mouse_state_changed = true;
}
void OSystem_X11::set_shake_pos(int shake_pos)
{
+ if (new_shake_pos != shake_pos) {
+ if (_mouse_state_changed == false) {
+ undraw_mouse();
+ }
+ _mouse_state_changed = true;
+ }
new_shake_pos = shake_pos;
}
@@ -1027,3 +1003,41 @@ void OSystem_X11::delete_mutex(void *mutex)
pthread_mutex_destroy((pthread_mutex_t *) mutex);
free(mutex);
}
+
+void OSystem_X11::show_overlay() {
+ _overlay_visible = true;
+}
+
+void OSystem_X11::hide_overlay() {
+ _overlay_visible = false;
+ _palette_changed = true; // This is to force a full redraw to hide the overlay
+}
+
+void OSystem_X11::clear_overlay() {
+ if (_overlay_visible == false)
+ return;
+ dirty_square d = { 0, 0, fb_width, fb_height };
+ AddDirtyRec(0, 0, fb_width, fb_height);
+ blit_convert(&d, local_fb_overlay, fb_width);
+}
+
+void OSystem_X11::grab_overlay(int16 *dest, int pitch) {
+ if (_overlay_visible == false)
+ return;
+
+ dirty_square d = { 0, 0, fb_width, fb_height };
+ blit_convert(&d, (uint16 *) dest, pitch);
+}
+
+void OSystem_X11::copy_rect_overlay(const int16 *src, int pitch, int x, int y, int w, int h) {
+ if (_overlay_visible == false)
+ return;
+ uint16 *dst = local_fb_overlay + x + (y * fb_width);
+ AddDirtyRec(x, y, w, h);
+ while (h > 0) {
+ memcpy(dst, src, w * sizeof(*dst));
+ dst += fb_width;
+ src += pitch;
+ h--;
+ }
+}