diff options
Diffstat (limited to 'plugins/gxvideo/draw.c')
| -rw-r--r-- | plugins/gxvideo/draw.c | 1518 |
1 files changed, 757 insertions, 761 deletions
diff --git a/plugins/gxvideo/draw.c b/plugins/gxvideo/draw.c index a83e429b..5e3b31ad 100644 --- a/plugins/gxvideo/draw.c +++ b/plugins/gxvideo/draw.c @@ -1,761 +1,757 @@ -/* - * Copyright (C) 2010 Benoit Gschwind - * Inspired by original author : Pete Bernert - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - */ - -#include <stdio.h> -#include <string.h> -#include <stdlib.h> -#include <math.h> -#include <sys/shm.h> -#include <X11/cursorfont.h> - -#include "globals.h" -#include "swap.h" - -#define MAX(a,b) (((a) > (b)) ? (a) : (b)) -#define MIN(a,b) (((a) < (b)) ? (a) : (b)) - -enum { - GXV_YUV_PORT = 0, GXV_RGB_PORT = 1, GXV_MAX_PORT = 2, -}; - -gxv_blit_t available_port[GXV_MAX_PORT]; - -/* Convert RGB to YUV */ -static inline uint32_t rgb_to_yuv(uint8_t R, uint8_t G, uint8_t B) { - uint8_t Y, U, V; - Y = abs(R * 2104 + G * 4130 + B * 802 + 4096 + 131072) >> 13; - Y = MIN(Y, 235); - U = abs(R * -1214 + G * -2384 + B * 3598 + 4096 + 1048576) >> 13; - U = MIN(U, 240); - V = abs(R * 3598 + G * -3013 + B * -585 + 4096 + 1048576) >> 13; - V = MIN(V, 240); - return Y << 24 | V << 16 | Y << 8 | U; -} - -static inline uint32_t rgb_to_yuv2(uint8_t R0, uint8_t G0, uint8_t B0, uint8_t R1, - uint8_t G1, uint8_t B1) { - int32_t Y0, U0, V0; - int32_t Y1, U1, V1; - int32_t U, V; - Y0 = abs(R0 * 2104 + G0 * 4130 + B0 * 802 + 4096 + 131072) >> 13; - Y0 = MIN(Y0, 235); - U0 = abs(R0 * -1214 + G0 * -2384 + B0 * 3598 + 4096 + 1048576) >> 13; - U0 = MIN(U0, 240); - V0 = abs(R0 * 3598 + G0 * -3013 + B0 * -585 + 4096 + 1048576) >> 13; - V0 = MIN(V0, 240); - Y1 = abs(R1 * 2104 + G1 * 4130 + B1 * 802 + 4096 + 131072) >> 13; - Y1 = MIN(Y1, 235); - U1 = abs(R1 * -1214 + G1 * -2384 + B1 * 3598 + 4096 + 1048576) >> 13; - U1 = MIN(U1, 240); - V1 = abs(R1 * 3598 + G1 * -3013 + B1 * -585 + 4096 + 1048576) >> 13; - V1 = MIN(V1, 240); - U = (U0 + U1) / 2; - V = (V0 + V1) / 2; - return Y1 << 24 | V << 16 | Y0 << 8 | U; -} - -#define colorMask8 0x00FEFEFE -#define lowPixelMask8 0x00010101 -#define qcolorMask8 0x00FCFCFC -#define qlowpixelMask8 0x00030303 - -static Atom xv_intern_atom_if_exists(Display *display, char const * atom_name) { - XvAttribute * attributes; - int attrib_count, i; - Atom xv_atom = None; - - attributes = XvQueryPortAttributes(display, g_draw.xv_port, &attrib_count); - if (attributes != NULL) { - for (i = 0; i < attrib_count; ++i) { - if (strcmp(attributes[i].name, atom_name) == 0) { - xv_atom = XInternAtom(display, atom_name, False); - break; // found what we want, break out - } - } - XFree(attributes); - } - - return xv_atom; -} - -// close display - -static void DestroyDisplay(void) { - if (g_draw.display) { - XFreeColormap(g_draw.display, g_draw.colormap); - if (g_draw.hGC) { - XFreeGC(g_draw.display, g_draw.hGC); - g_draw.hGC = 0; - } - if (g_draw.Ximage) { - XDestroyImage(g_draw.Ximage); - g_draw.Ximage = 0; - } - if (g_draw.XCimage) { - XFree(g_draw.XCimage); - g_draw.XCimage = 0; - } - if (g_draw.XFimage) { - XDestroyImage(g_draw.XFimage); - g_draw.XFimage = 0; - } - - XShmDetach(g_draw.display, &g_draw.shminfo); - shmdt(g_draw.shminfo.shmaddr); - shmctl(g_draw.shminfo.shmid, IPC_RMID, NULL); - - Atom atom_vsync = xv_intern_atom_if_exists(g_draw.display, - "XV_SYNC_TO_VBLANK"); - if (atom_vsync != None) { - XvSetPortAttribute(g_draw.display, g_draw.xv_port, atom_vsync, - g_draw.xv_vsync); - } - - XSync(g_draw.display, False); - - XCloseDisplay(g_draw.display); - } -} - -// Create display - -static void create_display(void) { - //fprintf(stderr, "Entering %s\n", __FUNCTION__); - XSetWindowAttributes winattr; - int myscreen; - Screen * screen; - XEvent event; - XSizeHints hints; - XWMHints wm_hints; - MotifWmHints mwmhints; - Atom mwmatom; - - Atom delwindow; - - XGCValues gcv; - int i; - - int ret, j, p; - int formats; - unsigned int p_num_adaptors = 0, p_num_ports = 0; - - XvAdaptorInfo *ai; - XvImageFormatValues *fo; - - // Open display - g_draw.display = XOpenDisplay(NULL); - - if (!g_draw.display) { - fprintf(stderr, "Failed to open display!!!\n"); - DestroyDisplay(); - return; - } - - myscreen = DefaultScreen(g_draw.display); - - // desktop fullscreen switch - if (g_cfg.FullScreen) - g_draw.fx = 1; - - screen = DefaultScreenOfDisplay(g_draw.display); - - g_draw.root_window_id = RootWindow(g_draw.display, myscreen); - - //Look for an Xvideo RGB port - ret = XvQueryAdaptors(g_draw.display, g_draw.root_window_id, - &p_num_adaptors, &ai); - if (ret != Success) { - if (ret == XvBadExtension) - fprintf(stderr, "XvBadExtension returned at XvQueryExtension.\n"); - else if (ret == XvBadAlloc) - fprintf(stderr, "XvBadAlloc returned at XvQueryExtension.\n"); - else - fprintf(stderr, "other error happaned at XvQueryAdaptors.\n"); - exit(EXIT_FAILURE); - } - - g_draw.depth = DefaultDepth(g_draw.display, myscreen); - - g_draw.xv_id = -1; - g_draw.xv_port = -1; - g_draw.xv = -1; - - for (i = 0; i < p_num_adaptors; i++) { - p_num_ports = ai[i].base_id + ai[i].num_ports; - for (p = ai[i].base_id; p < p_num_ports; p++) { - fo = XvListImageFormats(g_draw.display, p, &formats); - for (j = 0; j < formats; ++j) { - - if (fo[j].type == XvYUV && fo[j].bits_per_pixel == 16 - && fo[j].format == XvPacked && strncmp("UYVY", - fo[j].component_order, 4) == 0) { - g_draw.xv_port = p; - g_draw.xv_id = fo[j].id; - - g_draw.xv = GXV_YUV_PORT; - j = formats; - p = p_num_ports; - i = p_num_adaptors; - break; - } - - if (fo[j].type == XvRGB && fo[j].bits_per_pixel == 32) { - g_draw.xv_port = p; - g_draw.xv_id = fo[j].id; - printf("RGB mode found. id: %x\n", g_draw.xv_id); - g_draw.xv = GXV_RGB_PORT; - //break out of loops - j = formats; - p = p_num_ports; - i = p_num_adaptors; - } - } - - if (fo) - XFree(fo); - } - } - - if (p_num_adaptors > 0) - XvFreeAdaptorInfo(ai); - - if (g_draw.xv < 0) { - fprintf(stderr, "RGB & YUV not found. Quitting.\n"); - exit(EXIT_FAILURE); - } - - Atom atom_vsync = xv_intern_atom_if_exists(g_draw.display, - "XV_SYNC_TO_VBLANK"); - if (atom_vsync != None) { - XvGetPortAttribute(g_draw.display, g_draw.xv_port, atom_vsync, - &g_draw.xv_vsync); - XvSetPortAttribute(g_draw.display, g_draw.xv_port, atom_vsync, 0); - } - - g_draw.myvisual = 0; - - if (XMatchVisualInfo(g_draw.display, myscreen, g_draw.depth, TrueColor, - &g_draw.vi)) - g_draw.myvisual = &g_draw.vi; - - if (!g_draw.myvisual) { - fprintf(stderr, "Failed to obtain visual!\n"); - DestroyDisplay(); - return; - } - - if (!g_cfg.FullScreen) - g_draw.cursor = XCreateFontCursor(g_draw.display, XC_trek); - else { - g_draw.cursor = None; - } - - g_draw.colormap = XCreateColormap(g_draw.display, g_draw.root_window_id, - g_draw.myvisual->visual, AllocNone); - - winattr.background_pixel = BlackPixelOfScreen(screen); - winattr.border_pixel = WhitePixelOfScreen(screen); - winattr.bit_gravity = ForgetGravity; - winattr.win_gravity = NorthWestGravity; - winattr.backing_store = NotUseful; - - winattr.override_redirect = False; - winattr.save_under = False; - winattr.event_mask = 0; - winattr.do_not_propagate_mask = 0; - winattr.colormap = g_draw.colormap; - winattr.cursor = None; - - g_draw.window = XCreateWindow(g_draw.display, g_draw.root_window_id, 0, 0, - g_cfg.ResX, g_cfg.ResY, 0, g_draw.myvisual->depth, InputOutput, - g_draw.myvisual->visual, CWBorderPixel | CWBackPixel | CWEventMask - | CWDontPropagate | CWColormap | CWCursor, &winattr); - - if (!g_draw.window) { - fprintf(stderr, "Failed in XCreateWindow()!!!\n"); - DestroyDisplay(); - return; - } - - delwindow = XInternAtom(g_draw.display, "WM_DELETE_WINDOW", 0); - XSetWMProtocols(g_draw.display, g_draw.window, &delwindow, 1); - - hints.flags = USPosition | USSize; - hints.base_width = g_cfg.ResX; - hints.base_height = g_cfg.ResY; - - wm_hints.input = 1; - wm_hints.flags = InputHint; - - XSetWMHints(g_draw.display, g_draw.window, &wm_hints); - XSetWMNormalHints(g_draw.display, g_draw.window, &hints); - //if (pCaptionText) - // XStoreName(draw_ctx.display, draw_ctx.window, pCaptionText); - //else - XStoreName(g_draw.display, g_draw.window, "GXVideo GPU"); - - XDefineCursor(g_draw.display, g_draw.window, g_draw.cursor); - - // hack to get rid of window title bar - if (g_draw.fx) { - mwmhints.flags = MWM_HINTS_DECORATIONS; - mwmhints.decorations = 0; - mwmatom = XInternAtom(g_draw.display, "_MOTIF_WM_HINTS", 0); - XChangeProperty(g_draw.display, g_draw.window, mwmatom, mwmatom, 32, - PropModeReplace, (unsigned char *) &mwmhints, 4); - } - - // key stuff - XSelectInput(g_draw.display, g_draw.window, FocusChangeMask | ExposureMask - | KeyPressMask | KeyReleaseMask); - - XMapRaised(g_draw.display, g_draw.window); - XClearWindow(g_draw.display, g_draw.window); - XWindowEvent(g_draw.display, g_draw.window, ExposureMask, &event); - - if (g_draw.fx) { - XResizeWindow(g_draw.display, g_draw.window, screen->width, - screen->height); - - hints.min_width = hints.max_width = hints.base_width = screen->width; - hints.min_height = hints.max_height = hints.base_height - = screen->height; - - XSetWMNormalHints(g_draw.display, g_draw.window, &hints); - - // set the window layer for GNOME - { - XEvent xev; - - memset(&xev, 0, sizeof(xev)); - xev.xclient.type = ClientMessage; - xev.xclient.serial = 0; - xev.xclient.send_event = 1; - xev.xclient.message_type = XInternAtom(g_draw.display, - "_NET_WM_STATE", 0); - xev.xclient.window = g_draw.window; - xev.xclient.format = 32; - xev.xclient.data.l[0] = 1; - xev.xclient.data.l[1] = XInternAtom(g_draw.display, - "_NET_WM_STATE_FULLSCREEN", 0); - xev.xclient.data.l[2] = 0; - xev.xclient.data.l[3] = 0; - xev.xclient.data.l[4] = 0; - - XSendEvent(g_draw.display, g_draw.root_window_id, 0, - SubstructureRedirectMask | SubstructureNotifyMask, &xev); - } - } - - gcv.graphics_exposures = False; - gcv.foreground = WhitePixelOfScreen(screen); - gcv.background = BlackPixelOfScreen(screen); - g_draw.hGC = XCreateGC(g_draw.display, g_draw.window, GCGraphicsExposures - |GCForeground | GCBackground, &gcv); - if (!g_draw.hGC) { - fprintf(stderr, "No gfx context!!!\n"); - DestroyDisplay(); - } - - g_draw.Xpixels = (char *) malloc(600 * 15 * 4); - - uint32_t color; - if (g_draw.xv == GXV_YUV_PORT) - color = rgb_to_yuv(0x00, 0x00, 0xff); - else - color = 0x0000ff; - - for (i = 0; i < 600 * 15; ++i) - ((uint32_t *) g_draw.Xpixels)[i] = color; - - g_draw.XFimage = XCreateImage(g_draw.display, g_draw.myvisual->visual, - g_draw.depth, ZPixmap, 0, (char *) g_draw.Xpixels, 600, 15, - g_draw.depth > 16 ? 32 : 16, 0); - - /* fix the green back ground in YUV mode */ - if (g_draw.xv == GXV_YUV_PORT) - color = rgb_to_yuv(0x00, 0x00, 0x00); - else - color = 0; - - g_draw.Xpixels = (char *) malloc(8 * 8 * 4); - for (i = 0; i < 8 * 8; ++i) - ((uint32_t *) g_draw.Xpixels)[i] = color; - - g_draw.XCimage = XvCreateImage(g_draw.display, g_draw.xv_port, - g_draw.xv_id, (char *) g_draw.Xpixels, 8, 8); - - /* - Allocate max that could be needed: - Big(est?) PSX res: 640x512 - 32bpp (times 4) - 2xsai func= 3xwidth,3xheight - = approx 11.8mb - */ - g_draw.shminfo.shmid - = shmget(IPC_PRIVATE, 1024 * 512 * 4, IPC_CREAT | 0777); - g_draw.shminfo.shmaddr = shmat(g_draw.shminfo.shmid, 0, 0); - g_draw.shminfo.readOnly = 0; - - if (!XShmAttach(g_draw.display, &g_draw.shminfo)) { - printf("XShmAttach failed !\n"); - exit(-1); - } - - uint32_t *pShmaddr = (uint32_t *) g_draw.shminfo.shmaddr; - for (i = 0; i < 1024 * 512; ++i) - pShmaddr[i] = color; - - //fprintf(stderr, "Return %s\n", __FUNCTION__); - return; -} - -#if 0 -static int rgb_check_port(XvImageFormatValues const * fo) { - if (fo->type == XvRGB && fo->bits_per_pixel == 32) { - g_draw.xv_id = fo->id; - return 1; - } - return 0; -} -#endif - -static void rgb_blit_16(int8_t * buff, int32_t x, int32_t y, int32_t w, int32_t h) { - //fprintf(stderr, "BlitToYUV\n"); - int16_t * src_pxl; - int8_t * dst_pxl; - int32_t startxy; - int32_t _x, _y; - - startxy = 0; - dst_pxl = buff; - for (_y = y; _y < h; ++_y) { - src_pxl = &g_gpu.psx_vram.s16[startxy]; - for (_x = x; _x < w; ++_x) { - dst_pxl[0] = ((*src_pxl) << 3) & 0xf8; - dst_pxl[1] = ((*src_pxl) >> 2) & 0xf8; - dst_pxl[2] = ((*src_pxl) >> 7) & 0xf8; - dst_pxl += 3; - src_pxl += 1; - } - startxy += 2048; - } -} - -static void rgb_blit_24(int8_t * buff, int32_t x, int32_t y, int32_t w, int32_t h) { - //fprintf(stderr, "BlitToYUV\n"); - int8_t * src_pxl; - int8_t * dst_pxl; - int32_t startxy; - int32_t _x, _y; - - dst_pxl = buff; - startxy = 0; - for (_y = y; _y < h; ++_y) { - src_pxl = &g_gpu.psx_vram.s8[startxy]; - for (_x = x; _x < w; ++_x) { - dst_pxl[0] = src_pxl[0]; - dst_pxl[1] = src_pxl[1]; - dst_pxl[2] = src_pxl[2]; - dst_pxl += 3; - src_pxl += 3; - } - startxy += 2048; - } -} - -#if 0 -static int yuyv_check_port(XvImageFormatValues * fo) { - if (fo->type == XvYUV && fo->bits_per_pixel == 16 && fo->format == XvPacked - && strncmp("UYVY", fo->component_order, 4) == 0) { - g_draw.xv_id = fo->id; - return 1; - } - return 0; -} -#endif - -static void yuyv_blit_24(int8_t * buff, int32_t x, int32_t y, int32_t w, int32_t h) { - //fprintf(stderr, "yuyv_blit_24 %d %d %d %d\n", x, y, w, h); - uint8_t * src_pxl; - int8_t R0, G0, B0; - int8_t R1, G1, B1; - uint32_t * dst_pxl; - int32_t _x, _y; - - /* x and w should be multiple of 2 to be align */ - x = x & 0xfffffffe; - w = (w + 1) & 0xfffffffe; - - dst_pxl = (uint32_t *) (buff); - for (_y = y; _y < (y + h); _y += 1) { - src_pxl = &g_gpu.psx_vram.u8[x * 3 + (_y * 2048)]; - for (_x = 0; _x < (w / 2); ++_x) { - R0 = src_pxl[0]; - G0 = src_pxl[1]; - B0 = src_pxl[2]; - R1 = src_pxl[3]; - G1 = src_pxl[4]; - B1 = src_pxl[5]; - *dst_pxl++ = rgb_to_yuv2(R0, G0, B0, R1, G1, B1); - src_pxl += 6; - } - } -} - -static void yuyv_blit_16(int8_t * buff, int32_t x, int32_t y, int32_t w, int32_t h) { - //fprintf(stderr, "yuyv_blit_16 %d %d %d %d\n", x, y, w, h); - int8_t R0, G0, B0; - int8_t R1, G1, B1; - uint32_t * dst_pxl; - int32_t _x, _y; - int32_t s; - uint16_t * src_pxl; - - /* x must be a multiple of 2 */ - /* x and w must be a multiple of 2 */ - x = x & 0xfffffffe; - w = (w + 1) & 0xfffffffe; - - dst_pxl = (uint32_t *) (buff); - for (_y = y; _y < (y + h); _y += 1) { - src_pxl = &g_gpu.psx_vram.u16[x + (_y * 1024)]; - for (_x = 0; _x < (w / 2); ++_x) { - s = GETLE16(src_pxl++); - R0 = (s << 3) & 0xf8; - G0 = (s >> 2) & 0xf8; - B0 = (s >> 7) & 0xf8; - s = GETLE16(src_pxl++); - R1 = (s << 3) & 0xf8; - G1 = (s >> 2) & 0xf8; - B1 = (s >> 7) & 0xf8; - *dst_pxl++ = rgb_to_yuv2(R0, G0, B0, R1, G1, B1); - } - } -} - -/** - * compute the position and the size of output screen - * The aspect of the psx output mode is preserved. - * Note: dest dx,dy,dw,dh are both input and output variables - */ -static inline void maintain_aspect(uint32_t * dx, uint32_t * dy, uint32_t * dw, - uint32_t * dh, int32_t w, int32_t h) { - - double ratio_x = ((double) *dw) / ((double) w); - double ratio_y = ((double) *dh) / ((double) h); - - double ratio; - if (ratio_x < ratio_y) { - ratio = ratio_x; - } else { - ratio = ratio_y; - } - - uint32_t tw = (uint32_t) floor(w * ratio); - uint32_t th = (uint32_t) floor(h * ratio); - - *dx += (uint32_t) floor((*dw - tw) / 2.0); - *dy += (uint32_t) floor((*dh - th) / 2.0); - *dw = tw; - *dh = th; -} - -void do_buffer_swap(void) { - //Screen *screen; - Window _dw; - XvImage *xvi; - unsigned int dstx, dsty; - unsigned int _d, _w, _h; //don't care about _d - - dstx = 0; - dsty = 0; - - XSync(g_draw.display, False); - - XGetGeometry(g_draw.display, g_draw.window, &_dw, (int *) &_d, (int *) &_d, - &_w, &_h, &_d, &_d); - - if (g_cfg.ShowFPS) { - dsty += 15; - _h -= 15; - compute_fps(); - snprintf(g_draw.msg, 511, "FPS : %f", g_draw.fps); - XDrawImageString(g_draw.display, g_draw.window, g_draw.hGC, 0, 12, - g_draw.msg, strlen(g_draw.msg)); - } - - uint32_t _x_, _y_, _w_, _h_; - - /* if video mode is valid */ - if (g_gpu.dsp.mode.x) { - - if (g_gpu.status_reg & STATUS_RGB24) { - _x_ = (g_gpu.dsp.position.x * 2) / 3; - } else { - _x_ = g_gpu.dsp.position.x; - } - _y_ = g_gpu.dsp.position.y; - _w_ = (g_gpu.dsp.range.x1 - g_gpu.dsp.range.x0) / g_gpu.dsp.mode.x; - _h_ = (g_gpu.dsp.range.y1 - g_gpu.dsp.range.y0) * g_gpu.dsp.mode.y; - - if (g_gpu.status_reg & STATUS_RGB24) { - available_port[g_draw.xv].blit_24_bits( - (int8_t *) g_draw.shminfo.shmaddr, _x_, _y_, _w_, _h_); - } else { - available_port[GXV_YUV_PORT].blit_16_bits( - (int8_t *) g_draw.shminfo.shmaddr, _x_, _y_, _w_, _h_); - } - - xvi = XvShmCreateImage(g_draw.display, g_draw.xv_port, g_draw.xv_id, 0, - _w_, _h_, &g_draw.shminfo); - - xvi->data = g_draw.shminfo.shmaddr; - - //screen = DefaultScreenOfDisplay(g_draw.display); - //screennum = DefaultScreen(display); - - // if (g_cfg.FullScreen) { - // _w = screen->width; - // _h = screen->height; - // } - - if (g_cfg.Maintain43) - maintain_aspect(&dstx, &dsty, &_w, &_h, _w_, (g_gpu.dsp.range.y1 - - g_gpu.dsp.range.y0)); - - // int _i; - // int32_t * dst_pxl; - // dst_pxl = (int32_t *) &g_draw.shminfo.shmaddr[2048 * _y_]; - // for (_i = _x_ / 2; _i < (_x_ + _w_) / 2; ++_i) - // dst_pxl[_i] = rgb_to_yuv2(255, 0, 0, 255, 0, 0); - // dst_pxl = (int32_t *) &g_draw.shminfo.shmaddr[2048 * (_y_ + _h_)]; - // for (_i = _x_ / 2; _i < (_x_ + _w_) / 2; ++_i) - // dst_pxl[_i] = rgb_to_yuv2(255, 0, 0, 255, 0, 0); - // dst_pxl = (int32_t *) &g_draw.shminfo.shmaddr[4 * (_x_ / 2)]; - // for (_i = _y_; _i < (_y_ + _h_); ++_i) - // dst_pxl[_i * 512] = rgb_to_yuv2(255, 0, 0, 255, 0, 0); - // dst_pxl = (int32_t *) &g_draw.shminfo.shmaddr[4 * ((_x_ + _w_) / 2)]; - // for (_i = _y_; _i < (_y_ + _h_); ++_i) - // dst_pxl[_i * 512] = rgb_to_yuv2(255, 0, 0, 255, 0, 0); - - //fprintf(stderr, "From %d,%d,%d,%d\n", _x_, _y_, _w_, _h_); - XvShmPutImage(g_draw.display, g_draw.xv_port, g_draw.window, - g_draw.hGC, xvi, 0, 0, _w_, _h_, - //0, 0, 1024, 512, - /* dst */ - dstx, dsty, _w, _h, 1); - XFree(xvi); - } -} - -void do_clear_screen_buffer(void) // CLEAR DX BUFFER -{ - XClearWindow(g_draw.display, g_draw.window); -} - -static void Xcleanup() // X CLEANUP -{ - //CloseMenu(); -} - -/** - * Call on GPUopen - * Return the current display. - **/ -unsigned long init_display() { - - available_port[GXV_YUV_PORT].blit_24_bits = yuyv_blit_24; - available_port[GXV_YUV_PORT].blit_16_bits = yuyv_blit_16; - - available_port[GXV_RGB_PORT].blit_24_bits = rgb_blit_24; - available_port[GXV_RGB_PORT].blit_16_bits = rgb_blit_16; - - create_display(); // x stuff - g_draw.bIsFirstFrame = 0; - return (unsigned long) g_draw.display; -} - -void CloseDisplay(void) { - Xcleanup(); // cleanup dx - DestroyDisplay(); -} - -void CreatePic(unsigned char * pMem) { - unsigned char * p = (unsigned char *) malloc(128 * 96 * 4); - unsigned char * ps; - //int x, y; - - ps = p; - - // if (iDesktopCol == 16) { - // unsigned short s; - // for (y = 0; y < 96; y++) { - // for (x = 0; x < 128; x++) { - // s = (*(pMem + 0)) >> 3; - // s |= ((*(pMem + 1)) & 0xfc) << 3; - // s |= ((*(pMem + 2)) & 0xf8) << 8; - // pMem += 3; - // *((unsigned short *) (ps + y * 256 + x * 2)) = s; - // } - // } - // } else if (iDesktopCol == 15) { - // unsigned short s; - // for (y = 0; y < 96; y++) { - // for (x = 0; x < 128; x++) { - // s = (*(pMem + 0)) >> 3; - // s |= ((*(pMem + 1)) & 0xfc) << 2; - // s |= ((*(pMem + 2)) & 0xf8) << 7; - // pMem += 3; - // *((unsigned short *) (ps + y * 256 + x * 2)) = s; - // } - // } - // } else if (iDesktopCol == 32) { - // uint32_t l; - // for (y = 0; y < 96; y++) { - // for (x = 0; x < 128; x++) { - // l = *(pMem + 0); - // l |= (*(pMem + 1)) << 8; - // l |= (*(pMem + 2)) << 16; - // pMem += 3; - // *((uint32_t *) (ps + y * 512 + x * 4)) = l; - // } - // } - // } - - g_draw.XPimage = XCreateImage(g_draw.display, g_draw.myvisual->visual, - g_draw.depth, ZPixmap, 0, (char *) p, 128, 96, - g_draw.depth > 16 ? 32 : 16, 0); -} - -void DestroyPic(void) { - if (g_draw.XPimage) { /* - XPutImage(display,window,hGC, XCimage, - 0, 0, 0, 0, iResX, iResY);*/ - XDestroyImage(g_draw.XPimage); - g_draw.XPimage = 0; - } -} - -void ShowGpuPic(void) { -} - -void ShowTextGpuPic(void) { -} +/*
+ * Copyright (C) 2010 Benoit Gschwind
+ * Inspired by original author : Pete Bernert
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <math.h>
+#include <sys/shm.h>
+#include <X11/cursorfont.h>
+
+#include "globals.h"
+#include "swap.h"
+
+#define MAX(a,b) (((a) > (b)) ? (a) : (b))
+#define MIN(a,b) (((a) < (b)) ? (a) : (b))
+
+enum {
+ GXV_YUV_PORT = 0, GXV_RGB_PORT = 1, GXV_MAX_PORT = 2,
+};
+
+gxv_blit_t available_port[GXV_MAX_PORT];
+
+/* Convert RGB to YUV */
+inline uint32_t rgb_to_yuv(uint8_t R, uint8_t G, uint8_t B) {
+ uint8_t Y, U, V;
+ Y = abs(R * 2104 + G * 4130 + B * 802 + 4096 + 131072) >> 13;
+ Y = MIN(Y, 235);
+ U = abs(R * -1214 + G * -2384 + B * 3598 + 4096 + 1048576) >> 13;
+ U = MIN(U, 240);
+ V = abs(R * 3598 + G * -3013 + B * -585 + 4096 + 1048576) >> 13;
+ V = MIN(V, 240);
+ return Y << 24 | V << 16 | Y << 8 | U;
+}
+
+inline uint32_t rgb_to_yuv2(uint8_t R0, uint8_t G0, uint8_t B0, uint8_t R1,
+ uint8_t G1, uint8_t B1) {
+ int32_t Y0, U0, V0;
+ int32_t Y1, U1, V1;
+ int32_t U, V;
+ Y0 = abs(R0 * 2104 + G0 * 4130 + B0 * 802 + 4096 + 131072) >> 13;
+ Y0 = MIN(Y0, 235);
+ U0 = abs(R0 * -1214 + G0 * -2384 + B0 * 3598 + 4096 + 1048576) >> 13;
+ U0 = MIN(U0, 240);
+ V0 = abs(R0 * 3598 + G0 * -3013 + B0 * -585 + 4096 + 1048576) >> 13;
+ V0 = MIN(V0, 240);
+ Y1 = abs(R1 * 2104 + G1 * 4130 + B1 * 802 + 4096 + 131072) >> 13;
+ Y1 = MIN(Y1, 235);
+ U1 = abs(R1 * -1214 + G1 * -2384 + B1 * 3598 + 4096 + 1048576) >> 13;
+ U1 = MIN(U1, 240);
+ V1 = abs(R1 * 3598 + G1 * -3013 + B1 * -585 + 4096 + 1048576) >> 13;
+ V1 = MIN(V1, 240);
+ U = (U0 + U1) / 2;
+ V = (V0 + V1) / 2;
+ return Y1 << 24 | V << 16 | Y0 << 8 | U;
+}
+
+#define colorMask8 0x00FEFEFE
+#define lowPixelMask8 0x00010101
+#define qcolorMask8 0x00FCFCFC
+#define qlowpixelMask8 0x00030303
+
+static Atom xv_intern_atom_if_exists(Display *display, char const * atom_name) {
+ XvAttribute * attributes;
+ int attrib_count, i;
+ Atom xv_atom = None;
+
+ attributes = XvQueryPortAttributes(display, g_draw.xv_port, &attrib_count);
+ if (attributes != NULL) {
+ for (i = 0; i < attrib_count; ++i) {
+ if (strcmp(attributes[i].name, atom_name) == 0) {
+ xv_atom = XInternAtom(display, atom_name, False);
+ break; // found what we want, break out
+ }
+ }
+ XFree(attributes);
+ }
+
+ return xv_atom;
+}
+
+// close display
+
+void DestroyDisplay(void) {
+ if (g_draw.display) {
+ XFreeColormap(g_draw.display, g_draw.colormap);
+ if (g_draw.hGC) {
+ XFreeGC(g_draw.display, g_draw.hGC);
+ g_draw.hGC = 0;
+ }
+ if (g_draw.Ximage) {
+ XDestroyImage(g_draw.Ximage);
+ g_draw.Ximage = 0;
+ }
+ if (g_draw.XCimage) {
+ XFree(g_draw.XCimage);
+ g_draw.XCimage = 0;
+ }
+ if (g_draw.XFimage) {
+ XDestroyImage(g_draw.XFimage);
+ g_draw.XFimage = 0;
+ }
+
+ XShmDetach(g_draw.display, &g_draw.shminfo);
+ shmdt(g_draw.shminfo.shmaddr);
+ shmctl(g_draw.shminfo.shmid, IPC_RMID, NULL);
+
+ Atom atom_vsync = xv_intern_atom_if_exists(g_draw.display,
+ "XV_SYNC_TO_VBLANK");
+ if (atom_vsync != None) {
+ XvSetPortAttribute(g_draw.display, g_draw.xv_port, atom_vsync,
+ g_draw.xv_vsync);
+ }
+
+ XSync(g_draw.display, False);
+
+ XCloseDisplay(g_draw.display);
+ }
+}
+
+// Create display
+
+void create_display(void) {
+ //fprintf(stderr, "Entering %s\n", __FUNCTION__);
+ XSetWindowAttributes winattr;
+ int myscreen;
+ Screen * screen;
+ XEvent event;
+ XSizeHints hints;
+ XWMHints wm_hints;
+ MotifWmHints mwmhints;
+ Atom mwmatom;
+
+ Atom delwindow;
+
+ XGCValues gcv;
+ int i;
+
+ int ret, j, p;
+ int formats;
+ unsigned int p_num_adaptors = 0, p_num_ports = 0;
+
+ XvAdaptorInfo *ai;
+ XvImageFormatValues *fo;
+
+ // Open display
+ g_draw.display = XOpenDisplay(NULL);
+
+ if (!g_draw.display) {
+ fprintf(stderr, "Failed to open display!!!\n");
+ DestroyDisplay();
+ return;
+ }
+
+ myscreen = DefaultScreen(g_draw.display);
+
+ // desktop fullscreen switch
+ if (g_cfg.FullScreen)
+ g_draw.fx = 1;
+
+ screen = DefaultScreenOfDisplay(g_draw.display);
+
+ g_draw.root_window_id = RootWindow(g_draw.display, myscreen);
+
+ //Look for an Xvideo RGB port
+ ret = XvQueryAdaptors(g_draw.display, g_draw.root_window_id,
+ &p_num_adaptors, &ai);
+ if (ret != Success) {
+ if (ret == XvBadExtension)
+ fprintf(stderr, "XvBadExtension returned at XvQueryExtension.\n");
+ else if (ret == XvBadAlloc)
+ fprintf(stderr, "XvBadAlloc returned at XvQueryExtension.\n");
+ else
+ fprintf(stderr, "other error happaned at XvQueryAdaptors.\n");
+ exit(EXIT_FAILURE);
+ }
+
+ g_draw.depth = DefaultDepth(g_draw.display, myscreen);
+
+ g_draw.xv_id = -1;
+ g_draw.xv_port = -1;
+ g_draw.xv = -1;
+
+ for (i = 0; i < p_num_adaptors; i++) {
+ p_num_ports = ai[i].base_id + ai[i].num_ports;
+ for (p = ai[i].base_id; p < p_num_ports; p++) {
+ fo = XvListImageFormats(g_draw.display, p, &formats);
+ for (j = 0; j < formats; ++j) {
+
+ if (fo[j].type == XvYUV && fo[j].bits_per_pixel == 16
+ && fo[j].format == XvPacked && strncmp("UYVY",
+ fo[j].component_order, 4) == 0) {
+ g_draw.xv_port = p;
+ g_draw.xv_id = fo[j].id;
+
+ g_draw.xv = GXV_YUV_PORT;
+ j = formats;
+ p = p_num_ports;
+ i = p_num_adaptors;
+ break;
+ }
+
+ if (fo[j].type == XvRGB && fo[j].bits_per_pixel == 32) {
+ g_draw.xv_port = p;
+ g_draw.xv_id = fo[j].id;
+ printf("RGB mode found. id: %x\n", g_draw.xv_id);
+ g_draw.xv = GXV_RGB_PORT;
+ //break out of loops
+ j = formats;
+ p = p_num_ports;
+ i = p_num_adaptors;
+ }
+ }
+
+ if (fo)
+ XFree(fo);
+ }
+ }
+
+ if (p_num_adaptors > 0)
+ XvFreeAdaptorInfo(ai);
+
+ if (g_draw.xv < 0) {
+ fprintf(stderr, "RGB & YUV not found. Quitting.\n");
+ exit(EXIT_FAILURE);
+ }
+
+ Atom atom_vsync = xv_intern_atom_if_exists(g_draw.display,
+ "XV_SYNC_TO_VBLANK");
+ if (atom_vsync != None) {
+ XvGetPortAttribute(g_draw.display, g_draw.xv_port, atom_vsync,
+ &g_draw.xv_vsync);
+ XvSetPortAttribute(g_draw.display, g_draw.xv_port, atom_vsync, 0);
+ }
+
+ g_draw.myvisual = 0;
+
+ if (XMatchVisualInfo(g_draw.display, myscreen, g_draw.depth, TrueColor,
+ &g_draw.vi))
+ g_draw.myvisual = &g_draw.vi;
+
+ if (!g_draw.myvisual) {
+ fprintf(stderr, "Failed to obtain visual!\n");
+ DestroyDisplay();
+ return;
+ }
+
+ if (!g_cfg.FullScreen)
+ g_draw.cursor = XCreateFontCursor(g_draw.display, XC_trek);
+ else {
+ g_draw.cursor = None;
+ }
+
+ g_draw.colormap = XCreateColormap(g_draw.display, g_draw.root_window_id,
+ g_draw.myvisual->visual, AllocNone);
+
+ winattr.background_pixel = BlackPixelOfScreen(screen);
+ winattr.border_pixel = WhitePixelOfScreen(screen);
+ winattr.bit_gravity = ForgetGravity;
+ winattr.win_gravity = NorthWestGravity;
+ winattr.backing_store = NotUseful;
+
+ winattr.override_redirect = False;
+ winattr.save_under = False;
+ winattr.event_mask = 0;
+ winattr.do_not_propagate_mask = 0;
+ winattr.colormap = g_draw.colormap;
+ winattr.cursor = None;
+
+ g_draw.window = XCreateWindow(g_draw.display, g_draw.root_window_id, 0, 0,
+ g_cfg.ResX, g_cfg.ResY, 0, g_draw.myvisual->depth, InputOutput,
+ g_draw.myvisual->visual, CWBorderPixel | CWBackPixel | CWEventMask
+ | CWDontPropagate | CWColormap | CWCursor, &winattr);
+
+ if (!g_draw.window) {
+ fprintf(stderr, "Failed in XCreateWindow()!!!\n");
+ DestroyDisplay();
+ return;
+ }
+
+ delwindow = XInternAtom(g_draw.display, "WM_DELETE_WINDOW", 0);
+ XSetWMProtocols(g_draw.display, g_draw.window, &delwindow, 1);
+
+ hints.flags = USPosition | USSize;
+ hints.base_width = g_cfg.ResX;
+ hints.base_height = g_cfg.ResY;
+
+ wm_hints.input = 1;
+ wm_hints.flags = InputHint;
+
+ XSetWMHints(g_draw.display, g_draw.window, &wm_hints);
+ XSetWMNormalHints(g_draw.display, g_draw.window, &hints);
+ //if (pCaptionText)
+ // XStoreName(draw_ctx.display, draw_ctx.window, pCaptionText);
+ //else
+ XStoreName(g_draw.display, g_draw.window, "GXVideo GPU");
+
+ XDefineCursor(g_draw.display, g_draw.window, g_draw.cursor);
+
+ // hack to get rid of window title bar
+ if (g_draw.fx) {
+ mwmhints.flags = MWM_HINTS_DECORATIONS;
+ mwmhints.decorations = 0;
+ mwmatom = XInternAtom(g_draw.display, "_MOTIF_WM_HINTS", 0);
+ XChangeProperty(g_draw.display, g_draw.window, mwmatom, mwmatom, 32,
+ PropModeReplace, (unsigned char *) &mwmhints, 4);
+ }
+
+ // key stuff
+ XSelectInput(g_draw.display, g_draw.window, FocusChangeMask | ExposureMask
+ | KeyPressMask | KeyReleaseMask);
+
+ XMapRaised(g_draw.display, g_draw.window);
+ XClearWindow(g_draw.display, g_draw.window);
+ XWindowEvent(g_draw.display, g_draw.window, ExposureMask, &event);
+
+ if (g_draw.fx) {
+ XResizeWindow(g_draw.display, g_draw.window, screen->width,
+ screen->height);
+
+ hints.min_width = hints.max_width = hints.base_width = screen->width;
+ hints.min_height = hints.max_height = hints.base_height
+ = screen->height;
+
+ XSetWMNormalHints(g_draw.display, g_draw.window, &hints);
+
+ // set the window layer for GNOME
+ {
+ XEvent xev;
+
+ memset(&xev, 0, sizeof(xev));
+ xev.xclient.type = ClientMessage;
+ xev.xclient.serial = 0;
+ xev.xclient.send_event = 1;
+ xev.xclient.message_type = XInternAtom(g_draw.display,
+ "_NET_WM_STATE", 0);
+ xev.xclient.window = g_draw.window;
+ xev.xclient.format = 32;
+ xev.xclient.data.l[0] = 1;
+ xev.xclient.data.l[1] = XInternAtom(g_draw.display,
+ "_NET_WM_STATE_FULLSCREEN", 0);
+ xev.xclient.data.l[2] = 0;
+ xev.xclient.data.l[3] = 0;
+ xev.xclient.data.l[4] = 0;
+
+ XSendEvent(g_draw.display, g_draw.root_window_id, 0,
+ SubstructureRedirectMask | SubstructureNotifyMask, &xev);
+ }
+ }
+
+ gcv.graphics_exposures = False;
+ gcv.foreground = WhitePixelOfScreen(screen);
+ gcv.background = BlackPixelOfScreen(screen);
+ g_draw.hGC = XCreateGC(g_draw.display, g_draw.window, GCGraphicsExposures
+ |GCForeground | GCBackground, &gcv);
+ if (!g_draw.hGC) {
+ fprintf(stderr, "No gfx context!!!\n");
+ DestroyDisplay();
+ }
+
+ g_draw.Xpixels = (char *) malloc(600 * 15 * 4);
+
+ uint32_t color;
+ if (g_draw.xv == GXV_YUV_PORT)
+ color = rgb_to_yuv(0x00, 0x00, 0xff);
+ else
+ color = 0x0000ff;
+
+ for (i = 0; i < 600 * 15; ++i)
+ ((uint32_t *) g_draw.Xpixels)[i] = color;
+
+ g_draw.XFimage = XCreateImage(g_draw.display, g_draw.myvisual->visual,
+ g_draw.depth, ZPixmap, 0, (char *) g_draw.Xpixels, 600, 15,
+ g_draw.depth > 16 ? 32 : 16, 0);
+
+ /* fix the green back ground in YUV mode */
+ if (g_draw.xv == GXV_YUV_PORT)
+ color = rgb_to_yuv(0x00, 0x00, 0x00);
+ else
+ color = 0;
+
+ g_draw.Xpixels = (char *) malloc(8 * 8 * 4);
+ for (i = 0; i < 8 * 8; ++i)
+ ((uint32_t *) g_draw.Xpixels)[i] = color;
+
+ g_draw.XCimage = XvCreateImage(g_draw.display, g_draw.xv_port,
+ g_draw.xv_id, (char *) g_draw.Xpixels, 8, 8);
+
+ /*
+ Allocate max that could be needed:
+ Big(est?) PSX res: 640x512
+ 32bpp (times 4)
+ 2xsai func= 3xwidth,3xheight
+ = approx 11.8mb
+ */
+ g_draw.shminfo.shmid
+ = shmget(IPC_PRIVATE, 1024 * 512 * 4, IPC_CREAT | 0777);
+ g_draw.shminfo.shmaddr = shmat(g_draw.shminfo.shmid, 0, 0);
+ g_draw.shminfo.readOnly = 0;
+
+ if (!XShmAttach(g_draw.display, &g_draw.shminfo)) {
+ printf("XShmAttach failed !\n");
+ exit(-1);
+ }
+
+ uint32_t *pShmaddr = (uint32_t *) g_draw.shminfo.shmaddr;
+ for (i = 0; i < 1024 * 512; ++i)
+ pShmaddr[i] = color;
+
+ //fprintf(stderr, "Return %s\n", __FUNCTION__);
+ return;
+}
+
+int rgb_check_port(XvImageFormatValues const * fo) {
+ if (fo->type == XvRGB && fo->bits_per_pixel == 32) {
+ g_draw.xv_id = fo->id;
+ return 1;
+ }
+ return 0;
+}
+
+void rgb_blit_16(int8_t * buff, int32_t x, int32_t y, int32_t w, int32_t h) {
+ //fprintf(stderr, "BlitToYUV\n");
+ int16_t * src_pxl;
+ int8_t * dst_pxl;
+ int32_t startxy;
+ int32_t _x, _y;
+
+ startxy = 0;
+ dst_pxl = buff;
+ for (_y = y; _y < h; ++_y) {
+ src_pxl = &g_gpu.psx_vram.s16[startxy];
+ for (_x = x; _x < w; ++_x) {
+ dst_pxl[0] = ((*src_pxl) << 3) & 0xf8;
+ dst_pxl[1] = ((*src_pxl) >> 2) & 0xf8;
+ dst_pxl[2] = ((*src_pxl) >> 7) & 0xf8;
+ dst_pxl += 3;
+ src_pxl += 1;
+ }
+ startxy += 2048;
+ }
+}
+
+void rgb_blit_24(int8_t * buff, int32_t x, int32_t y, int32_t w, int32_t h) {
+ //fprintf(stderr, "BlitToYUV\n");
+ int8_t * src_pxl;
+ int8_t * dst_pxl;
+ int32_t startxy;
+ int32_t _x, _y;
+
+ dst_pxl = buff;
+ startxy = 0;
+ for (_y = y; _y < h; ++_y) {
+ src_pxl = &g_gpu.psx_vram.s8[startxy];
+ for (_x = x; _x < w; ++_x) {
+ dst_pxl[0] = src_pxl[0];
+ dst_pxl[1] = src_pxl[1];
+ dst_pxl[2] = src_pxl[2];
+ dst_pxl += 3;
+ src_pxl += 3;
+ }
+ startxy += 2048;
+ }
+}
+
+int yuyv_check_port(XvImageFormatValues * fo) {
+ if (fo->type == XvYUV && fo->bits_per_pixel == 16 && fo->format == XvPacked
+ && strncmp("UYVY", fo->component_order, 4) == 0) {
+ g_draw.xv_id = fo->id;
+ return 1;
+ }
+ return 0;
+}
+
+void yuyv_blit_24(int8_t * buff, int32_t x, int32_t y, int32_t w, int32_t h) {
+ //fprintf(stderr, "yuyv_blit_24 %d %d %d %d\n", x, y, w, h);
+ uint8_t * src_pxl;
+ int8_t R0, G0, B0;
+ int8_t R1, G1, B1;
+ uint32_t * dst_pxl;
+ int32_t _x, _y;
+
+ /* x and w should be multiple of 2 to be align */
+ x = x & 0xfffffffe;
+ w = (w + 1) & 0xfffffffe;
+
+ dst_pxl = (uint32_t *) (buff);
+ for (_y = y; _y < (y + h); _y += 1) {
+ src_pxl = &g_gpu.psx_vram.u8[x * 3 + (_y * 2048)];
+ for (_x = 0; _x < (w / 2); ++_x) {
+ R0 = src_pxl[0];
+ G0 = src_pxl[1];
+ B0 = src_pxl[2];
+ R1 = src_pxl[3];
+ G1 = src_pxl[4];
+ B1 = src_pxl[5];
+ *dst_pxl++ = rgb_to_yuv2(R0, G0, B0, R1, G1, B1);
+ src_pxl += 6;
+ }
+ }
+}
+
+void yuyv_blit_16(int8_t * buff, int32_t x, int32_t y, int32_t w, int32_t h) {
+ //fprintf(stderr, "yuyv_blit_16 %d %d %d %d\n", x, y, w, h);
+ int8_t R0, G0, B0;
+ int8_t R1, G1, B1;
+ uint32_t * dst_pxl;
+ int32_t _x, _y;
+ int32_t s;
+ uint16_t * src_pxl;
+
+ /* x must be a multiple of 2 */
+ /* x and w must be a multiple of 2 */
+ x = x & 0xfffffffe;
+ w = (w + 1) & 0xfffffffe;
+
+ dst_pxl = (uint32_t *) (buff);
+ for (_y = y; _y < (y + h); _y += 1) {
+ src_pxl = &g_gpu.psx_vram.u16[x + (_y * 1024)];
+ for (_x = 0; _x < (w / 2); ++_x) {
+ s = GETLE16(src_pxl++);
+ R0 = (s << 3) & 0xf8;
+ G0 = (s >> 2) & 0xf8;
+ B0 = (s >> 7) & 0xf8;
+ s = GETLE16(src_pxl++);
+ R1 = (s << 3) & 0xf8;
+ G1 = (s >> 2) & 0xf8;
+ B1 = (s >> 7) & 0xf8;
+ *dst_pxl++ = rgb_to_yuv2(R0, G0, B0, R1, G1, B1);
+ }
+ }
+}
+
+/**
+ * compute the position and the size of output screen
+ * The aspect of the psx output mode is preserved.
+ * Note: dest dx,dy,dw,dh are both input and output variables
+ */
+inline void maintain_aspect(uint32_t * dx, uint32_t * dy, uint32_t * dw,
+ uint32_t * dh, int32_t w, int32_t h) {
+
+ double ratio_x = ((double) *dw) / ((double) w);
+ double ratio_y = ((double) *dh) / ((double) h);
+
+ double ratio;
+ if (ratio_x < ratio_y) {
+ ratio = ratio_x;
+ } else {
+ ratio = ratio_y;
+ }
+
+ uint32_t tw = (uint32_t) floor(w * ratio);
+ uint32_t th = (uint32_t) floor(h * ratio);
+
+ *dx += (uint32_t) floor((*dw - tw) / 2.0);
+ *dy += (uint32_t) floor((*dh - th) / 2.0);
+ *dw = tw;
+ *dh = th;
+}
+
+void do_buffer_swap(void) {
+ //Screen *screen;
+ Window _dw;
+ XvImage *xvi;
+ unsigned int dstx, dsty;
+ unsigned int _d, _w, _h; //don't care about _d
+
+ dstx = 0;
+ dsty = 0;
+
+ XSync(g_draw.display, False);
+
+ XGetGeometry(g_draw.display, g_draw.window, &_dw, (int *) &_d, (int *) &_d,
+ &_w, &_h, &_d, &_d);
+
+ if (g_cfg.ShowFPS) {
+ dsty += 15;
+ _h -= 15;
+ compute_fps();
+ snprintf(g_draw.msg, 511, "FPS : %f", g_draw.fps);
+ XDrawImageString(g_draw.display, g_draw.window, g_draw.hGC, 0, 12,
+ g_draw.msg, strlen(g_draw.msg));
+ }
+
+ uint32_t _x_, _y_, _w_, _h_;
+
+ /* if video mode is valid */
+ if (g_gpu.dsp.mode.x) {
+
+ if (g_gpu.status_reg & STATUS_RGB24) {
+ _x_ = (g_gpu.dsp.position.x * 2) / 3;
+ } else {
+ _x_ = g_gpu.dsp.position.x;
+ }
+ _y_ = g_gpu.dsp.position.y;
+ _w_ = (g_gpu.dsp.range.x1 - g_gpu.dsp.range.x0) / g_gpu.dsp.mode.x;
+ _h_ = (g_gpu.dsp.range.y1 - g_gpu.dsp.range.y0) * g_gpu.dsp.mode.y;
+
+ if (g_gpu.status_reg & STATUS_RGB24) {
+ available_port[g_draw.xv].blit_24_bits(
+ (int8_t *) g_draw.shminfo.shmaddr, _x_, _y_, _w_, _h_);
+ } else {
+ available_port[GXV_YUV_PORT].blit_16_bits(
+ (int8_t *) g_draw.shminfo.shmaddr, _x_, _y_, _w_, _h_);
+ }
+
+ xvi = XvShmCreateImage(g_draw.display, g_draw.xv_port, g_draw.xv_id, 0,
+ _w_, _h_, &g_draw.shminfo);
+
+ xvi->data = g_draw.shminfo.shmaddr;
+
+ //screen = DefaultScreenOfDisplay(g_draw.display);
+ //screennum = DefaultScreen(display);
+
+ // if (g_cfg.FullScreen) {
+ // _w = screen->width;
+ // _h = screen->height;
+ // }
+
+ if (g_cfg.Maintain43)
+ maintain_aspect(&dstx, &dsty, &_w, &_h, _w_, (g_gpu.dsp.range.y1
+ - g_gpu.dsp.range.y0));
+
+ // int _i;
+ // int32_t * dst_pxl;
+ // dst_pxl = (int32_t *) &g_draw.shminfo.shmaddr[2048 * _y_];
+ // for (_i = _x_ / 2; _i < (_x_ + _w_) / 2; ++_i)
+ // dst_pxl[_i] = rgb_to_yuv2(255, 0, 0, 255, 0, 0);
+ // dst_pxl = (int32_t *) &g_draw.shminfo.shmaddr[2048 * (_y_ + _h_)];
+ // for (_i = _x_ / 2; _i < (_x_ + _w_) / 2; ++_i)
+ // dst_pxl[_i] = rgb_to_yuv2(255, 0, 0, 255, 0, 0);
+ // dst_pxl = (int32_t *) &g_draw.shminfo.shmaddr[4 * (_x_ / 2)];
+ // for (_i = _y_; _i < (_y_ + _h_); ++_i)
+ // dst_pxl[_i * 512] = rgb_to_yuv2(255, 0, 0, 255, 0, 0);
+ // dst_pxl = (int32_t *) &g_draw.shminfo.shmaddr[4 * ((_x_ + _w_) / 2)];
+ // for (_i = _y_; _i < (_y_ + _h_); ++_i)
+ // dst_pxl[_i * 512] = rgb_to_yuv2(255, 0, 0, 255, 0, 0);
+
+ //fprintf(stderr, "From %d,%d,%d,%d\n", _x_, _y_, _w_, _h_);
+ XvShmPutImage(g_draw.display, g_draw.xv_port, g_draw.window,
+ g_draw.hGC, xvi, 0, 0, _w_, _h_,
+ //0, 0, 1024, 512,
+ /* dst */
+ dstx, dsty, _w, _h, 1);
+ XFree(xvi);
+ }
+}
+
+void do_clear_screen_buffer(void) // CLEAR DX BUFFER
+{
+ XClearWindow(g_draw.display, g_draw.window);
+}
+
+void Xcleanup() // X CLEANUP
+{
+ //CloseMenu();
+}
+
+/**
+ * Call on GPUopen
+ * Return the current display.
+ **/
+unsigned long init_display() {
+
+ available_port[GXV_YUV_PORT].blit_24_bits = yuyv_blit_24;
+ available_port[GXV_YUV_PORT].blit_16_bits = yuyv_blit_16;
+
+ available_port[GXV_RGB_PORT].blit_24_bits = rgb_blit_24;
+ available_port[GXV_RGB_PORT].blit_16_bits = rgb_blit_16;
+
+ create_display(); // x stuff
+ g_draw.bIsFirstFrame = 0;
+ return (unsigned long) g_draw.display;
+}
+
+void CloseDisplay(void) {
+ Xcleanup(); // cleanup dx
+ DestroyDisplay();
+}
+
+void CreatePic(unsigned char * pMem) {
+ unsigned char * p = (unsigned char *) malloc(128 * 96 * 4);
+ unsigned char * ps;
+ //int x, y;
+
+ ps = p;
+
+ // if (iDesktopCol == 16) {
+ // unsigned short s;
+ // for (y = 0; y < 96; y++) {
+ // for (x = 0; x < 128; x++) {
+ // s = (*(pMem + 0)) >> 3;
+ // s |= ((*(pMem + 1)) & 0xfc) << 3;
+ // s |= ((*(pMem + 2)) & 0xf8) << 8;
+ // pMem += 3;
+ // *((unsigned short *) (ps + y * 256 + x * 2)) = s;
+ // }
+ // }
+ // } else if (iDesktopCol == 15) {
+ // unsigned short s;
+ // for (y = 0; y < 96; y++) {
+ // for (x = 0; x < 128; x++) {
+ // s = (*(pMem + 0)) >> 3;
+ // s |= ((*(pMem + 1)) & 0xfc) << 2;
+ // s |= ((*(pMem + 2)) & 0xf8) << 7;
+ // pMem += 3;
+ // *((unsigned short *) (ps + y * 256 + x * 2)) = s;
+ // }
+ // }
+ // } else if (iDesktopCol == 32) {
+ // uint32_t l;
+ // for (y = 0; y < 96; y++) {
+ // for (x = 0; x < 128; x++) {
+ // l = *(pMem + 0);
+ // l |= (*(pMem + 1)) << 8;
+ // l |= (*(pMem + 2)) << 16;
+ // pMem += 3;
+ // *((uint32_t *) (ps + y * 512 + x * 4)) = l;
+ // }
+ // }
+ // }
+
+ g_draw.XPimage = XCreateImage(g_draw.display, g_draw.myvisual->visual,
+ g_draw.depth, ZPixmap, 0, (char *) p, 128, 96,
+ g_draw.depth > 16 ? 32 : 16, 0);
+}
+
+void DestroyPic(void) {
+ if (g_draw.XPimage) { /*
+ XPutImage(display,window,hGC, XCimage,
+ 0, 0, 0, 0, iResX, iResY);*/
+ XDestroyImage(g_draw.XPimage);
+ g_draw.XPimage = 0;
+ }
+}
+
+void ShowGpuPic(void) {
+}
+
+void ShowTextGpuPic(void) {
+}
|
