diff options
Diffstat (limited to '3rdparty/SDL/src/video')
364 files changed, 113392 insertions, 0 deletions
diff --git a/3rdparty/SDL/src/video/SDL_RLEaccel.c b/3rdparty/SDL/src/video/SDL_RLEaccel.c new file mode 100644 index 0000000..d4b191c --- /dev/null +++ b/3rdparty/SDL/src/video/SDL_RLEaccel.c @@ -0,0 +1,1941 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* + * RLE encoding for software colorkey and alpha-channel acceleration + * + * Original version by Sam Lantinga + * + * Mattias Engdegrd (Yorick): Rewrite. New encoding format, encoder and + * decoder. Added per-surface alpha blitter. Added per-pixel alpha + * format, encoder and blitter. + * + * Many thanks to Xark and johns for hints, benchmarks and useful comments + * leading to this code. + * + * Welcome to Macro Mayhem. + */ + +/* + * The encoding translates the image data to a stream of segments of the form + * + * <skip> <run> <data> + * + * where <skip> is the number of transparent pixels to skip, + * <run> is the number of opaque pixels to blit, + * and <data> are the pixels themselves. + * + * This basic structure is used both for colorkeyed surfaces, used for simple + * binary transparency and for per-surface alpha blending, and for surfaces + * with per-pixel alpha. The details differ, however: + * + * Encoding of colorkeyed surfaces: + * + * Encoded pixels always have the same format as the target surface. + * <skip> and <run> are unsigned 8 bit integers, except for 32 bit depth + * where they are 16 bit. This makes the pixel data aligned at all times. + * Segments never wrap around from one scan line to the next. + * + * The end of the sequence is marked by a zero <skip>,<run> pair at the * + * beginning of a line. + * + * Encoding of surfaces with per-pixel alpha: + * + * The sequence begins with a struct RLEDestFormat describing the target + * pixel format, to provide reliable un-encoding. + * + * Each scan line is encoded twice: First all completely opaque pixels, + * encoded in the target format as described above, and then all + * partially transparent (translucent) pixels (where 1 <= alpha <= 254), + * in the following 32-bit format: + * + * For 32-bit targets, each pixel has the target RGB format but with + * the alpha value occupying the highest 8 bits. The <skip> and <run> + * counts are 16 bit. + * + * For 16-bit targets, each pixel has the target RGB format, but with + * the middle component (usually green) shifted 16 steps to the left, + * and the hole filled with the 5 most significant bits of the alpha value. + * i.e. if the target has the format rrrrrggggggbbbbb, + * the encoded pixel will be 00000gggggg00000rrrrr0aaaaabbbbb. + * The <skip> and <run> counts are 8 bit for the opaque lines, 16 bit + * for the translucent lines. Two padding bytes may be inserted + * before each translucent line to keep them 32-bit aligned. + * + * The end of the sequence is marked by a zero <skip>,<run> pair at the + * beginning of an opaque line. + */ + +#include "SDL_video.h" +#include "SDL_sysvideo.h" +#include "SDL_blit.h" +#include "SDL_RLEaccel_c.h" + +/* Force MMX to 0; this blows up on almost every major compiler now. --ryan. */ +#if 0 && defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__)) && SDL_ASSEMBLY_ROUTINES +#define MMX_ASMBLIT +#endif + +#ifdef MMX_ASMBLIT +#include "mmx.h" +#include "SDL_cpuinfo.h" +#endif + +#ifndef MAX +#define MAX(a, b) ((a) > (b) ? (a) : (b)) +#endif +#ifndef MIN +#define MIN(a, b) ((a) < (b) ? (a) : (b)) +#endif + +#define PIXEL_COPY(to, from, len, bpp) \ +do { \ + if(bpp == 4) { \ + SDL_memcpy4(to, from, (size_t)(len)); \ + } else { \ + SDL_memcpy(to, from, (size_t)(len) * (bpp)); \ + } \ +} while(0) + +/* + * Various colorkey blit methods, for opaque and per-surface alpha + */ + +#define OPAQUE_BLIT(to, from, length, bpp, alpha) \ + PIXEL_COPY(to, from, length, bpp) + +#ifdef MMX_ASMBLIT + +#define ALPHA_BLIT32_888MMX(to, from, length, bpp, alpha) \ + do { \ + Uint32 *srcp = (Uint32 *)(from); \ + Uint32 *dstp = (Uint32 *)(to); \ + int i = 0x00FF00FF; \ + movd_m2r(*(&i), mm3); \ + punpckldq_r2r(mm3, mm3); \ + i = 0xFF000000; \ + movd_m2r(*(&i), mm7); \ + punpckldq_r2r(mm7, mm7); \ + i = alpha | alpha << 16; \ + movd_m2r(*(&i), mm4); \ + punpckldq_r2r(mm4, mm4); \ + pcmpeqd_r2r(mm5,mm5); /* set mm5 to "1" */ \ + pxor_r2r(mm7, mm5); /* make clear alpha mask */ \ + i = length; \ + if(i & 1) { \ + movd_m2r((*srcp), mm1); /* src -> mm1 */ \ + punpcklbw_r2r(mm1, mm1); \ + pand_r2r(mm3, mm1); \ + movd_m2r((*dstp), mm2); /* dst -> mm2 */ \ + punpcklbw_r2r(mm2, mm2); \ + pand_r2r(mm3, mm2); \ + psubw_r2r(mm2, mm1); \ + pmullw_r2r(mm4, mm1); \ + psrlw_i2r(8, mm1); \ + paddw_r2r(mm1, mm2); \ + pand_r2r(mm3, mm2); \ + packuswb_r2r(mm2, mm2); \ + pand_r2r(mm5, mm2); /* 00000RGB -> mm2 */ \ + movd_r2m(mm2, *dstp); \ + ++srcp; \ + ++dstp; \ + i--; \ + } \ + for(; i > 0; --i) { \ + movq_m2r((*srcp), mm0); \ + movq_r2r(mm0, mm1); \ + punpcklbw_r2r(mm0, mm0); \ + movq_m2r((*dstp), mm2); \ + punpckhbw_r2r(mm1, mm1); \ + movq_r2r(mm2, mm6); \ + pand_r2r(mm3, mm0); \ + punpcklbw_r2r(mm2, mm2); \ + pand_r2r(mm3, mm1); \ + punpckhbw_r2r(mm6, mm6); \ + pand_r2r(mm3, mm2); \ + psubw_r2r(mm2, mm0); \ + pmullw_r2r(mm4, mm0); \ + pand_r2r(mm3, mm6); \ + psubw_r2r(mm6, mm1); \ + pmullw_r2r(mm4, mm1); \ + psrlw_i2r(8, mm0); \ + paddw_r2r(mm0, mm2); \ + psrlw_i2r(8, mm1); \ + paddw_r2r(mm1, mm6); \ + pand_r2r(mm3, mm2); \ + pand_r2r(mm3, mm6); \ + packuswb_r2r(mm2, mm2); \ + packuswb_r2r(mm6, mm6); \ + psrlq_i2r(32, mm2); \ + psllq_i2r(32, mm6); \ + por_r2r(mm6, mm2); \ + pand_r2r(mm5, mm2); /* 00000RGB -> mm2 */ \ + movq_r2m(mm2, *dstp); \ + srcp += 2; \ + dstp += 2; \ + i--; \ + } \ + emms(); \ + } while(0) + +#define ALPHA_BLIT16_565MMX(to, from, length, bpp, alpha) \ + do { \ + int i, n = 0; \ + Uint16 *srcp = (Uint16 *)(from); \ + Uint16 *dstp = (Uint16 *)(to); \ + Uint32 ALPHA = 0xF800; \ + movd_m2r(*(&ALPHA), mm1); \ + punpcklwd_r2r(mm1, mm1); \ + punpcklwd_r2r(mm1, mm1); \ + ALPHA = 0x07E0; \ + movd_m2r(*(&ALPHA), mm4); \ + punpcklwd_r2r(mm4, mm4); \ + punpcklwd_r2r(mm4, mm4); \ + ALPHA = 0x001F; \ + movd_m2r(*(&ALPHA), mm7); \ + punpcklwd_r2r(mm7, mm7); \ + punpcklwd_r2r(mm7, mm7); \ + alpha &= ~(1+2+4); \ + i = (Uint32)alpha | (Uint32)alpha << 16; \ + movd_m2r(*(&i), mm0); \ + punpckldq_r2r(mm0, mm0); \ + ALPHA = alpha >> 3; \ + i = ((int)(length) & 3); \ + for(; i > 0; --i) { \ + Uint32 s = *srcp++; \ + Uint32 d = *dstp; \ + s = (s | s << 16) & 0x07e0f81f; \ + d = (d | d << 16) & 0x07e0f81f; \ + d += (s - d) * ALPHA >> 5; \ + d &= 0x07e0f81f; \ + *dstp++ = d | d >> 16; \ + n++; \ + } \ + i = (int)(length) - n; \ + for(; i > 0; --i) { \ + movq_m2r((*dstp), mm3); \ + movq_m2r((*srcp), mm2); \ + movq_r2r(mm2, mm5); \ + pand_r2r(mm1 , mm5); \ + psrlq_i2r(11, mm5); \ + movq_r2r(mm3, mm6); \ + pand_r2r(mm1 , mm6); \ + psrlq_i2r(11, mm6); \ + psubw_r2r(mm6, mm5); \ + pmullw_r2r(mm0, mm5); \ + psrlw_i2r(8, mm5); \ + paddw_r2r(mm5, mm6); \ + psllq_i2r(11, mm6); \ + pand_r2r(mm1, mm6); \ + movq_r2r(mm4, mm5); \ + por_r2r(mm7, mm5); \ + pand_r2r(mm5, mm3); \ + por_r2r(mm6, mm3); \ + movq_r2r(mm2, mm5); \ + pand_r2r(mm4 , mm5); \ + psrlq_i2r(5, mm5); \ + movq_r2r(mm3, mm6); \ + pand_r2r(mm4 , mm6); \ + psrlq_i2r(5, mm6); \ + psubw_r2r(mm6, mm5); \ + pmullw_r2r(mm0, mm5); \ + psrlw_i2r(8, mm5); \ + paddw_r2r(mm5, mm6); \ + psllq_i2r(5, mm6); \ + pand_r2r(mm4, mm6); \ + movq_r2r(mm1, mm5); \ + por_r2r(mm7, mm5); \ + pand_r2r(mm5, mm3); \ + por_r2r(mm6, mm3); \ + movq_r2r(mm2, mm5); \ + pand_r2r(mm7 , mm5); \ + movq_r2r(mm3, mm6); \ + pand_r2r(mm7 , mm6); \ + psubw_r2r(mm6, mm5); \ + pmullw_r2r(mm0, mm5); \ + psrlw_i2r(8, mm5); \ + paddw_r2r(mm5, mm6); \ + pand_r2r(mm7, mm6); \ + movq_r2r(mm1, mm5); \ + por_r2r(mm4, mm5); \ + pand_r2r(mm5, mm3); \ + por_r2r(mm6, mm3); \ + movq_r2m(mm3, *dstp); \ + srcp += 4; \ + dstp += 4; \ + i -= 3; \ + } \ + emms(); \ + } while(0) + +#define ALPHA_BLIT16_555MMX(to, from, length, bpp, alpha) \ + do { \ + int i, n = 0; \ + Uint16 *srcp = (Uint16 *)(from); \ + Uint16 *dstp = (Uint16 *)(to); \ + Uint32 ALPHA = 0x7C00; \ + movd_m2r(*(&ALPHA), mm1); \ + punpcklwd_r2r(mm1, mm1); \ + punpcklwd_r2r(mm1, mm1); \ + ALPHA = 0x03E0; \ + movd_m2r(*(&ALPHA), mm4); \ + punpcklwd_r2r(mm4, mm4); \ + punpcklwd_r2r(mm4, mm4); \ + ALPHA = 0x001F; \ + movd_m2r(*(&ALPHA), mm7); \ + punpcklwd_r2r(mm7, mm7); \ + punpcklwd_r2r(mm7, mm7); \ + alpha &= ~(1+2+4); \ + i = (Uint32)alpha | (Uint32)alpha << 16; \ + movd_m2r(*(&i), mm0); \ + punpckldq_r2r(mm0, mm0); \ + i = ((int)(length) & 3); \ + ALPHA = alpha >> 3; \ + for(; i > 0; --i) { \ + Uint32 s = *srcp++; \ + Uint32 d = *dstp; \ + s = (s | s << 16) & 0x03e07c1f; \ + d = (d | d << 16) & 0x03e07c1f; \ + d += (s - d) * ALPHA >> 5; \ + d &= 0x03e07c1f; \ + *dstp++ = d | d >> 16; \ + n++; \ + } \ + i = (int)(length) - n; \ + for(; i > 0; --i) { \ + movq_m2r((*dstp), mm3); \ + movq_m2r((*srcp), mm2); \ + movq_r2r(mm2, mm5); \ + pand_r2r(mm1 , mm5); \ + psrlq_i2r(10, mm5); \ + movq_r2r(mm3, mm6); \ + pand_r2r(mm1 , mm6); \ + psrlq_i2r(10, mm6); \ + psubw_r2r(mm6, mm5); \ + pmullw_r2r(mm0, mm5); \ + psrlw_i2r(8, mm5); \ + paddw_r2r(mm5, mm6); \ + psllq_i2r(10, mm6); \ + pand_r2r(mm1, mm6); \ + movq_r2r(mm4, mm5); \ + por_r2r(mm7, mm5); \ + pand_r2r(mm5, mm3); \ + por_r2r(mm6, mm3); \ + movq_r2r(mm2, mm5); \ + pand_r2r(mm4 , mm5); \ + psrlq_i2r(5, mm5); \ + movq_r2r(mm3, mm6); \ + pand_r2r(mm4 , mm6); \ + psrlq_i2r(5, mm6); \ + psubw_r2r(mm6, mm5); \ + pmullw_r2r(mm0, mm5); \ + psrlw_i2r(8, mm5); \ + paddw_r2r(mm5, mm6); \ + psllq_i2r(5, mm6); \ + pand_r2r(mm4, mm6); \ + movq_r2r(mm1, mm5); \ + por_r2r(mm7, mm5); \ + pand_r2r(mm5, mm3); \ + por_r2r(mm6, mm3); \ + movq_r2r(mm2, mm5); \ + pand_r2r(mm7 , mm5); \ + movq_r2r(mm3, mm6); \ + pand_r2r(mm7 , mm6); \ + psubw_r2r(mm6, mm5); \ + pmullw_r2r(mm0, mm5); \ + psrlw_i2r(8, mm5); \ + paddw_r2r(mm5, mm6); \ + pand_r2r(mm7, mm6); \ + movq_r2r(mm1, mm5); \ + por_r2r(mm4, mm5); \ + pand_r2r(mm5, mm3); \ + por_r2r(mm6, mm3); \ + movq_r2m(mm3, *dstp); \ + srcp += 4; \ + dstp += 4; \ + i -= 3; \ + } \ + emms(); \ + } while(0) + +#endif + +/* + * For 32bpp pixels on the form 0x00rrggbb: + * If we treat the middle component separately, we can process the two + * remaining in parallel. This is safe to do because of the gap to the left + * of each component, so the bits from the multiplication don't collide. + * This can be used for any RGB permutation of course. + */ +#define ALPHA_BLIT32_888(to, from, length, bpp, alpha) \ + do { \ + int i; \ + Uint32 *src = (Uint32 *)(from); \ + Uint32 *dst = (Uint32 *)(to); \ + for(i = 0; i < (int)(length); i++) { \ + Uint32 s = *src++; \ + Uint32 d = *dst; \ + Uint32 s1 = s & 0xff00ff; \ + Uint32 d1 = d & 0xff00ff; \ + d1 = (d1 + ((s1 - d1) * alpha >> 8)) & 0xff00ff; \ + s &= 0xff00; \ + d &= 0xff00; \ + d = (d + ((s - d) * alpha >> 8)) & 0xff00; \ + *dst++ = d1 | d; \ + } \ + } while(0) + +/* + * For 16bpp pixels we can go a step further: put the middle component + * in the high 16 bits of a 32 bit word, and process all three RGB + * components at the same time. Since the smallest gap is here just + * 5 bits, we have to scale alpha down to 5 bits as well. + */ +#define ALPHA_BLIT16_565(to, from, length, bpp, alpha) \ + do { \ + int i; \ + Uint16 *src = (Uint16 *)(from); \ + Uint16 *dst = (Uint16 *)(to); \ + Uint32 ALPHA = alpha >> 3; \ + for(i = 0; i < (int)(length); i++) { \ + Uint32 s = *src++; \ + Uint32 d = *dst; \ + s = (s | s << 16) & 0x07e0f81f; \ + d = (d | d << 16) & 0x07e0f81f; \ + d += (s - d) * ALPHA >> 5; \ + d &= 0x07e0f81f; \ + *dst++ = (Uint16)(d | d >> 16); \ + } \ + } while(0) + +#define ALPHA_BLIT16_555(to, from, length, bpp, alpha) \ + do { \ + int i; \ + Uint16 *src = (Uint16 *)(from); \ + Uint16 *dst = (Uint16 *)(to); \ + Uint32 ALPHA = alpha >> 3; \ + for(i = 0; i < (int)(length); i++) { \ + Uint32 s = *src++; \ + Uint32 d = *dst; \ + s = (s | s << 16) & 0x03e07c1f; \ + d = (d | d << 16) & 0x03e07c1f; \ + d += (s - d) * ALPHA >> 5; \ + d &= 0x03e07c1f; \ + *dst++ = (Uint16)(d | d >> 16); \ + } \ + } while(0) + +/* + * The general slow catch-all function, for remaining depths and formats + */ +#define ALPHA_BLIT_ANY(to, from, length, bpp, alpha) \ + do { \ + int i; \ + Uint8 *src = from; \ + Uint8 *dst = to; \ + for(i = 0; i < (int)(length); i++) { \ + Uint32 s, d; \ + unsigned rs, gs, bs, rd, gd, bd; \ + switch(bpp) { \ + case 2: \ + s = *(Uint16 *)src; \ + d = *(Uint16 *)dst; \ + break; \ + case 3: \ + if(SDL_BYTEORDER == SDL_BIG_ENDIAN) { \ + s = (src[0] << 16) | (src[1] << 8) | src[2]; \ + d = (dst[0] << 16) | (dst[1] << 8) | dst[2]; \ + } else { \ + s = (src[2] << 16) | (src[1] << 8) | src[0]; \ + d = (dst[2] << 16) | (dst[1] << 8) | dst[0]; \ + } \ + break; \ + case 4: \ + s = *(Uint32 *)src; \ + d = *(Uint32 *)dst; \ + break; \ + } \ + RGB_FROM_PIXEL(s, fmt, rs, gs, bs); \ + RGB_FROM_PIXEL(d, fmt, rd, gd, bd); \ + rd += (rs - rd) * alpha >> 8; \ + gd += (gs - gd) * alpha >> 8; \ + bd += (bs - bd) * alpha >> 8; \ + PIXEL_FROM_RGB(d, fmt, rd, gd, bd); \ + switch(bpp) { \ + case 2: \ + *(Uint16 *)dst = (Uint16)d; \ + break; \ + case 3: \ + if(SDL_BYTEORDER == SDL_BIG_ENDIAN) { \ + dst[0] = (Uint8)(d >> 16); \ + dst[1] = (Uint8)(d >> 8); \ + dst[2] = (Uint8)(d); \ + } else { \ + dst[0] = (Uint8)d; \ + dst[1] = (Uint8)(d >> 8); \ + dst[2] = (Uint8)(d >> 16); \ + } \ + break; \ + case 4: \ + *(Uint32 *)dst = d; \ + break; \ + } \ + src += bpp; \ + dst += bpp; \ + } \ + } while(0) + +#ifdef MMX_ASMBLIT + +#define ALPHA_BLIT32_888_50MMX(to, from, length, bpp, alpha) \ + do { \ + Uint32 *srcp = (Uint32 *)(from); \ + Uint32 *dstp = (Uint32 *)(to); \ + int i = 0x00fefefe; \ + movd_m2r(*(&i), mm4); \ + punpckldq_r2r(mm4, mm4); \ + i = 0x00010101; \ + movd_m2r(*(&i), mm3); \ + punpckldq_r2r(mm3, mm3); \ + i = (int)(length); \ + if( i & 1 ) { \ + Uint32 s = *srcp++; \ + Uint32 d = *dstp; \ + *dstp++ = (((s & 0x00fefefe) + (d & 0x00fefefe)) >> 1) \ + + (s & d & 0x00010101); \ + i--; \ + } \ + for(; i > 0; --i) { \ + movq_m2r((*dstp), mm2); /* dst -> mm2 */ \ + movq_r2r(mm2, mm6); /* dst -> mm6 */ \ + movq_m2r((*srcp), mm1); /* src -> mm1 */ \ + movq_r2r(mm1, mm5); /* src -> mm5 */ \ + pand_r2r(mm4, mm6); /* dst & 0x00fefefe -> mm6 */ \ + pand_r2r(mm4, mm5); /* src & 0x00fefefe -> mm5 */ \ + paddd_r2r(mm6, mm5); /* (dst & 0x00fefefe) + (dst & 0x00fefefe) -> mm5 */ \ + psrld_i2r(1, mm5); \ + pand_r2r(mm1, mm2); /* s & d -> mm2 */ \ + pand_r2r(mm3, mm2); /* s & d & 0x00010101 -> mm2 */ \ + paddd_r2r(mm5, mm2); \ + movq_r2m(mm2, (*dstp)); \ + dstp += 2; \ + srcp += 2; \ + i--; \ + } \ + emms(); \ + } while(0) + +#endif + +/* + * Special case: 50% alpha (alpha=128) + * This is treated specially because it can be optimized very well, and + * since it is good for many cases of semi-translucency. + * The theory is to do all three components at the same time: + * First zero the lowest bit of each component, which gives us room to + * add them. Then shift right and add the sum of the lowest bits. + */ +#define ALPHA_BLIT32_888_50(to, from, length, bpp, alpha) \ + do { \ + int i; \ + Uint32 *src = (Uint32 *)(from); \ + Uint32 *dst = (Uint32 *)(to); \ + for(i = 0; i < (int)(length); i++) { \ + Uint32 s = *src++; \ + Uint32 d = *dst; \ + *dst++ = (((s & 0x00fefefe) + (d & 0x00fefefe)) >> 1) \ + + (s & d & 0x00010101); \ + } \ + } while(0) + +/* + * For 16bpp, we can actually blend two pixels in parallel, if we take + * care to shift before we add, not after. + */ + +/* helper: blend a single 16 bit pixel at 50% */ +#define BLEND16_50(dst, src, mask) \ + do { \ + Uint32 s = *src++; \ + Uint32 d = *dst; \ + *dst++ = (Uint16)((((s & mask) + (d & mask)) >> 1) + \ + (s & d & (~mask & 0xffff))); \ + } while(0) + +/* basic 16bpp blender. mask is the pixels to keep when adding. */ +#define ALPHA_BLIT16_50(to, from, length, bpp, alpha, mask) \ + do { \ + unsigned n = (length); \ + Uint16 *src = (Uint16 *)(from); \ + Uint16 *dst = (Uint16 *)(to); \ + if(((uintptr_t)src ^ (uintptr_t)dst) & 3) { \ + /* source and destination not in phase, blit one by one */ \ + while(n--) \ + BLEND16_50(dst, src, mask); \ + } else { \ + if((uintptr_t)src & 3) { \ + /* first odd pixel */ \ + BLEND16_50(dst, src, mask); \ + n--; \ + } \ + for(; n > 1; n -= 2) { \ + Uint32 s = *(Uint32 *)src; \ + Uint32 d = *(Uint32 *)dst; \ + *(Uint32 *)dst = ((s & (mask | mask << 16)) >> 1) \ + + ((d & (mask | mask << 16)) >> 1) \ + + (s & d & (~(mask | mask << 16))); \ + src += 2; \ + dst += 2; \ + } \ + if(n) \ + BLEND16_50(dst, src, mask); /* last odd pixel */ \ + } \ + } while(0) + +#define ALPHA_BLIT16_565_50(to, from, length, bpp, alpha) \ + ALPHA_BLIT16_50(to, from, length, bpp, alpha, 0xf7de) + +#define ALPHA_BLIT16_555_50(to, from, length, bpp, alpha) \ + ALPHA_BLIT16_50(to, from, length, bpp, alpha, 0xfbde) + +#ifdef MMX_ASMBLIT + +#define CHOOSE_BLIT(blitter, alpha, fmt) \ + do { \ + if(alpha == 255) { \ + switch(fmt->BytesPerPixel) { \ + case 1: blitter(1, Uint8, OPAQUE_BLIT); break; \ + case 2: blitter(2, Uint8, OPAQUE_BLIT); break; \ + case 3: blitter(3, Uint8, OPAQUE_BLIT); break; \ + case 4: blitter(4, Uint16, OPAQUE_BLIT); break; \ + } \ + } else { \ + switch(fmt->BytesPerPixel) { \ + case 1: \ + /* No 8bpp alpha blitting */ \ + break; \ + \ + case 2: \ + switch(fmt->Rmask | fmt->Gmask | fmt->Bmask) { \ + case 0xffff: \ + if(fmt->Gmask == 0x07e0 \ + || fmt->Rmask == 0x07e0 \ + || fmt->Bmask == 0x07e0) { \ + if(alpha == 128) \ + blitter(2, Uint8, ALPHA_BLIT16_565_50); \ + else { \ + if(SDL_HasMMX()) \ + blitter(2, Uint8, ALPHA_BLIT16_565MMX); \ + else \ + blitter(2, Uint8, ALPHA_BLIT16_565); \ + } \ + } else \ + goto general16; \ + break; \ + \ + case 0x7fff: \ + if(fmt->Gmask == 0x03e0 \ + || fmt->Rmask == 0x03e0 \ + || fmt->Bmask == 0x03e0) { \ + if(alpha == 128) \ + blitter(2, Uint8, ALPHA_BLIT16_555_50); \ + else { \ + if(SDL_HasMMX()) \ + blitter(2, Uint8, ALPHA_BLIT16_555MMX); \ + else \ + blitter(2, Uint8, ALPHA_BLIT16_555); \ + } \ + break; \ + } \ + /* fallthrough */ \ + \ + default: \ + general16: \ + blitter(2, Uint8, ALPHA_BLIT_ANY); \ + } \ + break; \ + \ + case 3: \ + blitter(3, Uint8, ALPHA_BLIT_ANY); \ + break; \ + \ + case 4: \ + if((fmt->Rmask | fmt->Gmask | fmt->Bmask) == 0x00ffffff \ + && (fmt->Gmask == 0xff00 || fmt->Rmask == 0xff00 \ + || fmt->Bmask == 0xff00)) { \ + if(alpha == 128) \ + { \ + if(SDL_HasMMX()) \ + blitter(4, Uint16, ALPHA_BLIT32_888_50MMX);\ + else \ + blitter(4, Uint16, ALPHA_BLIT32_888_50);\ + } \ + else \ + { \ + if(SDL_HasMMX()) \ + blitter(4, Uint16, ALPHA_BLIT32_888MMX);\ + else \ + blitter(4, Uint16, ALPHA_BLIT32_888); \ + } \ + } else \ + blitter(4, Uint16, ALPHA_BLIT_ANY); \ + break; \ + } \ + } \ + } while(0) + +#else + +#define CHOOSE_BLIT(blitter, alpha, fmt) \ + do { \ + if(alpha == 255) { \ + switch(fmt->BytesPerPixel) { \ + case 1: blitter(1, Uint8, OPAQUE_BLIT); break; \ + case 2: blitter(2, Uint8, OPAQUE_BLIT); break; \ + case 3: blitter(3, Uint8, OPAQUE_BLIT); break; \ + case 4: blitter(4, Uint16, OPAQUE_BLIT); break; \ + } \ + } else { \ + switch(fmt->BytesPerPixel) { \ + case 1: \ + /* No 8bpp alpha blitting */ \ + break; \ + \ + case 2: \ + switch(fmt->Rmask | fmt->Gmask | fmt->Bmask) { \ + case 0xffff: \ + if(fmt->Gmask == 0x07e0 \ + || fmt->Rmask == 0x07e0 \ + || fmt->Bmask == 0x07e0) { \ + if(alpha == 128) \ + blitter(2, Uint8, ALPHA_BLIT16_565_50); \ + else { \ + blitter(2, Uint8, ALPHA_BLIT16_565); \ + } \ + } else \ + goto general16; \ + break; \ + \ + case 0x7fff: \ + if(fmt->Gmask == 0x03e0 \ + || fmt->Rmask == 0x03e0 \ + || fmt->Bmask == 0x03e0) { \ + if(alpha == 128) \ + blitter(2, Uint8, ALPHA_BLIT16_555_50); \ + else { \ + blitter(2, Uint8, ALPHA_BLIT16_555); \ + } \ + break; \ + } \ + /* fallthrough */ \ + \ + default: \ + general16: \ + blitter(2, Uint8, ALPHA_BLIT_ANY); \ + } \ + break; \ + \ + case 3: \ + blitter(3, Uint8, ALPHA_BLIT_ANY); \ + break; \ + \ + case 4: \ + if((fmt->Rmask | fmt->Gmask | fmt->Bmask) == 0x00ffffff \ + && (fmt->Gmask == 0xff00 || fmt->Rmask == 0xff00 \ + || fmt->Bmask == 0xff00)) { \ + if(alpha == 128) \ + blitter(4, Uint16, ALPHA_BLIT32_888_50); \ + else \ + blitter(4, Uint16, ALPHA_BLIT32_888); \ + } else \ + blitter(4, Uint16, ALPHA_BLIT_ANY); \ + break; \ + } \ + } \ + } while(0) + +#endif + +/* + * This takes care of the case when the surface is clipped on the left and/or + * right. Top clipping has already been taken care of. + */ +static void RLEClipBlit(int w, Uint8 *srcbuf, SDL_Surface *dst, + Uint8 *dstbuf, SDL_Rect *srcrect, unsigned alpha) +{ + SDL_PixelFormat *fmt = dst->format; + +#define RLECLIPBLIT(bpp, Type, do_blit) \ + do { \ + int linecount = srcrect->h; \ + int ofs = 0; \ + int left = srcrect->x; \ + int right = left + srcrect->w; \ + dstbuf -= left * bpp; \ + for(;;) { \ + int run; \ + ofs += *(Type *)srcbuf; \ + run = ((Type *)srcbuf)[1]; \ + srcbuf += 2 * sizeof(Type); \ + if(run) { \ + /* clip to left and right borders */ \ + if(ofs < right) { \ + int start = 0; \ + int len = run; \ + int startcol; \ + if(left - ofs > 0) { \ + start = left - ofs; \ + len -= start; \ + if(len <= 0) \ + goto nocopy ## bpp ## do_blit; \ + } \ + startcol = ofs + start; \ + if(len > right - startcol) \ + len = right - startcol; \ + do_blit(dstbuf + startcol * bpp, srcbuf + start * bpp, \ + len, bpp, alpha); \ + } \ + nocopy ## bpp ## do_blit: \ + srcbuf += run * bpp; \ + ofs += run; \ + } else if(!ofs) \ + break; \ + if(ofs == w) { \ + ofs = 0; \ + dstbuf += dst->pitch; \ + if(!--linecount) \ + break; \ + } \ + } \ + } while(0) + + CHOOSE_BLIT(RLECLIPBLIT, alpha, fmt); + +#undef RLECLIPBLIT + +} + + +/* blit a colorkeyed RLE surface */ +int SDL_RLEBlit(SDL_Surface *src, SDL_Rect *srcrect, + SDL_Surface *dst, SDL_Rect *dstrect) +{ + Uint8 *dstbuf; + Uint8 *srcbuf; + int x, y; + int w = src->w; + unsigned alpha; + + /* Lock the destination if necessary */ + if ( SDL_MUSTLOCK(dst) ) { + if ( SDL_LockSurface(dst) < 0 ) { + return(-1); + } + } + + /* Set up the source and destination pointers */ + x = dstrect->x; + y = dstrect->y; + dstbuf = (Uint8 *)dst->pixels + + y * dst->pitch + x * src->format->BytesPerPixel; + srcbuf = (Uint8 *)src->map->sw_data->aux_data; + + { + /* skip lines at the top if neccessary */ + int vskip = srcrect->y; + int ofs = 0; + if(vskip) { + +#define RLESKIP(bpp, Type) \ + for(;;) { \ + int run; \ + ofs += *(Type *)srcbuf; \ + run = ((Type *)srcbuf)[1]; \ + srcbuf += sizeof(Type) * 2; \ + if(run) { \ + srcbuf += run * bpp; \ + ofs += run; \ + } else if(!ofs) \ + goto done; \ + if(ofs == w) { \ + ofs = 0; \ + if(!--vskip) \ + break; \ + } \ + } + + switch(src->format->BytesPerPixel) { + case 1: RLESKIP(1, Uint8); break; + case 2: RLESKIP(2, Uint8); break; + case 3: RLESKIP(3, Uint8); break; + case 4: RLESKIP(4, Uint16); break; + } + +#undef RLESKIP + + } + } + + alpha = (src->flags & SDL_SRCALPHA) == SDL_SRCALPHA + ? src->format->alpha : 255; + /* if left or right edge clipping needed, call clip blit */ + if ( srcrect->x || srcrect->w != src->w ) { + RLEClipBlit(w, srcbuf, dst, dstbuf, srcrect, alpha); + } else { + SDL_PixelFormat *fmt = src->format; + +#define RLEBLIT(bpp, Type, do_blit) \ + do { \ + int linecount = srcrect->h; \ + int ofs = 0; \ + for(;;) { \ + unsigned run; \ + ofs += *(Type *)srcbuf; \ + run = ((Type *)srcbuf)[1]; \ + srcbuf += 2 * sizeof(Type); \ + if(run) { \ + do_blit(dstbuf + ofs * bpp, srcbuf, run, bpp, alpha); \ + srcbuf += run * bpp; \ + ofs += run; \ + } else if(!ofs) \ + break; \ + if(ofs == w) { \ + ofs = 0; \ + dstbuf += dst->pitch; \ + if(!--linecount) \ + break; \ + } \ + } \ + } while(0) + + CHOOSE_BLIT(RLEBLIT, alpha, fmt); + +#undef RLEBLIT + } + +done: + /* Unlock the destination if necessary */ + if ( SDL_MUSTLOCK(dst) ) { + SDL_UnlockSurface(dst); + } + return(0); +} + +#undef OPAQUE_BLIT + +/* + * Per-pixel blitting macros for translucent pixels: + * These use the same techniques as the per-surface blitting macros + */ + +/* + * For 32bpp pixels, we have made sure the alpha is stored in the top + * 8 bits, so proceed as usual + */ +#define BLIT_TRANSL_888(src, dst) \ + do { \ + Uint32 s = src; \ + Uint32 d = dst; \ + unsigned alpha = s >> 24; \ + Uint32 s1 = s & 0xff00ff; \ + Uint32 d1 = d & 0xff00ff; \ + d1 = (d1 + ((s1 - d1) * alpha >> 8)) & 0xff00ff; \ + s &= 0xff00; \ + d &= 0xff00; \ + d = (d + ((s - d) * alpha >> 8)) & 0xff00; \ + dst = d1 | d; \ + } while(0) + +/* + * For 16bpp pixels, we have stored the 5 most significant alpha bits in + * bits 5-10. As before, we can process all 3 RGB components at the same time. + */ +#define BLIT_TRANSL_565(src, dst) \ + do { \ + Uint32 s = src; \ + Uint32 d = dst; \ + unsigned alpha = (s & 0x3e0) >> 5; \ + s &= 0x07e0f81f; \ + d = (d | d << 16) & 0x07e0f81f; \ + d += (s - d) * alpha >> 5; \ + d &= 0x07e0f81f; \ + dst = (Uint16)(d | d >> 16); \ + } while(0) + +#define BLIT_TRANSL_555(src, dst) \ + do { \ + Uint32 s = src; \ + Uint32 d = dst; \ + unsigned alpha = (s & 0x3e0) >> 5; \ + s &= 0x03e07c1f; \ + d = (d | d << 16) & 0x03e07c1f; \ + d += (s - d) * alpha >> 5; \ + d &= 0x03e07c1f; \ + dst = (Uint16)(d | d >> 16); \ + } while(0) + +/* used to save the destination format in the encoding. Designed to be + macro-compatible with SDL_PixelFormat but without the unneeded fields */ +typedef struct { + Uint8 BytesPerPixel; + Uint8 Rloss; + Uint8 Gloss; + Uint8 Bloss; + Uint8 Rshift; + Uint8 Gshift; + Uint8 Bshift; + Uint8 Ashift; + Uint32 Rmask; + Uint32 Gmask; + Uint32 Bmask; + Uint32 Amask; +} RLEDestFormat; + +/* blit a pixel-alpha RLE surface clipped at the right and/or left edges */ +static void RLEAlphaClipBlit(int w, Uint8 *srcbuf, SDL_Surface *dst, + Uint8 *dstbuf, SDL_Rect *srcrect) +{ + SDL_PixelFormat *df = dst->format; + /* + * clipped blitter: Ptype is the destination pixel type, + * Ctype the translucent count type, and do_blend the macro + * to blend one pixel. + */ +#define RLEALPHACLIPBLIT(Ptype, Ctype, do_blend) \ + do { \ + int linecount = srcrect->h; \ + int left = srcrect->x; \ + int right = left + srcrect->w; \ + dstbuf -= left * sizeof(Ptype); \ + do { \ + int ofs = 0; \ + /* blit opaque pixels on one line */ \ + do { \ + unsigned run; \ + ofs += ((Ctype *)srcbuf)[0]; \ + run = ((Ctype *)srcbuf)[1]; \ + srcbuf += 2 * sizeof(Ctype); \ + if(run) { \ + /* clip to left and right borders */ \ + int cofs = ofs; \ + int crun = run; \ + if(left - cofs > 0) { \ + crun -= left - cofs; \ + cofs = left; \ + } \ + if(crun > right - cofs) \ + crun = right - cofs; \ + if(crun > 0) \ + PIXEL_COPY(dstbuf + cofs * sizeof(Ptype), \ + srcbuf + (cofs - ofs) * sizeof(Ptype), \ + (unsigned)crun, sizeof(Ptype)); \ + srcbuf += run * sizeof(Ptype); \ + ofs += run; \ + } else if(!ofs) \ + return; \ + } while(ofs < w); \ + /* skip padding if necessary */ \ + if(sizeof(Ptype) == 2) \ + srcbuf += (uintptr_t)srcbuf & 2; \ + /* blit translucent pixels on the same line */ \ + ofs = 0; \ + do { \ + unsigned run; \ + ofs += ((Uint16 *)srcbuf)[0]; \ + run = ((Uint16 *)srcbuf)[1]; \ + srcbuf += 4; \ + if(run) { \ + /* clip to left and right borders */ \ + int cofs = ofs; \ + int crun = run; \ + if(left - cofs > 0) { \ + crun -= left - cofs; \ + cofs = left; \ + } \ + if(crun > right - cofs) \ + crun = right - cofs; \ + if(crun > 0) { \ + Ptype *dst = (Ptype *)dstbuf + cofs; \ + Uint32 *src = (Uint32 *)srcbuf + (cofs - ofs); \ + int i; \ + for(i = 0; i < crun; i++) \ + do_blend(src[i], dst[i]); \ + } \ + srcbuf += run * 4; \ + ofs += run; \ + } \ + } while(ofs < w); \ + dstbuf += dst->pitch; \ + } while(--linecount); \ + } while(0) + + switch(df->BytesPerPixel) { + case 2: + if(df->Gmask == 0x07e0 || df->Rmask == 0x07e0 + || df->Bmask == 0x07e0) + RLEALPHACLIPBLIT(Uint16, Uint8, BLIT_TRANSL_565); + else + RLEALPHACLIPBLIT(Uint16, Uint8, BLIT_TRANSL_555); + break; + case 4: + RLEALPHACLIPBLIT(Uint32, Uint16, BLIT_TRANSL_888); + break; + } +} + +/* blit a pixel-alpha RLE surface */ +int SDL_RLEAlphaBlit(SDL_Surface *src, SDL_Rect *srcrect, + SDL_Surface *dst, SDL_Rect *dstrect) +{ + int x, y; + int w = src->w; + Uint8 *srcbuf, *dstbuf; + SDL_PixelFormat *df = dst->format; + + /* Lock the destination if necessary */ + if ( SDL_MUSTLOCK(dst) ) { + if ( SDL_LockSurface(dst) < 0 ) { + return -1; + } + } + + x = dstrect->x; + y = dstrect->y; + dstbuf = (Uint8 *)dst->pixels + + y * dst->pitch + x * df->BytesPerPixel; + srcbuf = (Uint8 *)src->map->sw_data->aux_data + sizeof(RLEDestFormat); + + { + /* skip lines at the top if necessary */ + int vskip = srcrect->y; + if(vskip) { + int ofs; + if(df->BytesPerPixel == 2) { + /* the 16/32 interleaved format */ + do { + /* skip opaque line */ + ofs = 0; + do { + int run; + ofs += srcbuf[0]; + run = srcbuf[1]; + srcbuf += 2; + if(run) { + srcbuf += 2 * run; + ofs += run; + } else if(!ofs) + goto done; + } while(ofs < w); + + /* skip padding */ + srcbuf += (uintptr_t)srcbuf & 2; + + /* skip translucent line */ + ofs = 0; + do { + int run; + ofs += ((Uint16 *)srcbuf)[0]; + run = ((Uint16 *)srcbuf)[1]; + srcbuf += 4 * (run + 1); + ofs += run; + } while(ofs < w); + } while(--vskip); + } else { + /* the 32/32 interleaved format */ + vskip <<= 1; /* opaque and translucent have same format */ + do { + ofs = 0; + do { + int run; + ofs += ((Uint16 *)srcbuf)[0]; + run = ((Uint16 *)srcbuf)[1]; + srcbuf += 4; + if(run) { + srcbuf += 4 * run; + ofs += run; + } else if(!ofs) + goto done; + } while(ofs < w); + } while(--vskip); + } + } + } + + /* if left or right edge clipping needed, call clip blit */ + if(srcrect->x || srcrect->w != src->w) { + RLEAlphaClipBlit(w, srcbuf, dst, dstbuf, srcrect); + } else { + + /* + * non-clipped blitter. Ptype is the destination pixel type, + * Ctype the translucent count type, and do_blend the + * macro to blend one pixel. + */ +#define RLEALPHABLIT(Ptype, Ctype, do_blend) \ + do { \ + int linecount = srcrect->h; \ + do { \ + int ofs = 0; \ + /* blit opaque pixels on one line */ \ + do { \ + unsigned run; \ + ofs += ((Ctype *)srcbuf)[0]; \ + run = ((Ctype *)srcbuf)[1]; \ + srcbuf += 2 * sizeof(Ctype); \ + if(run) { \ + PIXEL_COPY(dstbuf + ofs * sizeof(Ptype), srcbuf, \ + run, sizeof(Ptype)); \ + srcbuf += run * sizeof(Ptype); \ + ofs += run; \ + } else if(!ofs) \ + goto done; \ + } while(ofs < w); \ + /* skip padding if necessary */ \ + if(sizeof(Ptype) == 2) \ + srcbuf += (uintptr_t)srcbuf & 2; \ + /* blit translucent pixels on the same line */ \ + ofs = 0; \ + do { \ + unsigned run; \ + ofs += ((Uint16 *)srcbuf)[0]; \ + run = ((Uint16 *)srcbuf)[1]; \ + srcbuf += 4; \ + if(run) { \ + Ptype *dst = (Ptype *)dstbuf + ofs; \ + unsigned i; \ + for(i = 0; i < run; i++) { \ + Uint32 src = *(Uint32 *)srcbuf; \ + do_blend(src, *dst); \ + srcbuf += 4; \ + dst++; \ + } \ + ofs += run; \ + } \ + } while(ofs < w); \ + dstbuf += dst->pitch; \ + } while(--linecount); \ + } while(0) + + switch(df->BytesPerPixel) { + case 2: + if(df->Gmask == 0x07e0 || df->Rmask == 0x07e0 + || df->Bmask == 0x07e0) + RLEALPHABLIT(Uint16, Uint8, BLIT_TRANSL_565); + else + RLEALPHABLIT(Uint16, Uint8, BLIT_TRANSL_555); + break; + case 4: + RLEALPHABLIT(Uint32, Uint16, BLIT_TRANSL_888); + break; + } + } + + done: + /* Unlock the destination if necessary */ + if ( SDL_MUSTLOCK(dst) ) { + SDL_UnlockSurface(dst); + } + return 0; +} + +/* + * Auxiliary functions: + * The encoding functions take 32bpp rgb + a, and + * return the number of bytes copied to the destination. + * The decoding functions copy to 32bpp rgb + a, and + * return the number of bytes copied from the source. + * These are only used in the encoder and un-RLE code and are therefore not + * highly optimised. + */ + +/* encode 32bpp rgb + a into 16bpp rgb, losing alpha */ +static int copy_opaque_16(void *dst, Uint32 *src, int n, + SDL_PixelFormat *sfmt, SDL_PixelFormat *dfmt) +{ + int i; + Uint16 *d = dst; + for(i = 0; i < n; i++) { + unsigned r, g, b; + RGB_FROM_PIXEL(*src, sfmt, r, g, b); + PIXEL_FROM_RGB(*d, dfmt, r, g, b); + src++; + d++; + } + return n * 2; +} + +/* decode opaque pixels from 16bpp to 32bpp rgb + a */ +static int uncopy_opaque_16(Uint32 *dst, void *src, int n, + RLEDestFormat *sfmt, SDL_PixelFormat *dfmt) +{ + int i; + Uint16 *s = src; + unsigned alpha = dfmt->Amask ? 255 : 0; + for(i = 0; i < n; i++) { + unsigned r, g, b; + RGB_FROM_PIXEL(*s, sfmt, r, g, b); + PIXEL_FROM_RGBA(*dst, dfmt, r, g, b, alpha); + s++; + dst++; + } + return n * 2; +} + + + +/* encode 32bpp rgb + a into 32bpp G0RAB format for blitting into 565 */ +static int copy_transl_565(void *dst, Uint32 *src, int n, + SDL_PixelFormat *sfmt, SDL_PixelFormat *dfmt) +{ + int i; + Uint32 *d = dst; + for(i = 0; i < n; i++) { + unsigned r, g, b, a; + Uint16 pix; + RGBA_FROM_8888(*src, sfmt, r, g, b, a); + PIXEL_FROM_RGB(pix, dfmt, r, g, b); + *d = ((pix & 0x7e0) << 16) | (pix & 0xf81f) | ((a << 2) & 0x7e0); + src++; + d++; + } + return n * 4; +} + +/* encode 32bpp rgb + a into 32bpp G0RAB format for blitting into 555 */ +static int copy_transl_555(void *dst, Uint32 *src, int n, + SDL_PixelFormat *sfmt, SDL_PixelFormat *dfmt) +{ + int i; + Uint32 *d = dst; + for(i = 0; i < n; i++) { + unsigned r, g, b, a; + Uint16 pix; + RGBA_FROM_8888(*src, sfmt, r, g, b, a); + PIXEL_FROM_RGB(pix, dfmt, r, g, b); + *d = ((pix & 0x3e0) << 16) | (pix & 0xfc1f) | ((a << 2) & 0x3e0); + src++; + d++; + } + return n * 4; +} + +/* decode translucent pixels from 32bpp GORAB to 32bpp rgb + a */ +static int uncopy_transl_16(Uint32 *dst, void *src, int n, + RLEDestFormat *sfmt, SDL_PixelFormat *dfmt) +{ + int i; + Uint32 *s = src; + for(i = 0; i < n; i++) { + unsigned r, g, b, a; + Uint32 pix = *s++; + a = (pix & 0x3e0) >> 2; + pix = (pix & ~0x3e0) | pix >> 16; + RGB_FROM_PIXEL(pix, sfmt, r, g, b); + PIXEL_FROM_RGBA(*dst, dfmt, r, g, b, a); + dst++; + } + return n * 4; +} + +/* encode 32bpp rgba into 32bpp rgba, keeping alpha (dual purpose) */ +static int copy_32(void *dst, Uint32 *src, int n, + SDL_PixelFormat *sfmt, SDL_PixelFormat *dfmt) +{ + int i; + Uint32 *d = dst; + for(i = 0; i < n; i++) { + unsigned r, g, b, a; + Uint32 pixel; + RGBA_FROM_8888(*src, sfmt, r, g, b, a); + PIXEL_FROM_RGB(pixel, dfmt, r, g, b); + *d++ = pixel | a << 24; + src++; + } + return n * 4; +} + +/* decode 32bpp rgba into 32bpp rgba, keeping alpha (dual purpose) */ +static int uncopy_32(Uint32 *dst, void *src, int n, + RLEDestFormat *sfmt, SDL_PixelFormat *dfmt) +{ + int i; + Uint32 *s = src; + for(i = 0; i < n; i++) { + unsigned r, g, b, a; + Uint32 pixel = *s++; + RGB_FROM_PIXEL(pixel, sfmt, r, g, b); + a = pixel >> 24; + PIXEL_FROM_RGBA(*dst, dfmt, r, g, b, a); + dst++; + } + return n * 4; +} + +#define ISOPAQUE(pixel, fmt) ((((pixel) & fmt->Amask) >> fmt->Ashift) == 255) + +#define ISTRANSL(pixel, fmt) \ + ((unsigned)((((pixel) & fmt->Amask) >> fmt->Ashift) - 1U) < 254U) + +/* convert surface to be quickly alpha-blittable onto dest, if possible */ +static int RLEAlphaSurface(SDL_Surface *surface) +{ + SDL_Surface *dest; + SDL_PixelFormat *df; + int maxsize = 0; + int max_opaque_run; + int max_transl_run = 65535; + unsigned masksum; + Uint8 *rlebuf, *dst; + int (*copy_opaque)(void *, Uint32 *, int, + SDL_PixelFormat *, SDL_PixelFormat *); + int (*copy_transl)(void *, Uint32 *, int, + SDL_PixelFormat *, SDL_PixelFormat *); + + dest = surface->map->dst; + if(!dest) + return -1; + df = dest->format; + if(surface->format->BitsPerPixel != 32) + return -1; /* only 32bpp source supported */ + + /* find out whether the destination is one we support, + and determine the max size of the encoded result */ + masksum = df->Rmask | df->Gmask | df->Bmask; + switch(df->BytesPerPixel) { + case 2: + /* 16bpp: only support 565 and 555 formats */ + switch(masksum) { + case 0xffff: + if(df->Gmask == 0x07e0 + || df->Rmask == 0x07e0 || df->Bmask == 0x07e0) { + copy_opaque = copy_opaque_16; + copy_transl = copy_transl_565; + } else + return -1; + break; + case 0x7fff: + if(df->Gmask == 0x03e0 + || df->Rmask == 0x03e0 || df->Bmask == 0x03e0) { + copy_opaque = copy_opaque_16; + copy_transl = copy_transl_555; + } else + return -1; + break; + default: + return -1; + } + max_opaque_run = 255; /* runs stored as bytes */ + + /* worst case is alternating opaque and translucent pixels, + with room for alignment padding between lines */ + maxsize = surface->h * (2 + (4 + 2) * (surface->w + 1)) + 2; + break; + case 4: + if(masksum != 0x00ffffff) + return -1; /* requires unused high byte */ + copy_opaque = copy_32; + copy_transl = copy_32; + max_opaque_run = 255; /* runs stored as short ints */ + + /* worst case is alternating opaque and translucent pixels */ + maxsize = surface->h * 2 * 4 * (surface->w + 1) + 4; + break; + default: + return -1; /* anything else unsupported right now */ + } + + maxsize += sizeof(RLEDestFormat); + rlebuf = (Uint8 *)SDL_malloc(maxsize); + if(!rlebuf) { + SDL_OutOfMemory(); + return -1; + } + { + /* save the destination format so we can undo the encoding later */ + RLEDestFormat *r = (RLEDestFormat *)rlebuf; + r->BytesPerPixel = df->BytesPerPixel; + r->Rloss = df->Rloss; + r->Gloss = df->Gloss; + r->Bloss = df->Bloss; + r->Rshift = df->Rshift; + r->Gshift = df->Gshift; + r->Bshift = df->Bshift; + r->Ashift = df->Ashift; + r->Rmask = df->Rmask; + r->Gmask = df->Gmask; + r->Bmask = df->Bmask; + r->Amask = df->Amask; + } + dst = rlebuf + sizeof(RLEDestFormat); + + /* Do the actual encoding */ + { + int x, y; + int h = surface->h, w = surface->w; + SDL_PixelFormat *sf = surface->format; + Uint32 *src = (Uint32 *)surface->pixels; + Uint8 *lastline = dst; /* end of last non-blank line */ + + /* opaque counts are 8 or 16 bits, depending on target depth */ +#define ADD_OPAQUE_COUNTS(n, m) \ + if(df->BytesPerPixel == 4) { \ + ((Uint16 *)dst)[0] = n; \ + ((Uint16 *)dst)[1] = m; \ + dst += 4; \ + } else { \ + dst[0] = n; \ + dst[1] = m; \ + dst += 2; \ + } + + /* translucent counts are always 16 bit */ +#define ADD_TRANSL_COUNTS(n, m) \ + (((Uint16 *)dst)[0] = n, ((Uint16 *)dst)[1] = m, dst += 4) + + for(y = 0; y < h; y++) { + int runstart, skipstart; + int blankline = 0; + /* First encode all opaque pixels of a scan line */ + x = 0; + do { + int run, skip, len; + skipstart = x; + while(x < w && !ISOPAQUE(src[x], sf)) + x++; + runstart = x; + while(x < w && ISOPAQUE(src[x], sf)) + x++; + skip = runstart - skipstart; + if(skip == w) + blankline = 1; + run = x - runstart; + while(skip > max_opaque_run) { + ADD_OPAQUE_COUNTS(max_opaque_run, 0); + skip -= max_opaque_run; + } + len = MIN(run, max_opaque_run); + ADD_OPAQUE_COUNTS(skip, len); + dst += copy_opaque(dst, src + runstart, len, sf, df); + runstart += len; + run -= len; + while(run) { + len = MIN(run, max_opaque_run); + ADD_OPAQUE_COUNTS(0, len); + dst += copy_opaque(dst, src + runstart, len, sf, df); + runstart += len; + run -= len; + } + } while(x < w); + + /* Make sure the next output address is 32-bit aligned */ + dst += (uintptr_t)dst & 2; + + /* Next, encode all translucent pixels of the same scan line */ + x = 0; + do { + int run, skip, len; + skipstart = x; + while(x < w && !ISTRANSL(src[x], sf)) + x++; + runstart = x; + while(x < w && ISTRANSL(src[x], sf)) + x++; + skip = runstart - skipstart; + blankline &= (skip == w); + run = x - runstart; + while(skip > max_transl_run) { + ADD_TRANSL_COUNTS(max_transl_run, 0); + skip -= max_transl_run; + } + len = MIN(run, max_transl_run); + ADD_TRANSL_COUNTS(skip, len); + dst += copy_transl(dst, src + runstart, len, sf, df); + runstart += len; + run -= len; + while(run) { + len = MIN(run, max_transl_run); + ADD_TRANSL_COUNTS(0, len); + dst += copy_transl(dst, src + runstart, len, sf, df); + runstart += len; + run -= len; + } + if(!blankline) + lastline = dst; + } while(x < w); + + src += surface->pitch >> 2; + } + dst = lastline; /* back up past trailing blank lines */ + ADD_OPAQUE_COUNTS(0, 0); + } + +#undef ADD_OPAQUE_COUNTS +#undef ADD_TRANSL_COUNTS + + /* Now that we have it encoded, release the original pixels */ + if((surface->flags & SDL_PREALLOC) != SDL_PREALLOC + && (surface->flags & SDL_HWSURFACE) != SDL_HWSURFACE) { + SDL_free( surface->pixels ); + surface->pixels = NULL; + } + + /* realloc the buffer to release unused memory */ + { + Uint8 *p = SDL_realloc(rlebuf, dst - rlebuf); + if(!p) + p = rlebuf; + surface->map->sw_data->aux_data = p; + } + + return 0; +} + +static Uint32 getpix_8(Uint8 *srcbuf) +{ + return *srcbuf; +} + +static Uint32 getpix_16(Uint8 *srcbuf) +{ + return *(Uint16 *)srcbuf; +} + +static Uint32 getpix_24(Uint8 *srcbuf) +{ +#if SDL_BYTEORDER == SDL_LIL_ENDIAN + return srcbuf[0] + (srcbuf[1] << 8) + (srcbuf[2] << 16); +#else + return (srcbuf[0] << 16) + (srcbuf[1] << 8) + srcbuf[2]; +#endif +} + +static Uint32 getpix_32(Uint8 *srcbuf) +{ + return *(Uint32 *)srcbuf; +} + +typedef Uint32 (*getpix_func)(Uint8 *); + +static getpix_func getpixes[4] = { + getpix_8, getpix_16, getpix_24, getpix_32 +}; + +static int RLEColorkeySurface(SDL_Surface *surface) +{ + Uint8 *rlebuf, *dst; + int maxn; + int y; + Uint8 *srcbuf, *lastline; + int maxsize = 0; + int bpp = surface->format->BytesPerPixel; + getpix_func getpix; + Uint32 ckey, rgbmask; + int w, h; + + /* calculate the worst case size for the compressed surface */ + switch(bpp) { + case 1: + /* worst case is alternating opaque and transparent pixels, + starting with an opaque pixel */ + maxsize = surface->h * 3 * (surface->w / 2 + 1) + 2; + break; + case 2: + case 3: + /* worst case is solid runs, at most 255 pixels wide */ + maxsize = surface->h * (2 * (surface->w / 255 + 1) + + surface->w * bpp) + 2; + break; + case 4: + /* worst case is solid runs, at most 65535 pixels wide */ + maxsize = surface->h * (4 * (surface->w / 65535 + 1) + + surface->w * 4) + 4; + break; + } + + rlebuf = (Uint8 *)SDL_malloc(maxsize); + if ( rlebuf == NULL ) { + SDL_OutOfMemory(); + return(-1); + } + + /* Set up the conversion */ + srcbuf = (Uint8 *)surface->pixels; + maxn = bpp == 4 ? 65535 : 255; + dst = rlebuf; + rgbmask = ~surface->format->Amask; + ckey = surface->format->colorkey & rgbmask; + lastline = dst; + getpix = getpixes[bpp - 1]; + w = surface->w; + h = surface->h; + +#define ADD_COUNTS(n, m) \ + if(bpp == 4) { \ + ((Uint16 *)dst)[0] = n; \ + ((Uint16 *)dst)[1] = m; \ + dst += 4; \ + } else { \ + dst[0] = n; \ + dst[1] = m; \ + dst += 2; \ + } + + for(y = 0; y < h; y++) { + int x = 0; + int blankline = 0; + do { + int run, skip, len; + int runstart; + int skipstart = x; + + /* find run of transparent, then opaque pixels */ + while(x < w && (getpix(srcbuf + x * bpp) & rgbmask) == ckey) + x++; + runstart = x; + while(x < w && (getpix(srcbuf + x * bpp) & rgbmask) != ckey) + x++; + skip = runstart - skipstart; + if(skip == w) + blankline = 1; + run = x - runstart; + + /* encode segment */ + while(skip > maxn) { + ADD_COUNTS(maxn, 0); + skip -= maxn; + } + len = MIN(run, maxn); + ADD_COUNTS(skip, len); + SDL_memcpy(dst, srcbuf + runstart * bpp, len * bpp); + dst += len * bpp; + run -= len; + runstart += len; + while(run) { + len = MIN(run, maxn); + ADD_COUNTS(0, len); + SDL_memcpy(dst, srcbuf + runstart * bpp, len * bpp); + dst += len * bpp; + runstart += len; + run -= len; + } + if(!blankline) + lastline = dst; + } while(x < w); + + srcbuf += surface->pitch; + } + dst = lastline; /* back up bast trailing blank lines */ + ADD_COUNTS(0, 0); + +#undef ADD_COUNTS + + /* Now that we have it encoded, release the original pixels */ + if((surface->flags & SDL_PREALLOC) != SDL_PREALLOC + && (surface->flags & SDL_HWSURFACE) != SDL_HWSURFACE) { + SDL_free( surface->pixels ); + surface->pixels = NULL; + } + + /* realloc the buffer to release unused memory */ + { + /* If realloc returns NULL, the original block is left intact */ + Uint8 *p = SDL_realloc(rlebuf, dst - rlebuf); + if(!p) + p = rlebuf; + surface->map->sw_data->aux_data = p; + } + + return(0); +} + +int SDL_RLESurface(SDL_Surface *surface) +{ + int retcode; + + /* Clear any previous RLE conversion */ + if ( (surface->flags & SDL_RLEACCEL) == SDL_RLEACCEL ) { + SDL_UnRLESurface(surface, 1); + } + + /* We don't support RLE encoding of bitmaps */ + if ( surface->format->BitsPerPixel < 8 ) { + return(-1); + } + + /* Lock the surface if it's in hardware */ + if ( SDL_MUSTLOCK(surface) ) { + if ( SDL_LockSurface(surface) < 0 ) { + return(-1); + } + } + + /* Encode */ + if((surface->flags & SDL_SRCCOLORKEY) == SDL_SRCCOLORKEY) { + retcode = RLEColorkeySurface(surface); + } else { + if((surface->flags & SDL_SRCALPHA) == SDL_SRCALPHA + && surface->format->Amask != 0) + retcode = RLEAlphaSurface(surface); + else + retcode = -1; /* no RLE for per-surface alpha sans ckey */ + } + + /* Unlock the surface if it's in hardware */ + if ( SDL_MUSTLOCK(surface) ) { + SDL_UnlockSurface(surface); + } + + if(retcode < 0) + return -1; + + /* The surface is now accelerated */ + surface->flags |= SDL_RLEACCEL; + + return(0); +} + +/* + * Un-RLE a surface with pixel alpha + * This may not give back exactly the image before RLE-encoding; all + * completely transparent pixels will be lost, and colour and alpha depth + * may have been reduced (when encoding for 16bpp targets). + */ +static SDL_bool UnRLEAlpha(SDL_Surface *surface) +{ + Uint8 *srcbuf; + Uint32 *dst; + SDL_PixelFormat *sf = surface->format; + RLEDestFormat *df = surface->map->sw_data->aux_data; + int (*uncopy_opaque)(Uint32 *, void *, int, + RLEDestFormat *, SDL_PixelFormat *); + int (*uncopy_transl)(Uint32 *, void *, int, + RLEDestFormat *, SDL_PixelFormat *); + int w = surface->w; + int bpp = df->BytesPerPixel; + + if(bpp == 2) { + uncopy_opaque = uncopy_opaque_16; + uncopy_transl = uncopy_transl_16; + } else { + uncopy_opaque = uncopy_transl = uncopy_32; + } + + surface->pixels = SDL_malloc(surface->h * surface->pitch); + if ( !surface->pixels ) { + return(SDL_FALSE); + } + /* fill background with transparent pixels */ + SDL_memset(surface->pixels, 0, surface->h * surface->pitch); + + dst = surface->pixels; + srcbuf = (Uint8 *)(df + 1); + for(;;) { + /* copy opaque pixels */ + int ofs = 0; + do { + unsigned run; + if(bpp == 2) { + ofs += srcbuf[0]; + run = srcbuf[1]; + srcbuf += 2; + } else { + ofs += ((Uint16 *)srcbuf)[0]; + run = ((Uint16 *)srcbuf)[1]; + srcbuf += 4; + } + if(run) { + srcbuf += uncopy_opaque(dst + ofs, srcbuf, run, df, sf); + ofs += run; + } else if(!ofs) + return(SDL_TRUE); + } while(ofs < w); + + /* skip padding if needed */ + if(bpp == 2) + srcbuf += (uintptr_t)srcbuf & 2; + + /* copy translucent pixels */ + ofs = 0; + do { + unsigned run; + ofs += ((Uint16 *)srcbuf)[0]; + run = ((Uint16 *)srcbuf)[1]; + srcbuf += 4; + if(run) { + srcbuf += uncopy_transl(dst + ofs, srcbuf, run, df, sf); + ofs += run; + } + } while(ofs < w); + dst += surface->pitch >> 2; + } + /* Make the compiler happy */ + return(SDL_TRUE); +} + +void SDL_UnRLESurface(SDL_Surface *surface, int recode) +{ + if ( (surface->flags & SDL_RLEACCEL) == SDL_RLEACCEL ) { + surface->flags &= ~SDL_RLEACCEL; + + if(recode && (surface->flags & SDL_PREALLOC) != SDL_PREALLOC + && (surface->flags & SDL_HWSURFACE) != SDL_HWSURFACE) { + if((surface->flags & SDL_SRCCOLORKEY) == SDL_SRCCOLORKEY) { + SDL_Rect full; + unsigned alpha_flag; + + /* re-create the original surface */ + surface->pixels = SDL_malloc(surface->h * surface->pitch); + if ( !surface->pixels ) { + /* Oh crap... */ + surface->flags |= SDL_RLEACCEL; + return; + } + + /* fill it with the background colour */ + SDL_FillRect(surface, NULL, surface->format->colorkey); + + /* now render the encoded surface */ + full.x = full.y = 0; + full.w = surface->w; + full.h = surface->h; + alpha_flag = surface->flags & SDL_SRCALPHA; + surface->flags &= ~SDL_SRCALPHA; /* opaque blit */ + SDL_RLEBlit(surface, &full, surface, &full); + surface->flags |= alpha_flag; + } else { + if ( !UnRLEAlpha(surface) ) { + /* Oh crap... */ + surface->flags |= SDL_RLEACCEL; + return; + } + } + } + + if ( surface->map && surface->map->sw_data->aux_data ) { + SDL_free(surface->map->sw_data->aux_data); + surface->map->sw_data->aux_data = NULL; + } + } +} + + diff --git a/3rdparty/SDL/src/video/SDL_RLEaccel_c.h b/3rdparty/SDL/src/video/SDL_RLEaccel_c.h new file mode 100644 index 0000000..daf0c53 --- /dev/null +++ b/3rdparty/SDL/src/video/SDL_RLEaccel_c.h @@ -0,0 +1,31 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* Useful functions and variables from SDL_RLEaccel.c */ + +extern int SDL_RLESurface(SDL_Surface *surface); +extern int SDL_RLEBlit(SDL_Surface *src, SDL_Rect *srcrect, + SDL_Surface *dst, SDL_Rect *dstrect); +extern int SDL_RLEAlphaBlit(SDL_Surface *src, SDL_Rect *srcrect, + SDL_Surface *dst, SDL_Rect *dstrect); +extern void SDL_UnRLESurface(SDL_Surface *surface, int recode); diff --git a/3rdparty/SDL/src/video/SDL_blit.c b/3rdparty/SDL/src/video/SDL_blit.c new file mode 100644 index 0000000..e3f194a --- /dev/null +++ b/3rdparty/SDL/src/video/SDL_blit.c @@ -0,0 +1,360 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#include "SDL_video.h" +#include "SDL_sysvideo.h" +#include "SDL_blit.h" +#include "SDL_RLEaccel_c.h" +#include "SDL_pixels_c.h" + +#if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__)) && SDL_ASSEMBLY_ROUTINES +#define MMX_ASMBLIT +#if (__GNUC__ > 2) /* SSE instructions aren't in GCC 2. */ +#define SSE_ASMBLIT +#endif +#endif + +#if defined(MMX_ASMBLIT) +#include "SDL_cpuinfo.h" +#include "mmx.h" +#endif + +/* The general purpose software blit routine */ +static int SDL_SoftBlit(SDL_Surface *src, SDL_Rect *srcrect, + SDL_Surface *dst, SDL_Rect *dstrect) +{ + int okay; + int src_locked; + int dst_locked; + + /* Everything is okay at the beginning... */ + okay = 1; + + /* Lock the destination if it's in hardware */ + dst_locked = 0; + if ( SDL_MUSTLOCK(dst) ) { + if ( SDL_LockSurface(dst) < 0 ) { + okay = 0; + } else { + dst_locked = 1; + } + } + /* Lock the source if it's in hardware */ + src_locked = 0; + if ( SDL_MUSTLOCK(src) ) { + if ( SDL_LockSurface(src) < 0 ) { + okay = 0; + } else { + src_locked = 1; + } + } + + /* Set up source and destination buffer pointers, and BLIT! */ + if ( okay && srcrect->w && srcrect->h ) { + SDL_BlitInfo info; + SDL_loblit RunBlit; + + /* Set up the blit information */ + info.s_pixels = (Uint8 *)src->pixels + + (Uint16)srcrect->y*src->pitch + + (Uint16)srcrect->x*src->format->BytesPerPixel; + info.s_width = srcrect->w; + info.s_height = srcrect->h; + info.s_skip=src->pitch-info.s_width*src->format->BytesPerPixel; + info.d_pixels = (Uint8 *)dst->pixels + + (Uint16)dstrect->y*dst->pitch + + (Uint16)dstrect->x*dst->format->BytesPerPixel; + info.d_width = dstrect->w; + info.d_height = dstrect->h; + info.d_skip=dst->pitch-info.d_width*dst->format->BytesPerPixel; + info.aux_data = src->map->sw_data->aux_data; + info.src = src->format; + info.table = src->map->table; + info.dst = dst->format; + RunBlit = src->map->sw_data->blit; + + /* Run the actual software blit */ + RunBlit(&info); + } + + /* We need to unlock the surfaces if they're locked */ + if ( dst_locked ) { + SDL_UnlockSurface(dst); + } + if ( src_locked ) { + SDL_UnlockSurface(src); + } + /* Blit is done! */ + return(okay ? 0 : -1); +} + +#ifdef MMX_ASMBLIT +static __inline__ void SDL_memcpyMMX(Uint8 *to, const Uint8 *from, int len) +{ + int i; + + for(i=0; i<len/8; i++) { + __asm__ __volatile__ ( + " movq (%0), %%mm0\n" + " movq %%mm0, (%1)\n" + : : "r" (from), "r" (to) : "memory"); + from+=8; + to+=8; + } + if (len&7) + SDL_memcpy(to, from, len&7); +} + +#ifdef SSE_ASMBLIT +static __inline__ void SDL_memcpySSE(Uint8 *to, const Uint8 *from, int len) +{ + int i; + + __asm__ __volatile__ ( + " prefetchnta (%0)\n" + " prefetchnta 64(%0)\n" + " prefetchnta 128(%0)\n" + " prefetchnta 192(%0)\n" + : : "r" (from) ); + + for(i=0; i<len/8; i++) { + __asm__ __volatile__ ( + " prefetchnta 256(%0)\n" + " movq (%0), %%mm0\n" + " movntq %%mm0, (%1)\n" + : : "r" (from), "r" (to) : "memory"); + from+=8; + to+=8; + } + if (len&7) + SDL_memcpy(to, from, len&7); +} +#endif +#endif + +static void SDL_BlitCopy(SDL_BlitInfo *info) +{ + Uint8 *src, *dst; + int w, h; + int srcskip, dstskip; + + w = info->d_width*info->dst->BytesPerPixel; + h = info->d_height; + src = info->s_pixels; + dst = info->d_pixels; + srcskip = w+info->s_skip; + dstskip = w+info->d_skip; + +#ifdef SSE_ASMBLIT + if(SDL_HasSSE()) + { + while ( h-- ) { + SDL_memcpySSE(dst, src, w); + src += srcskip; + dst += dstskip; + } + __asm__ __volatile__ ( + " emms\n" + ::); + } + else +#endif +#ifdef MMX_ASMBLIT + if(SDL_HasMMX()) + { + while ( h-- ) { + SDL_memcpyMMX(dst, src, w); + src += srcskip; + dst += dstskip; + } + __asm__ __volatile__ ( + " emms\n" + ::); + } + else +#endif + while ( h-- ) { + SDL_memcpy(dst, src, w); + src += srcskip; + dst += dstskip; + } +} + +static void SDL_BlitCopyOverlap(SDL_BlitInfo *info) +{ + Uint8 *src, *dst; + int w, h; + int srcskip, dstskip; + + w = info->d_width*info->dst->BytesPerPixel; + h = info->d_height; + src = info->s_pixels; + dst = info->d_pixels; + srcskip = w+info->s_skip; + dstskip = w+info->d_skip; + if ( dst < src ) { + while ( h-- ) { + SDL_memmove(dst, src, w); + src += srcskip; + dst += dstskip; + } + } else { + src += ((h-1) * srcskip); + dst += ((h-1) * dstskip); + while ( h-- ) { + SDL_revcpy(dst, src, w); + src -= srcskip; + dst -= dstskip; + } + } +} + +/* Figure out which of many blit routines to set up on a surface */ +int SDL_CalculateBlit(SDL_Surface *surface) +{ + int blit_index; + + /* Clean everything out to start */ + if ( (surface->flags & SDL_RLEACCEL) == SDL_RLEACCEL ) { + SDL_UnRLESurface(surface, 1); + } + surface->map->sw_blit = NULL; + + /* Figure out if an accelerated hardware blit is possible */ + surface->flags &= ~SDL_HWACCEL; + if ( surface->map->identity ) { + int hw_blit_ok; + + if ( (surface->flags & SDL_HWSURFACE) == SDL_HWSURFACE ) { + /* We only support accelerated blitting to hardware */ + if ( surface->map->dst->flags & SDL_HWSURFACE ) { + hw_blit_ok = current_video->info.blit_hw; + } else { + hw_blit_ok = 0; + } + if (hw_blit_ok && (surface->flags & SDL_SRCCOLORKEY)) { + hw_blit_ok = current_video->info.blit_hw_CC; + } + if ( hw_blit_ok && (surface->flags & SDL_SRCALPHA) ) { + hw_blit_ok = current_video->info.blit_hw_A; + } + } else { + /* We only support accelerated blitting to hardware */ + if ( surface->map->dst->flags & SDL_HWSURFACE ) { + hw_blit_ok = current_video->info.blit_sw; + } else { + hw_blit_ok = 0; + } + if (hw_blit_ok && (surface->flags & SDL_SRCCOLORKEY)) { + hw_blit_ok = current_video->info.blit_sw_CC; + } + if ( hw_blit_ok && (surface->flags & SDL_SRCALPHA) ) { + hw_blit_ok = current_video->info.blit_sw_A; + } + } + if ( hw_blit_ok ) { + SDL_VideoDevice *video = current_video; + SDL_VideoDevice *this = current_video; + video->CheckHWBlit(this, surface, surface->map->dst); + } + } + + /* if an alpha pixel format is specified, we can accelerate alpha blits */ + if (((surface->flags & SDL_HWSURFACE) == SDL_HWSURFACE )&&(current_video->displayformatalphapixel)) + { + if ( (surface->flags & SDL_SRCALPHA) ) + if ( current_video->info.blit_hw_A ) { + SDL_VideoDevice *video = current_video; + SDL_VideoDevice *this = current_video; + video->CheckHWBlit(this, surface, surface->map->dst); + } + } + + /* Get the blit function index, based on surface mode */ + /* { 0 = nothing, 1 = colorkey, 2 = alpha, 3 = colorkey+alpha } */ + blit_index = 0; + blit_index |= (!!(surface->flags & SDL_SRCCOLORKEY)) << 0; + if ( surface->flags & SDL_SRCALPHA + && (surface->format->alpha != SDL_ALPHA_OPAQUE + || surface->format->Amask) ) { + blit_index |= 2; + } + + /* Check for special "identity" case -- copy blit */ + if ( surface->map->identity && blit_index == 0 ) { + surface->map->sw_data->blit = SDL_BlitCopy; + + /* Handle overlapping blits on the same surface */ + if ( surface == surface->map->dst ) { + surface->map->sw_data->blit = SDL_BlitCopyOverlap; + } + } else { + if ( surface->format->BitsPerPixel < 8 ) { + surface->map->sw_data->blit = + SDL_CalculateBlit0(surface, blit_index); + } else { + switch ( surface->format->BytesPerPixel ) { + case 1: + surface->map->sw_data->blit = + SDL_CalculateBlit1(surface, blit_index); + break; + case 2: + case 3: + case 4: + surface->map->sw_data->blit = + SDL_CalculateBlitN(surface, blit_index); + break; + default: + surface->map->sw_data->blit = NULL; + break; + } + } + } + /* Make sure we have a blit function */ + if ( surface->map->sw_data->blit == NULL ) { + SDL_InvalidateMap(surface->map); + SDL_SetError("Blit combination not supported"); + return(-1); + } + + /* Choose software blitting function */ + if(surface->flags & SDL_RLEACCELOK + && (surface->flags & SDL_HWACCEL) != SDL_HWACCEL) { + + if(surface->map->identity + && (blit_index == 1 + || (blit_index == 3 && !surface->format->Amask))) { + if ( SDL_RLESurface(surface) == 0 ) + surface->map->sw_blit = SDL_RLEBlit; + } else if(blit_index == 2 && surface->format->Amask) { + if ( SDL_RLESurface(surface) == 0 ) + surface->map->sw_blit = SDL_RLEAlphaBlit; + } + } + + if ( surface->map->sw_blit == NULL ) { + surface->map->sw_blit = SDL_SoftBlit; + } + return(0); +} + diff --git a/3rdparty/SDL/src/video/SDL_blit.h b/3rdparty/SDL/src/video/SDL_blit.h new file mode 100644 index 0000000..d64c1e5 --- /dev/null +++ b/3rdparty/SDL/src/video/SDL_blit.h @@ -0,0 +1,528 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#ifndef _SDL_blit_h +#define _SDL_blit_h + +#include "SDL_endian.h" + +/* The structure passed to the low level blit functions */ +typedef struct { + Uint8 *s_pixels; + int s_width; + int s_height; + int s_skip; + Uint8 *d_pixels; + int d_width; + int d_height; + int d_skip; + void *aux_data; + SDL_PixelFormat *src; + Uint8 *table; + SDL_PixelFormat *dst; +} SDL_BlitInfo; + +/* The type definition for the low level blit functions */ +typedef void (*SDL_loblit)(SDL_BlitInfo *info); + +/* This is the private info structure for software accelerated blits */ +struct private_swaccel { + SDL_loblit blit; + void *aux_data; +}; + +/* Blit mapping definition */ +typedef struct SDL_BlitMap { + SDL_Surface *dst; + int identity; + Uint8 *table; + SDL_blit hw_blit; + SDL_blit sw_blit; + struct private_hwaccel *hw_data; + struct private_swaccel *sw_data; + + /* the version count matches the destination; mismatch indicates + an invalid mapping */ + unsigned int format_version; +} SDL_BlitMap; + + +/* Functions found in SDL_blit.c */ +extern int SDL_CalculateBlit(SDL_Surface *surface); + +/* Functions found in SDL_blit_{0,1,N,A}.c */ +extern SDL_loblit SDL_CalculateBlit0(SDL_Surface *surface, int complex); +extern SDL_loblit SDL_CalculateBlit1(SDL_Surface *surface, int complex); +extern SDL_loblit SDL_CalculateBlitN(SDL_Surface *surface, int complex); +extern SDL_loblit SDL_CalculateAlphaBlit(SDL_Surface *surface, int complex); + +/* + * Useful macros for blitting routines + */ + +#define FORMAT_EQUAL(A, B) \ + ((A)->BitsPerPixel == (B)->BitsPerPixel \ + && ((A)->Rmask == (B)->Rmask) && ((A)->Amask == (B)->Amask)) + +/* Load pixel of the specified format from a buffer and get its R-G-B values */ +/* FIXME: rescale values to 0..255 here? */ +#define RGB_FROM_PIXEL(Pixel, fmt, r, g, b) \ +{ \ + r = (((Pixel&fmt->Rmask)>>fmt->Rshift)<<fmt->Rloss); \ + g = (((Pixel&fmt->Gmask)>>fmt->Gshift)<<fmt->Gloss); \ + b = (((Pixel&fmt->Bmask)>>fmt->Bshift)<<fmt->Bloss); \ +} +#define RGB_FROM_RGB565(Pixel, r, g, b) \ +{ \ + r = (((Pixel&0xF800)>>11)<<3); \ + g = (((Pixel&0x07E0)>>5)<<2); \ + b = ((Pixel&0x001F)<<3); \ +} +#define RGB_FROM_RGB555(Pixel, r, g, b) \ +{ \ + r = (((Pixel&0x7C00)>>10)<<3); \ + g = (((Pixel&0x03E0)>>5)<<3); \ + b = ((Pixel&0x001F)<<3); \ +} +#define RGB_FROM_RGB888(Pixel, r, g, b) \ +{ \ + r = ((Pixel&0xFF0000)>>16); \ + g = ((Pixel&0xFF00)>>8); \ + b = (Pixel&0xFF); \ +} +#define RETRIEVE_RGB_PIXEL(buf, bpp, Pixel) \ +do { \ + switch (bpp) { \ + case 2: \ + Pixel = *((Uint16 *)(buf)); \ + break; \ + \ + case 3: { \ + Uint8 *B = (Uint8 *)(buf); \ + if(SDL_BYTEORDER == SDL_LIL_ENDIAN) { \ + Pixel = B[0] + (B[1] << 8) + (B[2] << 16); \ + } else { \ + Pixel = (B[0] << 16) + (B[1] << 8) + B[2]; \ + } \ + } \ + break; \ + \ + case 4: \ + Pixel = *((Uint32 *)(buf)); \ + break; \ + \ + default: \ + Pixel = 0; /* appease gcc */ \ + break; \ + } \ +} while(0) + +#define DISEMBLE_RGB(buf, bpp, fmt, Pixel, r, g, b) \ +do { \ + switch (bpp) { \ + case 2: \ + Pixel = *((Uint16 *)(buf)); \ + break; \ + \ + case 3: { \ + Uint8 *B = (Uint8 *)buf; \ + if(SDL_BYTEORDER == SDL_LIL_ENDIAN) { \ + Pixel = B[0] + (B[1] << 8) + (B[2] << 16); \ + } else { \ + Pixel = (B[0] << 16) + (B[1] << 8) + B[2]; \ + } \ + } \ + break; \ + \ + case 4: \ + Pixel = *((Uint32 *)(buf)); \ + break; \ + \ + default: \ + Pixel = 0; /* prevent gcc from complaining */ \ + break; \ + } \ + RGB_FROM_PIXEL(Pixel, fmt, r, g, b); \ +} while(0) + +/* Assemble R-G-B values into a specified pixel format and store them */ +#ifdef __NDS__ /* FIXME */ +#define PIXEL_FROM_RGB(Pixel, fmt, r, g, b) \ +{ \ + Pixel = ((r>>fmt->Rloss)<<fmt->Rshift)| \ + ((g>>fmt->Gloss)<<fmt->Gshift)| \ + ((b>>fmt->Bloss)<<fmt->Bshift) | (1<<15); \ +} +#else +#define PIXEL_FROM_RGB(Pixel, fmt, r, g, b) \ +{ \ + Pixel = ((r>>fmt->Rloss)<<fmt->Rshift)| \ + ((g>>fmt->Gloss)<<fmt->Gshift)| \ + ((b>>fmt->Bloss)<<fmt->Bshift); \ +} +#endif /* __NDS__ FIXME */ +#define RGB565_FROM_RGB(Pixel, r, g, b) \ +{ \ + Pixel = ((r>>3)<<11)|((g>>2)<<5)|(b>>3); \ +} +#define RGB555_FROM_RGB(Pixel, r, g, b) \ +{ \ + Pixel = ((r>>3)<<10)|((g>>3)<<5)|(b>>3); \ +} +#define RGB888_FROM_RGB(Pixel, r, g, b) \ +{ \ + Pixel = (r<<16)|(g<<8)|b; \ +} +#define ASSEMBLE_RGB(buf, bpp, fmt, r, g, b) \ +{ \ + switch (bpp) { \ + case 2: { \ + Uint16 Pixel; \ + \ + PIXEL_FROM_RGB(Pixel, fmt, r, g, b); \ + *((Uint16 *)(buf)) = Pixel; \ + } \ + break; \ + \ + case 3: { \ + if(SDL_BYTEORDER == SDL_LIL_ENDIAN) { \ + *((buf)+fmt->Rshift/8) = r; \ + *((buf)+fmt->Gshift/8) = g; \ + *((buf)+fmt->Bshift/8) = b; \ + } else { \ + *((buf)+2-fmt->Rshift/8) = r; \ + *((buf)+2-fmt->Gshift/8) = g; \ + *((buf)+2-fmt->Bshift/8) = b; \ + } \ + } \ + break; \ + \ + case 4: { \ + Uint32 Pixel; \ + \ + PIXEL_FROM_RGB(Pixel, fmt, r, g, b); \ + *((Uint32 *)(buf)) = Pixel; \ + } \ + break; \ + } \ +} +#define ASSEMBLE_RGB_AMASK(buf, bpp, fmt, r, g, b, Amask) \ +{ \ + switch (bpp) { \ + case 2: { \ + Uint16 *bufp; \ + Uint16 Pixel; \ + \ + bufp = (Uint16 *)buf; \ + PIXEL_FROM_RGB(Pixel, fmt, r, g, b); \ + *bufp = Pixel | (*bufp & Amask); \ + } \ + break; \ + \ + case 3: { \ + if(SDL_BYTEORDER == SDL_LIL_ENDIAN) { \ + *((buf)+fmt->Rshift/8) = r; \ + *((buf)+fmt->Gshift/8) = g; \ + *((buf)+fmt->Bshift/8) = b; \ + } else { \ + *((buf)+2-fmt->Rshift/8) = r; \ + *((buf)+2-fmt->Gshift/8) = g; \ + *((buf)+2-fmt->Bshift/8) = b; \ + } \ + } \ + break; \ + \ + case 4: { \ + Uint32 *bufp; \ + Uint32 Pixel; \ + \ + bufp = (Uint32 *)buf; \ + PIXEL_FROM_RGB(Pixel, fmt, r, g, b); \ + *bufp = Pixel | (*bufp & Amask); \ + } \ + break; \ + } \ +} + +/* FIXME: Should we rescale alpha into 0..255 here? */ +#define RGBA_FROM_PIXEL(Pixel, fmt, r, g, b, a) \ +{ \ + r = ((Pixel&fmt->Rmask)>>fmt->Rshift)<<fmt->Rloss; \ + g = ((Pixel&fmt->Gmask)>>fmt->Gshift)<<fmt->Gloss; \ + b = ((Pixel&fmt->Bmask)>>fmt->Bshift)<<fmt->Bloss; \ + a = ((Pixel&fmt->Amask)>>fmt->Ashift)<<fmt->Aloss; \ +} +#define RGBA_FROM_8888(Pixel, fmt, r, g, b, a) \ +{ \ + r = (Pixel&fmt->Rmask)>>fmt->Rshift; \ + g = (Pixel&fmt->Gmask)>>fmt->Gshift; \ + b = (Pixel&fmt->Bmask)>>fmt->Bshift; \ + a = (Pixel&fmt->Amask)>>fmt->Ashift; \ +} +#define RGBA_FROM_RGBA8888(Pixel, r, g, b, a) \ +{ \ + r = (Pixel>>24); \ + g = ((Pixel>>16)&0xFF); \ + b = ((Pixel>>8)&0xFF); \ + a = (Pixel&0xFF); \ +} +#define RGBA_FROM_ARGB8888(Pixel, r, g, b, a) \ +{ \ + r = ((Pixel>>16)&0xFF); \ + g = ((Pixel>>8)&0xFF); \ + b = (Pixel&0xFF); \ + a = (Pixel>>24); \ +} +#define RGBA_FROM_ABGR8888(Pixel, r, g, b, a) \ +{ \ + r = (Pixel&0xFF); \ + g = ((Pixel>>8)&0xFF); \ + b = ((Pixel>>16)&0xFF); \ + a = (Pixel>>24); \ +} +#define DISEMBLE_RGBA(buf, bpp, fmt, Pixel, r, g, b, a) \ +do { \ + switch (bpp) { \ + case 2: \ + Pixel = *((Uint16 *)(buf)); \ + break; \ + \ + case 3: {/* FIXME: broken code (no alpha) */ \ + Uint8 *b = (Uint8 *)buf; \ + if(SDL_BYTEORDER == SDL_LIL_ENDIAN) { \ + Pixel = b[0] + (b[1] << 8) + (b[2] << 16); \ + } else { \ + Pixel = (b[0] << 16) + (b[1] << 8) + b[2]; \ + } \ + } \ + break; \ + \ + case 4: \ + Pixel = *((Uint32 *)(buf)); \ + break; \ + \ + default: \ + Pixel = 0; /* stop gcc complaints */ \ + break; \ + } \ + RGBA_FROM_PIXEL(Pixel, fmt, r, g, b, a); \ + Pixel &= ~fmt->Amask; \ +} while(0) + +/* FIXME: this isn't correct, especially for Alpha (maximum != 255) */ +#ifdef __NDS__ /* FIXME */ +#define PIXEL_FROM_RGBA(Pixel, fmt, r, g, b, a) \ +{ \ + Pixel = ((r>>fmt->Rloss)<<fmt->Rshift)| \ + ((g>>fmt->Gloss)<<fmt->Gshift)| \ + ((b>>fmt->Bloss)<<fmt->Bshift)| \ + ((a>>fmt->Aloss)<<fmt->Ashift) | (1<<15); \ +} +#else +#define PIXEL_FROM_RGBA(Pixel, fmt, r, g, b, a) \ +{ \ + Pixel = ((r>>fmt->Rloss)<<fmt->Rshift)| \ + ((g>>fmt->Gloss)<<fmt->Gshift)| \ + ((b>>fmt->Bloss)<<fmt->Bshift)| \ + ((a>>fmt->Aloss)<<fmt->Ashift); \ +} +#endif /* __NDS__ FIXME */ +#define ASSEMBLE_RGBA(buf, bpp, fmt, r, g, b, a) \ +{ \ + switch (bpp) { \ + case 2: { \ + Uint16 Pixel; \ + \ + PIXEL_FROM_RGBA(Pixel, fmt, r, g, b, a); \ + *((Uint16 *)(buf)) = Pixel; \ + } \ + break; \ + \ + case 3: { /* FIXME: broken code (no alpha) */ \ + if(SDL_BYTEORDER == SDL_LIL_ENDIAN) { \ + *((buf)+fmt->Rshift/8) = r; \ + *((buf)+fmt->Gshift/8) = g; \ + *((buf)+fmt->Bshift/8) = b; \ + } else { \ + *((buf)+2-fmt->Rshift/8) = r; \ + *((buf)+2-fmt->Gshift/8) = g; \ + *((buf)+2-fmt->Bshift/8) = b; \ + } \ + } \ + break; \ + \ + case 4: { \ + Uint32 Pixel; \ + \ + PIXEL_FROM_RGBA(Pixel, fmt, r, g, b, a); \ + *((Uint32 *)(buf)) = Pixel; \ + } \ + break; \ + } \ +} + +/* Blend the RGB values of two Pixels based on a source alpha value */ +#define ALPHA_BLEND(sR, sG, sB, A, dR, dG, dB) \ +do { \ + dR = (((sR-dR)*(A)+255)>>8)+dR; \ + dG = (((sG-dG)*(A)+255)>>8)+dG; \ + dB = (((sB-dB)*(A)+255)>>8)+dB; \ +} while(0) + + +/* This is a very useful loop for optimizing blitters */ +#if defined(_MSC_VER) && (_MSC_VER == 1300) +/* There's a bug in the Visual C++ 7 optimizer when compiling this code */ +#else +#define USE_DUFFS_LOOP +#endif +#ifdef USE_DUFFS_LOOP + +/* 8-times unrolled loop */ +#define DUFFS_LOOP8(pixel_copy_increment, width) \ +{ int n = (width+7)/8; \ + switch (width & 7) { \ + case 0: do { pixel_copy_increment; \ + case 7: pixel_copy_increment; \ + case 6: pixel_copy_increment; \ + case 5: pixel_copy_increment; \ + case 4: pixel_copy_increment; \ + case 3: pixel_copy_increment; \ + case 2: pixel_copy_increment; \ + case 1: pixel_copy_increment; \ + } while ( --n > 0 ); \ + } \ +} + +/* 4-times unrolled loop */ +#define DUFFS_LOOP4(pixel_copy_increment, width) \ +{ int n = (width+3)/4; \ + switch (width & 3) { \ + case 0: do { pixel_copy_increment; \ + case 3: pixel_copy_increment; \ + case 2: pixel_copy_increment; \ + case 1: pixel_copy_increment; \ + } while ( --n > 0 ); \ + } \ +} + +/* 2 - times unrolled loop */ +#define DUFFS_LOOP_DOUBLE2(pixel_copy_increment, \ + double_pixel_copy_increment, width) \ +{ int n, w = width; \ + if( w & 1 ) { \ + pixel_copy_increment; \ + w--; \ + } \ + if ( w > 0 ) { \ + n = ( w + 2) / 4; \ + switch( w & 2 ) { \ + case 0: do { double_pixel_copy_increment; \ + case 2: double_pixel_copy_increment; \ + } while ( --n > 0 ); \ + } \ + } \ +} + +/* 2 - times unrolled loop 4 pixels */ +#define DUFFS_LOOP_QUATRO2(pixel_copy_increment, \ + double_pixel_copy_increment, \ + quatro_pixel_copy_increment, width) \ +{ int n, w = width; \ + if(w & 1) { \ + pixel_copy_increment; \ + w--; \ + } \ + if(w & 2) { \ + double_pixel_copy_increment; \ + w -= 2; \ + } \ + if ( w > 0 ) { \ + n = ( w + 7 ) / 8; \ + switch( w & 4 ) { \ + case 0: do { quatro_pixel_copy_increment; \ + case 4: quatro_pixel_copy_increment; \ + } while ( --n > 0 ); \ + } \ + } \ +} + +/* Use the 8-times version of the loop by default */ +#define DUFFS_LOOP(pixel_copy_increment, width) \ + DUFFS_LOOP8(pixel_copy_increment, width) + +#else + +/* Don't use Duff's device to unroll loops */ +#define DUFFS_LOOP_DOUBLE2(pixel_copy_increment, \ + double_pixel_copy_increment, width) \ +{ int n = width; \ + if( n & 1 ) { \ + pixel_copy_increment; \ + n--; \ + } \ + n=n>>1; \ + for(; n > 0; --n) { \ + double_pixel_copy_increment; \ + } \ +} + +/* Don't use Duff's device to unroll loops */ +#define DUFFS_LOOP_QUATRO2(pixel_copy_increment, \ + double_pixel_copy_increment, \ + quatro_pixel_copy_increment, width) \ +{ int n = width; \ + if(n & 1) { \ + pixel_copy_increment; \ + n--; \ + } \ + if(n & 2) { \ + double_pixel_copy_increment; \ + n -= 2; \ + } \ + n=n>>2; \ + for(; n > 0; --n) { \ + quatro_pixel_copy_increment; \ + } \ +} + +/* Don't use Duff's device to unroll loops */ +#define DUFFS_LOOP(pixel_copy_increment, width) \ +{ int n; \ + for ( n=width; n > 0; --n ) { \ + pixel_copy_increment; \ + } \ +} +#define DUFFS_LOOP8(pixel_copy_increment, width) \ + DUFFS_LOOP(pixel_copy_increment, width) +#define DUFFS_LOOP4(pixel_copy_increment, width) \ + DUFFS_LOOP(pixel_copy_increment, width) + +#endif /* USE_DUFFS_LOOP */ + +/* Prevent Visual C++ 6.0 from printing out stupid warnings */ +#if defined(_MSC_VER) && (_MSC_VER >= 600) +#pragma warning(disable: 4550) +#endif + +#endif /* _SDL_blit_h */ diff --git a/3rdparty/SDL/src/video/SDL_blit_0.c b/3rdparty/SDL/src/video/SDL_blit_0.c new file mode 100644 index 0000000..c1bc0eb --- /dev/null +++ b/3rdparty/SDL/src/video/SDL_blit_0.c @@ -0,0 +1,471 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#include "SDL_video.h" +#include "SDL_blit.h" + +/* Functions to blit from bitmaps to other surfaces */ + +static void BlitBto1(SDL_BlitInfo *info) +{ + int c; + int width, height; + Uint8 *src, *map, *dst; + int srcskip, dstskip; + + /* Set up some basic variables */ + width = info->d_width; + height = info->d_height; + src = info->s_pixels; + srcskip = info->s_skip; + dst = info->d_pixels; + dstskip = info->d_skip; + map = info->table; + srcskip += width-(width+7)/8; + + if ( map ) { + while ( height-- ) { + Uint8 byte = 0, bit; + for ( c=0; c<width; ++c ) { + if ( (c&7) == 0 ) { + byte = *src++; + } + bit = (byte&0x80)>>7; + if ( 1 ) { + *dst = map[bit]; + } + dst++; + byte <<= 1; + } + src += srcskip; + dst += dstskip; + } + } else { + while ( height-- ) { + Uint8 byte = 0, bit; + for ( c=0; c<width; ++c ) { + if ( (c&7) == 0 ) { + byte = *src++; + } + bit = (byte&0x80)>>7; + if ( 1 ) { + *dst = bit; + } + dst++; + byte <<= 1; + } + src += srcskip; + dst += dstskip; + } + } +} +static void BlitBto2(SDL_BlitInfo *info) +{ + int c; + int width, height; + Uint8 *src; + Uint16 *map, *dst; + int srcskip, dstskip; + + /* Set up some basic variables */ + width = info->d_width; + height = info->d_height; + src = info->s_pixels; + srcskip = info->s_skip; + dst = (Uint16 *)info->d_pixels; + dstskip = info->d_skip/2; + map = (Uint16 *)info->table; + srcskip += width-(width+7)/8; + + while ( height-- ) { + Uint8 byte = 0, bit; + for ( c=0; c<width; ++c ) { + if ( (c&7) == 0 ) { + byte = *src++; + } + bit = (byte&0x80)>>7; + if ( 1 ) { + *dst = map[bit]; + } + byte <<= 1; + dst++; + } + src += srcskip; + dst += dstskip; + } +} +static void BlitBto3(SDL_BlitInfo *info) +{ + int c, o; + int width, height; + Uint8 *src, *map, *dst; + int srcskip, dstskip; + + /* Set up some basic variables */ + width = info->d_width; + height = info->d_height; + src = info->s_pixels; + srcskip = info->s_skip; + dst = info->d_pixels; + dstskip = info->d_skip; + map = info->table; + srcskip += width-(width+7)/8; + + while ( height-- ) { + Uint8 byte = 0, bit; + for ( c=0; c<width; ++c ) { + if ( (c&7) == 0 ) { + byte = *src++; + } + bit = (byte&0x80)>>7; + if ( 1 ) { + o = bit * 4; + dst[0] = map[o++]; + dst[1] = map[o++]; + dst[2] = map[o++]; + } + byte <<= 1; + dst += 3; + } + src += srcskip; + dst += dstskip; + } +} +static void BlitBto4(SDL_BlitInfo *info) +{ + int width, height; + Uint8 *src; + Uint32 *map, *dst; + int srcskip, dstskip; + int c; + + /* Set up some basic variables */ + width = info->d_width; + height = info->d_height; + src = info->s_pixels; + srcskip = info->s_skip; + dst = (Uint32 *)info->d_pixels; + dstskip = info->d_skip/4; + map = (Uint32 *)info->table; + srcskip += width-(width+7)/8; + + while ( height-- ) { + Uint8 byte = 0, bit; + for ( c=0; c<width; ++c ) { + if ( (c&7) == 0 ) { + byte = *src++; + } + bit = (byte&0x80)>>7; + if ( 1 ) { + *dst = map[bit]; + } + byte <<= 1; + dst++; + } + src += srcskip; + dst += dstskip; + } +} + +static void BlitBto1Key(SDL_BlitInfo *info) +{ + int width = info->d_width; + int height = info->d_height; + Uint8 *src = info->s_pixels; + Uint8 *dst = info->d_pixels; + int srcskip = info->s_skip; + int dstskip = info->d_skip; + Uint32 ckey = info->src->colorkey; + Uint8 *palmap = info->table; + int c; + + /* Set up some basic variables */ + srcskip += width-(width+7)/8; + + if ( palmap ) { + while ( height-- ) { + Uint8 byte = 0, bit; + for ( c=0; c<width; ++c ) { + if ( (c&7) == 0 ) { + byte = *src++; + } + bit = (byte&0x80)>>7; + if ( bit != ckey ) { + *dst = palmap[bit]; + } + dst++; + byte <<= 1; + } + src += srcskip; + dst += dstskip; + } + } else { + while ( height-- ) { + Uint8 byte = 0, bit; + for ( c=0; c<width; ++c ) { + if ( (c&7) == 0 ) { + byte = *src++; + } + bit = (byte&0x80)>>7; + if ( bit != ckey ) { + *dst = bit; + } + dst++; + byte <<= 1; + } + src += srcskip; + dst += dstskip; + } + } +} + +static void BlitBto2Key(SDL_BlitInfo *info) +{ + int width = info->d_width; + int height = info->d_height; + Uint8 *src = info->s_pixels; + Uint16 *dstp = (Uint16 *)info->d_pixels; + int srcskip = info->s_skip; + int dstskip = info->d_skip; + Uint32 ckey = info->src->colorkey; + Uint8 *palmap = info->table; + int c; + + /* Set up some basic variables */ + srcskip += width-(width+7)/8; + dstskip /= 2; + + while ( height-- ) { + Uint8 byte = 0, bit; + for ( c=0; c<width; ++c ) { + if ( (c&7) == 0 ) { + byte = *src++; + } + bit = (byte&0x80)>>7; + if ( bit != ckey ) { + *dstp=((Uint16 *)palmap)[bit]; + } + byte <<= 1; + dstp++; + } + src += srcskip; + dstp += dstskip; + } +} + +static void BlitBto3Key(SDL_BlitInfo *info) +{ + int width = info->d_width; + int height = info->d_height; + Uint8 *src = info->s_pixels; + Uint8 *dst = info->d_pixels; + int srcskip = info->s_skip; + int dstskip = info->d_skip; + Uint32 ckey = info->src->colorkey; + Uint8 *palmap = info->table; + int c; + + /* Set up some basic variables */ + srcskip += width-(width+7)/8; + + while ( height-- ) { + Uint8 byte = 0, bit; + for ( c=0; c<width; ++c ) { + if ( (c&7) == 0 ) { + byte = *src++; + } + bit = (byte&0x80)>>7; + if ( bit != ckey ) { + SDL_memcpy(dst, &palmap[bit*4], 3); + } + byte <<= 1; + dst += 3; + } + src += srcskip; + dst += dstskip; + } +} + +static void BlitBto4Key(SDL_BlitInfo *info) +{ + int width = info->d_width; + int height = info->d_height; + Uint8 *src = info->s_pixels; + Uint32 *dstp = (Uint32 *)info->d_pixels; + int srcskip = info->s_skip; + int dstskip = info->d_skip; + Uint32 ckey = info->src->colorkey; + Uint8 *palmap = info->table; + int c; + + /* Set up some basic variables */ + srcskip += width-(width+7)/8; + dstskip /= 4; + + while ( height-- ) { + Uint8 byte = 0, bit; + for ( c=0; c<width; ++c ) { + if ( (c&7) == 0 ) { + byte = *src++; + } + bit = (byte&0x80)>>7; + if ( bit != ckey ) { + *dstp=((Uint32 *)palmap)[bit]; + } + byte <<= 1; + dstp++; + } + src += srcskip; + dstp += dstskip; + } +} + +static void BlitBtoNAlpha(SDL_BlitInfo *info) +{ + int width = info->d_width; + int height = info->d_height; + Uint8 *src = info->s_pixels; + Uint8 *dst = info->d_pixels; + int srcskip = info->s_skip; + int dstskip = info->d_skip; + const SDL_Color *srcpal = info->src->palette->colors; + SDL_PixelFormat *dstfmt = info->dst; + int dstbpp; + int c; + const int A = info->src->alpha; + + /* Set up some basic variables */ + dstbpp = dstfmt->BytesPerPixel; + srcskip += width-(width+7)/8; + + while ( height-- ) { + Uint8 byte = 0, bit; + for ( c=0; c<width; ++c ) { + if ( (c&7) == 0 ) { + byte = *src++; + } + bit = (byte&0x80)>>7; + if ( 1 ) { + Uint32 pixel; + unsigned sR, sG, sB; + unsigned dR, dG, dB; + sR = srcpal[bit].r; + sG = srcpal[bit].g; + sB = srcpal[bit].b; + DISEMBLE_RGB(dst, dstbpp, dstfmt, + pixel, dR, dG, dB); + ALPHA_BLEND(sR, sG, sB, A, dR, dG, dB); + ASSEMBLE_RGB(dst, dstbpp, dstfmt, dR, dG, dB); + } + byte <<= 1; + dst += dstbpp; + } + src += srcskip; + dst += dstskip; + } +} + +static void BlitBtoNAlphaKey(SDL_BlitInfo *info) +{ + int width = info->d_width; + int height = info->d_height; + Uint8 *src = info->s_pixels; + Uint8 *dst = info->d_pixels; + int srcskip = info->s_skip; + int dstskip = info->d_skip; + SDL_PixelFormat *srcfmt = info->src; + SDL_PixelFormat *dstfmt = info->dst; + const SDL_Color *srcpal = srcfmt->palette->colors; + int dstbpp; + int c; + const int A = srcfmt->alpha; + Uint32 ckey = srcfmt->colorkey; + + /* Set up some basic variables */ + dstbpp = dstfmt->BytesPerPixel; + srcskip += width-(width+7)/8; + + while ( height-- ) { + Uint8 byte = 0, bit; + for ( c=0; c<width; ++c ) { + if ( (c&7) == 0 ) { + byte = *src++; + } + bit = (byte&0x80)>>7; + if ( bit != ckey ) { + int sR, sG, sB; + int dR, dG, dB; + Uint32 pixel; + sR = srcpal[bit].r; + sG = srcpal[bit].g; + sB = srcpal[bit].b; + DISEMBLE_RGB(dst, dstbpp, dstfmt, + pixel, dR, dG, dB); + ALPHA_BLEND(sR, sG, sB, A, dR, dG, dB); + ASSEMBLE_RGB(dst, dstbpp, dstfmt, dR, dG, dB); + } + byte <<= 1; + dst += dstbpp; + } + src += srcskip; + dst += dstskip; + } +} + +static SDL_loblit bitmap_blit[] = { + NULL, BlitBto1, BlitBto2, BlitBto3, BlitBto4 +}; + +static SDL_loblit colorkey_blit[] = { + NULL, BlitBto1Key, BlitBto2Key, BlitBto3Key, BlitBto4Key +}; + +SDL_loblit SDL_CalculateBlit0(SDL_Surface *surface, int blit_index) +{ + int which; + + if ( surface->format->BitsPerPixel != 1 ) { + /* We don't support sub 8-bit packed pixel modes */ + return NULL; + } + if ( surface->map->dst->format->BitsPerPixel < 8 ) { + which = 0; + } else { + which = surface->map->dst->format->BytesPerPixel; + } + switch(blit_index) { + case 0: /* copy */ + return bitmap_blit[which]; + + case 1: /* colorkey */ + return colorkey_blit[which]; + + case 2: /* alpha */ + return which >= 2 ? BlitBtoNAlpha : NULL; + + case 4: /* alpha + colorkey */ + return which >= 2 ? BlitBtoNAlphaKey : NULL; + } + return NULL; +} + diff --git a/3rdparty/SDL/src/video/SDL_blit_1.c b/3rdparty/SDL/src/video/SDL_blit_1.c new file mode 100644 index 0000000..7f95f5b --- /dev/null +++ b/3rdparty/SDL/src/video/SDL_blit_1.c @@ -0,0 +1,523 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#include "SDL_video.h" +#include "SDL_blit.h" +#include "SDL_sysvideo.h" +#include "SDL_endian.h" + +/* Functions to blit from 8-bit surfaces to other surfaces */ + +static void Blit1to1(SDL_BlitInfo *info) +{ +#ifndef USE_DUFFS_LOOP + int c; +#endif + int width, height; + Uint8 *src, *map, *dst; + int srcskip, dstskip; + + /* Set up some basic variables */ + width = info->d_width; + height = info->d_height; + src = info->s_pixels; + srcskip = info->s_skip; + dst = info->d_pixels; + dstskip = info->d_skip; + map = info->table; + + while ( height-- ) { +#ifdef USE_DUFFS_LOOP + DUFFS_LOOP( + { + *dst = map[*src]; + } + dst++; + src++; + , width); +#else + for ( c=width; c; --c ) { + *dst = map[*src]; + dst++; + src++; + } +#endif + src += srcskip; + dst += dstskip; + } +} +/* This is now endian dependent */ +#if ( SDL_BYTEORDER == SDL_LIL_ENDIAN ) +#define HI 1 +#define LO 0 +#else /* ( SDL_BYTEORDER == SDL_BIG_ENDIAN ) */ +#define HI 0 +#define LO 1 +#endif +static void Blit1to2(SDL_BlitInfo *info) +{ +#ifndef USE_DUFFS_LOOP + int c; +#endif + int width, height; + Uint8 *src, *dst; + Uint16 *map; + int srcskip, dstskip; + + /* Set up some basic variables */ + width = info->d_width; + height = info->d_height; + src = info->s_pixels; + srcskip = info->s_skip; + dst = info->d_pixels; + dstskip = info->d_skip; + map = (Uint16 *)info->table; + +#ifdef USE_DUFFS_LOOP + while ( height-- ) { + DUFFS_LOOP( + { + *(Uint16 *)dst = map[*src++]; + dst += 2; + }, + width); + src += srcskip; + dst += dstskip; + } +#else + /* Memory align at 4-byte boundary, if necessary */ + if ( (long)dst & 0x03 ) { + /* Don't do anything if width is 0 */ + if ( width == 0 ) { + return; + } + --width; + + while ( height-- ) { + /* Perform copy alignment */ + *(Uint16 *)dst = map[*src++]; + dst += 2; + + /* Copy in 4 pixel chunks */ + for ( c=width/4; c; --c ) { + *(Uint32 *)dst = + (map[src[HI]]<<16)|(map[src[LO]]); + src += 2; + dst += 4; + *(Uint32 *)dst = + (map[src[HI]]<<16)|(map[src[LO]]); + src += 2; + dst += 4; + } + /* Get any leftovers */ + switch (width & 3) { + case 3: + *(Uint16 *)dst = map[*src++]; + dst += 2; + case 2: + *(Uint32 *)dst = + (map[src[HI]]<<16)|(map[src[LO]]); + src += 2; + dst += 4; + break; + case 1: + *(Uint16 *)dst = map[*src++]; + dst += 2; + break; + } + src += srcskip; + dst += dstskip; + } + } else { + while ( height-- ) { + /* Copy in 4 pixel chunks */ + for ( c=width/4; c; --c ) { + *(Uint32 *)dst = + (map[src[HI]]<<16)|(map[src[LO]]); + src += 2; + dst += 4; + *(Uint32 *)dst = + (map[src[HI]]<<16)|(map[src[LO]]); + src += 2; + dst += 4; + } + /* Get any leftovers */ + switch (width & 3) { + case 3: + *(Uint16 *)dst = map[*src++]; + dst += 2; + case 2: + *(Uint32 *)dst = + (map[src[HI]]<<16)|(map[src[LO]]); + src += 2; + dst += 4; + break; + case 1: + *(Uint16 *)dst = map[*src++]; + dst += 2; + break; + } + src += srcskip; + dst += dstskip; + } + } +#endif /* USE_DUFFS_LOOP */ +} +static void Blit1to3(SDL_BlitInfo *info) +{ +#ifndef USE_DUFFS_LOOP + int c; +#endif + int o; + int width, height; + Uint8 *src, *map, *dst; + int srcskip, dstskip; + + /* Set up some basic variables */ + width = info->d_width; + height = info->d_height; + src = info->s_pixels; + srcskip = info->s_skip; + dst = info->d_pixels; + dstskip = info->d_skip; + map = info->table; + + while ( height-- ) { +#ifdef USE_DUFFS_LOOP + DUFFS_LOOP( + { + o = *src * 4; + dst[0] = map[o++]; + dst[1] = map[o++]; + dst[2] = map[o++]; + } + src++; + dst += 3; + , width); +#else + for ( c=width; c; --c ) { + o = *src * 4; + dst[0] = map[o++]; + dst[1] = map[o++]; + dst[2] = map[o++]; + src++; + dst += 3; + } +#endif /* USE_DUFFS_LOOP */ + src += srcskip; + dst += dstskip; + } +} +static void Blit1to4(SDL_BlitInfo *info) +{ +#ifndef USE_DUFFS_LOOP + int c; +#endif + int width, height; + Uint8 *src; + Uint32 *map, *dst; + int srcskip, dstskip; + + /* Set up some basic variables */ + width = info->d_width; + height = info->d_height; + src = info->s_pixels; + srcskip = info->s_skip; + dst = (Uint32 *)info->d_pixels; + dstskip = info->d_skip/4; + map = (Uint32 *)info->table; + + while ( height-- ) { +#ifdef USE_DUFFS_LOOP + DUFFS_LOOP( + *dst++ = map[*src++]; + , width); +#else + for ( c=width/4; c; --c ) { + *dst++ = map[*src++]; + *dst++ = map[*src++]; + *dst++ = map[*src++]; + *dst++ = map[*src++]; + } + switch ( width & 3 ) { + case 3: + *dst++ = map[*src++]; + case 2: + *dst++ = map[*src++]; + case 1: + *dst++ = map[*src++]; + } +#endif /* USE_DUFFS_LOOP */ + src += srcskip; + dst += dstskip; + } +} + +static void Blit1to1Key(SDL_BlitInfo *info) +{ + int width = info->d_width; + int height = info->d_height; + Uint8 *src = info->s_pixels; + int srcskip = info->s_skip; + Uint8 *dst = info->d_pixels; + int dstskip = info->d_skip; + Uint8 *palmap = info->table; + Uint32 ckey = info->src->colorkey; + + if ( palmap ) { + while ( height-- ) { + DUFFS_LOOP( + { + if ( *src != ckey ) { + *dst = palmap[*src]; + } + dst++; + src++; + }, + width); + src += srcskip; + dst += dstskip; + } + } else { + while ( height-- ) { + DUFFS_LOOP( + { + if ( *src != ckey ) { + *dst = *src; + } + dst++; + src++; + }, + width); + src += srcskip; + dst += dstskip; + } + } +} + +static void Blit1to2Key(SDL_BlitInfo *info) +{ + int width = info->d_width; + int height = info->d_height; + Uint8 *src = info->s_pixels; + int srcskip = info->s_skip; + Uint16 *dstp = (Uint16 *)info->d_pixels; + int dstskip = info->d_skip; + Uint16 *palmap = (Uint16 *)info->table; + Uint32 ckey = info->src->colorkey; + + /* Set up some basic variables */ + dstskip /= 2; + + while ( height-- ) { + DUFFS_LOOP( + { + if ( *src != ckey ) { + *dstp=palmap[*src]; + } + src++; + dstp++; + }, + width); + src += srcskip; + dstp += dstskip; + } +} + +static void Blit1to3Key(SDL_BlitInfo *info) +{ + int width = info->d_width; + int height = info->d_height; + Uint8 *src = info->s_pixels; + int srcskip = info->s_skip; + Uint8 *dst = info->d_pixels; + int dstskip = info->d_skip; + Uint8 *palmap = info->table; + Uint32 ckey = info->src->colorkey; + int o; + + while ( height-- ) { + DUFFS_LOOP( + { + if ( *src != ckey ) { + o = *src * 4; + dst[0] = palmap[o++]; + dst[1] = palmap[o++]; + dst[2] = palmap[o++]; + } + src++; + dst += 3; + }, + width); + src += srcskip; + dst += dstskip; + } +} + +static void Blit1to4Key(SDL_BlitInfo *info) +{ + int width = info->d_width; + int height = info->d_height; + Uint8 *src = info->s_pixels; + int srcskip = info->s_skip; + Uint32 *dstp = (Uint32 *)info->d_pixels; + int dstskip = info->d_skip; + Uint32 *palmap = (Uint32 *)info->table; + Uint32 ckey = info->src->colorkey; + + /* Set up some basic variables */ + dstskip /= 4; + + while ( height-- ) { + DUFFS_LOOP( + { + if ( *src != ckey ) { + *dstp = palmap[*src]; + } + src++; + dstp++; + }, + width); + src += srcskip; + dstp += dstskip; + } +} + +static void Blit1toNAlpha(SDL_BlitInfo *info) +{ + int width = info->d_width; + int height = info->d_height; + Uint8 *src = info->s_pixels; + int srcskip = info->s_skip; + Uint8 *dst = info->d_pixels; + int dstskip = info->d_skip; + SDL_PixelFormat *dstfmt = info->dst; + const SDL_Color *srcpal = info->src->palette->colors; + int dstbpp; + const int A = info->src->alpha; + + /* Set up some basic variables */ + dstbpp = dstfmt->BytesPerPixel; + + while ( height-- ) { + int sR, sG, sB; + int dR, dG, dB; + DUFFS_LOOP4( + { + Uint32 pixel; + sR = srcpal[*src].r; + sG = srcpal[*src].g; + sB = srcpal[*src].b; + DISEMBLE_RGB(dst, dstbpp, dstfmt, + pixel, dR, dG, dB); + ALPHA_BLEND(sR, sG, sB, A, dR, dG, dB); + ASSEMBLE_RGB(dst, dstbpp, dstfmt, dR, dG, dB); + src++; + dst += dstbpp; + }, + width); + src += srcskip; + dst += dstskip; + } +} + +static void Blit1toNAlphaKey(SDL_BlitInfo *info) +{ + int width = info->d_width; + int height = info->d_height; + Uint8 *src = info->s_pixels; + int srcskip = info->s_skip; + Uint8 *dst = info->d_pixels; + int dstskip = info->d_skip; + SDL_PixelFormat *srcfmt = info->src; + SDL_PixelFormat *dstfmt = info->dst; + const SDL_Color *srcpal = info->src->palette->colors; + Uint32 ckey = srcfmt->colorkey; + int dstbpp; + const int A = srcfmt->alpha; + + /* Set up some basic variables */ + dstbpp = dstfmt->BytesPerPixel; + + while ( height-- ) { + int sR, sG, sB; + int dR, dG, dB; + DUFFS_LOOP( + { + if ( *src != ckey ) { + Uint32 pixel; + sR = srcpal[*src].r; + sG = srcpal[*src].g; + sB = srcpal[*src].b; + DISEMBLE_RGB(dst, dstbpp, dstfmt, + pixel, dR, dG, dB); + ALPHA_BLEND(sR, sG, sB, A, dR, dG, dB); + ASSEMBLE_RGB(dst, dstbpp, dstfmt, dR, dG, dB); + } + src++; + dst += dstbpp; + }, + width); + src += srcskip; + dst += dstskip; + } +} + +static SDL_loblit one_blit[] = { + NULL, Blit1to1, Blit1to2, Blit1to3, Blit1to4 +}; + +static SDL_loblit one_blitkey[] = { + NULL, Blit1to1Key, Blit1to2Key, Blit1to3Key, Blit1to4Key +}; + +SDL_loblit SDL_CalculateBlit1(SDL_Surface *surface, int blit_index) +{ + int which; + SDL_PixelFormat *dstfmt; + + dstfmt = surface->map->dst->format; + if ( dstfmt->BitsPerPixel < 8 ) { + which = 0; + } else { + which = dstfmt->BytesPerPixel; + } + switch(blit_index) { + case 0: /* copy */ + return one_blit[which]; + + case 1: /* colorkey */ + return one_blitkey[which]; + + case 2: /* alpha */ + /* Supporting 8bpp->8bpp alpha is doable but requires lots of + tables which consume space and takes time to precompute, + so is better left to the user */ + return which >= 2 ? Blit1toNAlpha : NULL; + + case 3: /* alpha + colorkey */ + return which >= 2 ? Blit1toNAlphaKey : NULL; + + } + return NULL; +} diff --git a/3rdparty/SDL/src/video/SDL_blit_A.c b/3rdparty/SDL/src/video/SDL_blit_A.c new file mode 100644 index 0000000..219cdcc --- /dev/null +++ b/3rdparty/SDL/src/video/SDL_blit_A.c @@ -0,0 +1,2873 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#include "SDL_video.h" +#include "SDL_blit.h" + +/* + In Visual C, VC6 has mmintrin.h in the "Processor Pack" add-on. + Checking if _mm_free is #defined in malloc.h is is the only way to + determine if the Processor Pack is installed, as far as I can tell. +*/ + +#if SDL_ASSEMBLY_ROUTINES +# if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__)) + /* forced MMX to 0...it breaks on most compilers now. --ryan. */ +# define MMX_ASMBLIT 0 +# define GCC_ASMBLIT 0 +# elif defined(_MSC_VER) && defined(_M_IX86) +# if (_MSC_VER <= 1200) +# include <malloc.h> +# if defined(_mm_free) +# define HAVE_MMINTRIN_H 1 +# endif +# else /* Visual Studio > VC6 always has mmintrin.h */ +# define HAVE_MMINTRIN_H 1 +# endif +# if HAVE_MMINTRIN_H +# define MMX_ASMBLIT 1 +# define MSVC_ASMBLIT 1 +# endif +# endif +#endif /* SDL_ASSEMBLY_ROUTINES */ + +/* Function to check the CPU flags */ +#include "SDL_cpuinfo.h" +#if GCC_ASMBLIT +#include "mmx.h" +#elif MSVC_ASMBLIT +#include <mmintrin.h> +#include <mm3dnow.h> +#endif + +/* Functions to perform alpha blended blitting */ + +/* N->1 blending with per-surface alpha */ +static void BlitNto1SurfaceAlpha(SDL_BlitInfo *info) +{ + int width = info->d_width; + int height = info->d_height; + Uint8 *src = info->s_pixels; + int srcskip = info->s_skip; + Uint8 *dst = info->d_pixels; + int dstskip = info->d_skip; + Uint8 *palmap = info->table; + SDL_PixelFormat *srcfmt = info->src; + SDL_PixelFormat *dstfmt = info->dst; + int srcbpp = srcfmt->BytesPerPixel; + + const unsigned A = srcfmt->alpha; + + while ( height-- ) { + DUFFS_LOOP4( + { + Uint32 Pixel; + unsigned sR; + unsigned sG; + unsigned sB; + unsigned dR; + unsigned dG; + unsigned dB; + DISEMBLE_RGB(src, srcbpp, srcfmt, Pixel, sR, sG, sB); + dR = dstfmt->palette->colors[*dst].r; + dG = dstfmt->palette->colors[*dst].g; + dB = dstfmt->palette->colors[*dst].b; + ALPHA_BLEND(sR, sG, sB, A, dR, dG, dB); + dR &= 0xff; + dG &= 0xff; + dB &= 0xff; + /* Pack RGB into 8bit pixel */ + if ( palmap == NULL ) { + *dst =((dR>>5)<<(3+2))| + ((dG>>5)<<(2))| + ((dB>>6)<<(0)); + } else { + *dst = palmap[((dR>>5)<<(3+2))| + ((dG>>5)<<(2)) | + ((dB>>6)<<(0))]; + } + dst++; + src += srcbpp; + }, + width); + src += srcskip; + dst += dstskip; + } +} + +/* N->1 blending with pixel alpha */ +static void BlitNto1PixelAlpha(SDL_BlitInfo *info) +{ + int width = info->d_width; + int height = info->d_height; + Uint8 *src = info->s_pixels; + int srcskip = info->s_skip; + Uint8 *dst = info->d_pixels; + int dstskip = info->d_skip; + Uint8 *palmap = info->table; + SDL_PixelFormat *srcfmt = info->src; + SDL_PixelFormat *dstfmt = info->dst; + int srcbpp = srcfmt->BytesPerPixel; + + /* FIXME: fix alpha bit field expansion here too? */ + while ( height-- ) { + DUFFS_LOOP4( + { + Uint32 Pixel; + unsigned sR; + unsigned sG; + unsigned sB; + unsigned sA; + unsigned dR; + unsigned dG; + unsigned dB; + DISEMBLE_RGBA(src,srcbpp,srcfmt,Pixel,sR,sG,sB,sA); + dR = dstfmt->palette->colors[*dst].r; + dG = dstfmt->palette->colors[*dst].g; + dB = dstfmt->palette->colors[*dst].b; + ALPHA_BLEND(sR, sG, sB, sA, dR, dG, dB); + dR &= 0xff; + dG &= 0xff; + dB &= 0xff; + /* Pack RGB into 8bit pixel */ + if ( palmap == NULL ) { + *dst =((dR>>5)<<(3+2))| + ((dG>>5)<<(2))| + ((dB>>6)<<(0)); + } else { + *dst = palmap[((dR>>5)<<(3+2))| + ((dG>>5)<<(2)) | + ((dB>>6)<<(0)) ]; + } + dst++; + src += srcbpp; + }, + width); + src += srcskip; + dst += dstskip; + } +} + +/* colorkeyed N->1 blending with per-surface alpha */ +static void BlitNto1SurfaceAlphaKey(SDL_BlitInfo *info) +{ + int width = info->d_width; + int height = info->d_height; + Uint8 *src = info->s_pixels; + int srcskip = info->s_skip; + Uint8 *dst = info->d_pixels; + int dstskip = info->d_skip; + Uint8 *palmap = info->table; + SDL_PixelFormat *srcfmt = info->src; + SDL_PixelFormat *dstfmt = info->dst; + int srcbpp = srcfmt->BytesPerPixel; + Uint32 ckey = srcfmt->colorkey; + + const int A = srcfmt->alpha; + + while ( height-- ) { + DUFFS_LOOP( + { + Uint32 Pixel; + unsigned sR; + unsigned sG; + unsigned sB; + unsigned dR; + unsigned dG; + unsigned dB; + DISEMBLE_RGB(src, srcbpp, srcfmt, Pixel, sR, sG, sB); + if ( Pixel != ckey ) { + dR = dstfmt->palette->colors[*dst].r; + dG = dstfmt->palette->colors[*dst].g; + dB = dstfmt->palette->colors[*dst].b; + ALPHA_BLEND(sR, sG, sB, A, dR, dG, dB); + dR &= 0xff; + dG &= 0xff; + dB &= 0xff; + /* Pack RGB into 8bit pixel */ + if ( palmap == NULL ) { + *dst =((dR>>5)<<(3+2))| + ((dG>>5)<<(2)) | + ((dB>>6)<<(0)); + } else { + *dst = palmap[((dR>>5)<<(3+2))| + ((dG>>5)<<(2)) | + ((dB>>6)<<(0)) ]; + } + } + dst++; + src += srcbpp; + }, + width); + src += srcskip; + dst += dstskip; + } +} + +#if GCC_ASMBLIT +/* fast RGB888->(A)RGB888 blending with surface alpha=128 special case */ +static void BlitRGBtoRGBSurfaceAlpha128MMX(SDL_BlitInfo *info) +{ + int width = info->d_width; + int height = info->d_height; + Uint32 *srcp = (Uint32 *)info->s_pixels; + int srcskip = info->s_skip >> 2; + Uint32 *dstp = (Uint32 *)info->d_pixels; + int dstskip = info->d_skip >> 2; + Uint32 dalpha = info->dst->Amask; + Uint64 load; + + load = 0x00fefefe00fefefeULL;/* alpha128 mask */ + movq_m2r(load, mm4); /* alpha128 mask -> mm4 */ + load = 0x0001010100010101ULL;/* !alpha128 mask */ + movq_m2r(load, mm3); /* !alpha128 mask -> mm3 */ + movd_m2r(dalpha, mm7); /* dst alpha mask */ + punpckldq_r2r(mm7, mm7); /* dst alpha mask | dst alpha mask -> mm7 */ + while(height--) { + DUFFS_LOOP_DOUBLE2( + { + Uint32 s = *srcp++; + Uint32 d = *dstp; + *dstp++ = ((((s & 0x00fefefe) + (d & 0x00fefefe)) >> 1) + + (s & d & 0x00010101)) | dalpha; + },{ + movq_m2r((*dstp), mm2);/* 2 x dst -> mm2(ARGBARGB) */ + movq_r2r(mm2, mm6); /* 2 x dst -> mm6(ARGBARGB) */ + + movq_m2r((*srcp), mm1);/* 2 x src -> mm1(ARGBARGB) */ + movq_r2r(mm1, mm5); /* 2 x src -> mm5(ARGBARGB) */ + + pand_r2r(mm4, mm6); /* dst & mask -> mm6 */ + pand_r2r(mm4, mm5); /* src & mask -> mm5 */ + paddd_r2r(mm6, mm5); /* mm6 + mm5 -> mm5 */ + pand_r2r(mm1, mm2); /* src & dst -> mm2 */ + psrld_i2r(1, mm5); /* mm5 >> 1 -> mm5 */ + pand_r2r(mm3, mm2); /* mm2 & !mask -> mm2 */ + paddd_r2r(mm5, mm2); /* mm5 + mm2 -> mm2 */ + + por_r2r(mm7, mm2); /* mm7(full alpha) | mm2 -> mm2 */ + movq_r2m(mm2, (*dstp));/* mm2 -> 2 x dst pixels */ + dstp += 2; + srcp += 2; + }, width); + srcp += srcskip; + dstp += dstskip; + } + emms(); +} + +/* fast RGB888->(A)RGB888 blending with surface alpha */ +static void BlitRGBtoRGBSurfaceAlphaMMX(SDL_BlitInfo *info) +{ + SDL_PixelFormat* df = info->dst; + unsigned alpha = info->src->alpha; + + if (alpha == 128 && (df->Rmask | df->Gmask | df->Bmask) == 0x00FFFFFF) { + /* only call a128 version when R,G,B occupy lower bits */ + BlitRGBtoRGBSurfaceAlpha128MMX(info); + } else { + int width = info->d_width; + int height = info->d_height; + Uint32 *srcp = (Uint32 *)info->s_pixels; + int srcskip = info->s_skip >> 2; + Uint32 *dstp = (Uint32 *)info->d_pixels; + int dstskip = info->d_skip >> 2; + + pxor_r2r(mm5, mm5); /* 0 -> mm5 */ + /* form the alpha mult */ + movd_m2r(alpha, mm4); /* 0000000A -> mm4 */ + punpcklwd_r2r(mm4, mm4); /* 00000A0A -> mm4 */ + punpckldq_r2r(mm4, mm4); /* 0A0A0A0A -> mm4 */ + alpha = (0xff << df->Rshift) | (0xff << df->Gshift) | (0xff << df->Bshift); + movd_m2r(alpha, mm0); /* 00000FFF -> mm0 */ + punpcklbw_r2r(mm0, mm0); /* 00FFFFFF -> mm0 */ + pand_r2r(mm0, mm4); /* 0A0A0A0A -> mm4, minus 1 chan */ + /* at this point mm4 can be 000A0A0A or 0A0A0A00 or another combo */ + movd_m2r(df->Amask, mm7); /* dst alpha mask */ + punpckldq_r2r(mm7, mm7); /* dst alpha mask | dst alpha mask -> mm7 */ + + while(height--) { + DUFFS_LOOP_DOUBLE2({ + /* One Pixel Blend */ + movd_m2r((*srcp), mm1);/* src(ARGB) -> mm1 (0000ARGB)*/ + movd_m2r((*dstp), mm2);/* dst(ARGB) -> mm2 (0000ARGB)*/ + punpcklbw_r2r(mm5, mm1); /* 0A0R0G0B -> mm1(src) */ + punpcklbw_r2r(mm5, mm2); /* 0A0R0G0B -> mm2(dst) */ + + psubw_r2r(mm2, mm1);/* src - dst -> mm1 */ + pmullw_r2r(mm4, mm1); /* mm1 * alpha -> mm1 */ + psrlw_i2r(8, mm1); /* mm1 >> 8 -> mm1 */ + paddb_r2r(mm1, mm2); /* mm1 + mm2(dst) -> mm2 */ + + packuswb_r2r(mm5, mm2); /* ARGBARGB -> mm2 */ + por_r2r(mm7, mm2); /* mm7(full alpha) | mm2 -> mm2 */ + movd_r2m(mm2, *dstp);/* mm2 -> pixel */ + ++srcp; + ++dstp; + },{ + /* Two Pixels Blend */ + movq_m2r((*srcp), mm0);/* 2 x src -> mm0(ARGBARGB)*/ + movq_m2r((*dstp), mm2);/* 2 x dst -> mm2(ARGBARGB) */ + movq_r2r(mm0, mm1); /* 2 x src -> mm1(ARGBARGB) */ + movq_r2r(mm2, mm6); /* 2 x dst -> mm6(ARGBARGB) */ + + punpcklbw_r2r(mm5, mm0); /* low - 0A0R0G0B -> mm0(src1) */ + punpckhbw_r2r(mm5, mm1); /* high - 0A0R0G0B -> mm1(src2) */ + punpcklbw_r2r(mm5, mm2); /* low - 0A0R0G0B -> mm2(dst1) */ + punpckhbw_r2r(mm5, mm6); /* high - 0A0R0G0B -> mm6(dst2) */ + + psubw_r2r(mm2, mm0);/* src1 - dst1 -> mm0 */ + pmullw_r2r(mm4, mm0); /* mm0 * alpha -> mm0 */ + psrlw_i2r(8, mm0); /* mm0 >> 8 -> mm1 */ + paddb_r2r(mm0, mm2); /* mm0 + mm2(dst1) -> mm2 */ + + psubw_r2r(mm6, mm1);/* src2 - dst2 -> mm1 */ + pmullw_r2r(mm4, mm1); /* mm1 * alpha -> mm1 */ + psrlw_i2r(8, mm1); /* mm1 >> 8 -> mm1 */ + paddb_r2r(mm1, mm6); /* mm1 + mm6(dst2) -> mm6 */ + + packuswb_r2r(mm6, mm2); /* ARGBARGB -> mm2 */ + por_r2r(mm7, mm2); /* mm7(dst alpha) | mm2 -> mm2 */ + + movq_r2m(mm2, *dstp);/* mm2 -> 2 x pixel */ + + srcp += 2; + dstp += 2; + }, width); + srcp += srcskip; + dstp += dstskip; + } + emms(); + } +} + +/* fast ARGB888->(A)RGB888 blending with pixel alpha */ +static void BlitRGBtoRGBPixelAlphaMMX(SDL_BlitInfo *info) +{ + int width = info->d_width; + int height = info->d_height; + Uint32 *srcp = (Uint32 *)info->s_pixels; + int srcskip = info->s_skip >> 2; + Uint32 *dstp = (Uint32 *)info->d_pixels; + int dstskip = info->d_skip >> 2; + SDL_PixelFormat* sf = info->src; + Uint32 amask = sf->Amask; + + pxor_r2r(mm6, mm6); /* 0 -> mm6 */ + /* form multiplication mask */ + movd_m2r(sf->Amask, mm7); /* 0000F000 -> mm7 */ + punpcklbw_r2r(mm7, mm7); /* FF000000 -> mm7 */ + pcmpeqb_r2r(mm0, mm0); /* FFFFFFFF -> mm0 */ + movq_r2r(mm0, mm3); /* FFFFFFFF -> mm3 (for later) */ + pxor_r2r(mm0, mm7); /* 00FFFFFF -> mm7 (mult mask) */ + /* form channel masks */ + movq_r2r(mm7, mm0); /* 00FFFFFF -> mm0 */ + packsswb_r2r(mm6, mm0); /* 00000FFF -> mm0 (channel mask) */ + packsswb_r2r(mm6, mm3); /* 0000FFFF -> mm3 */ + pxor_r2r(mm0, mm3); /* 0000F000 -> mm3 (~channel mask) */ + /* get alpha channel shift */ + __asm__ __volatile__ ( + "movd %0, %%mm5" + : : "rm" ((Uint32) sf->Ashift) ); /* Ashift -> mm5 */ + + while(height--) { + DUFFS_LOOP4({ + Uint32 alpha = *srcp & amask; + /* FIXME: Here we special-case opaque alpha since the + compositioning used (>>8 instead of /255) doesn't handle + it correctly. Also special-case alpha=0 for speed? + Benchmark this! */ + if(alpha == 0) { + /* do nothing */ + } else if(alpha == amask) { + /* opaque alpha -- copy RGB, keep dst alpha */ + /* using MMX here to free up regular registers for other things */ + movd_m2r((*srcp), mm1);/* src(ARGB) -> mm1 (0000ARGB)*/ + movd_m2r((*dstp), mm2);/* dst(ARGB) -> mm2 (0000ARGB)*/ + pand_r2r(mm0, mm1); /* src & chanmask -> mm1 */ + pand_r2r(mm3, mm2); /* dst & ~chanmask -> mm2 */ + por_r2r(mm1, mm2); /* src | dst -> mm2 */ + movd_r2m(mm2, (*dstp)); /* mm2 -> dst */ + } else { + movd_m2r((*srcp), mm1);/* src(ARGB) -> mm1 (0000ARGB)*/ + punpcklbw_r2r(mm6, mm1); /* 0A0R0G0B -> mm1 */ + + movd_m2r((*dstp), mm2);/* dst(ARGB) -> mm2 (0000ARGB)*/ + punpcklbw_r2r(mm6, mm2); /* 0A0R0G0B -> mm2 */ + + __asm__ __volatile__ ( + "movd %0, %%mm4" + : : "r" (alpha) ); /* 0000A000 -> mm4 */ + psrld_r2r(mm5, mm4); /* mm4 >> mm5 -> mm4 (0000000A) */ + punpcklwd_r2r(mm4, mm4); /* 00000A0A -> mm4 */ + punpcklwd_r2r(mm4, mm4); /* 0A0A0A0A -> mm4 */ + pand_r2r(mm7, mm4); /* 000A0A0A -> mm4, preserve dst alpha on add */ + + /* blend */ + psubw_r2r(mm2, mm1);/* src - dst -> mm1 */ + pmullw_r2r(mm4, mm1); /* mm1 * alpha -> mm1 */ + psrlw_i2r(8, mm1); /* mm1 >> 8 -> mm1(000R0G0B) */ + paddb_r2r(mm1, mm2); /* mm1 + mm2(dst) -> mm2 */ + + packuswb_r2r(mm6, mm2); /* 0000ARGB -> mm2 */ + movd_r2m(mm2, *dstp);/* mm2 -> dst */ + } + ++srcp; + ++dstp; + }, width); + srcp += srcskip; + dstp += dstskip; + } + emms(); +} +/* End GCC_ASMBLIT */ + +#elif MSVC_ASMBLIT +/* fast RGB888->(A)RGB888 blending with surface alpha=128 special case */ +static void BlitRGBtoRGBSurfaceAlpha128MMX(SDL_BlitInfo *info) +{ + int width = info->d_width; + int height = info->d_height; + Uint32 *srcp = (Uint32 *)info->s_pixels; + int srcskip = info->s_skip >> 2; + Uint32 *dstp = (Uint32 *)info->d_pixels; + int dstskip = info->d_skip >> 2; + Uint32 dalpha = info->dst->Amask; + + __m64 src1, src2, dst1, dst2, lmask, hmask, dsta; + + hmask = _mm_set_pi32(0x00fefefe, 0x00fefefe); /* alpha128 mask -> hmask */ + lmask = _mm_set_pi32(0x00010101, 0x00010101); /* !alpha128 mask -> lmask */ + dsta = _mm_set_pi32(dalpha, dalpha); /* dst alpha mask -> dsta */ + + while (height--) { + int n = width; + if ( n & 1 ) { + Uint32 s = *srcp++; + Uint32 d = *dstp; + *dstp++ = ((((s & 0x00fefefe) + (d & 0x00fefefe)) >> 1) + + (s & d & 0x00010101)) | dalpha; + n--; + } + + for (n >>= 1; n > 0; --n) { + dst1 = *(__m64*)dstp; /* 2 x dst -> dst1(ARGBARGB) */ + dst2 = dst1; /* 2 x dst -> dst2(ARGBARGB) */ + + src1 = *(__m64*)srcp; /* 2 x src -> src1(ARGBARGB) */ + src2 = src1; /* 2 x src -> src2(ARGBARGB) */ + + dst2 = _mm_and_si64(dst2, hmask); /* dst & mask -> dst2 */ + src2 = _mm_and_si64(src2, hmask); /* src & mask -> src2 */ + src2 = _mm_add_pi32(src2, dst2); /* dst2 + src2 -> src2 */ + src2 = _mm_srli_pi32(src2, 1); /* src2 >> 1 -> src2 */ + + dst1 = _mm_and_si64(dst1, src1); /* src & dst -> dst1 */ + dst1 = _mm_and_si64(dst1, lmask); /* dst1 & !mask -> dst1 */ + dst1 = _mm_add_pi32(dst1, src2); /* src2 + dst1 -> dst1 */ + dst1 = _mm_or_si64(dst1, dsta); /* dsta(full alpha) | dst1 -> dst1 */ + + *(__m64*)dstp = dst1; /* dst1 -> 2 x dst pixels */ + dstp += 2; + srcp += 2; + } + + srcp += srcskip; + dstp += dstskip; + } + _mm_empty(); +} + +/* fast RGB888->(A)RGB888 blending with surface alpha */ +static void BlitRGBtoRGBSurfaceAlphaMMX(SDL_BlitInfo *info) +{ + SDL_PixelFormat* df = info->dst; + Uint32 chanmask = df->Rmask | df->Gmask | df->Bmask; + unsigned alpha = info->src->alpha; + + if (alpha == 128 && (df->Rmask | df->Gmask | df->Bmask) == 0x00FFFFFF) { + /* only call a128 version when R,G,B occupy lower bits */ + BlitRGBtoRGBSurfaceAlpha128MMX(info); + } else { + int width = info->d_width; + int height = info->d_height; + Uint32 *srcp = (Uint32 *)info->s_pixels; + int srcskip = info->s_skip >> 2; + Uint32 *dstp = (Uint32 *)info->d_pixels; + int dstskip = info->d_skip >> 2; + Uint32 dalpha = df->Amask; + Uint32 amult; + + __m64 src1, src2, dst1, dst2, mm_alpha, mm_zero, dsta; + + mm_zero = _mm_setzero_si64(); /* 0 -> mm_zero */ + /* form the alpha mult */ + amult = alpha | (alpha << 8); + amult = amult | (amult << 16); + chanmask = (0xff << df->Rshift) | (0xff << df->Gshift) | (0xff << df->Bshift); + mm_alpha = _mm_set_pi32(0, amult & chanmask); /* 0000AAAA -> mm_alpha, minus 1 chan */ + mm_alpha = _mm_unpacklo_pi8(mm_alpha, mm_zero); /* 0A0A0A0A -> mm_alpha, minus 1 chan */ + /* at this point mm_alpha can be 000A0A0A or 0A0A0A00 or another combo */ + dsta = _mm_set_pi32(dalpha, dalpha); /* dst alpha mask -> dsta */ + + while (height--) { + int n = width; + if (n & 1) { + /* One Pixel Blend */ + src2 = _mm_cvtsi32_si64(*srcp); /* src(ARGB) -> src2 (0000ARGB)*/ + src2 = _mm_unpacklo_pi8(src2, mm_zero); /* 0A0R0G0B -> src2 */ + + dst1 = _mm_cvtsi32_si64(*dstp); /* dst(ARGB) -> dst1 (0000ARGB)*/ + dst1 = _mm_unpacklo_pi8(dst1, mm_zero); /* 0A0R0G0B -> dst1 */ + + src2 = _mm_sub_pi16(src2, dst1); /* src2 - dst2 -> src2 */ + src2 = _mm_mullo_pi16(src2, mm_alpha); /* src2 * alpha -> src2 */ + src2 = _mm_srli_pi16(src2, 8); /* src2 >> 8 -> src2 */ + dst1 = _mm_add_pi8(src2, dst1); /* src2 + dst1 -> dst1 */ + + dst1 = _mm_packs_pu16(dst1, mm_zero); /* 0000ARGB -> dst1 */ + dst1 = _mm_or_si64(dst1, dsta); /* dsta | dst1 -> dst1 */ + *dstp = _mm_cvtsi64_si32(dst1); /* dst1 -> pixel */ + + ++srcp; + ++dstp; + + n--; + } + + for (n >>= 1; n > 0; --n) { + /* Two Pixels Blend */ + src1 = *(__m64*)srcp; /* 2 x src -> src1(ARGBARGB)*/ + src2 = src1; /* 2 x src -> src2(ARGBARGB) */ + src1 = _mm_unpacklo_pi8(src1, mm_zero); /* low - 0A0R0G0B -> src1 */ + src2 = _mm_unpackhi_pi8(src2, mm_zero); /* high - 0A0R0G0B -> src2 */ + + dst1 = *(__m64*)dstp;/* 2 x dst -> dst1(ARGBARGB) */ + dst2 = dst1; /* 2 x dst -> dst2(ARGBARGB) */ + dst1 = _mm_unpacklo_pi8(dst1, mm_zero); /* low - 0A0R0G0B -> dst1 */ + dst2 = _mm_unpackhi_pi8(dst2, mm_zero); /* high - 0A0R0G0B -> dst2 */ + + src1 = _mm_sub_pi16(src1, dst1);/* src1 - dst1 -> src1 */ + src1 = _mm_mullo_pi16(src1, mm_alpha); /* src1 * alpha -> src1 */ + src1 = _mm_srli_pi16(src1, 8); /* src1 >> 8 -> src1 */ + dst1 = _mm_add_pi8(src1, dst1); /* src1 + dst1(dst1) -> dst1 */ + + src2 = _mm_sub_pi16(src2, dst2);/* src2 - dst2 -> src2 */ + src2 = _mm_mullo_pi16(src2, mm_alpha); /* src2 * alpha -> src2 */ + src2 = _mm_srli_pi16(src2, 8); /* src2 >> 8 -> src2 */ + dst2 = _mm_add_pi8(src2, dst2); /* src2 + dst2(dst2) -> dst2 */ + + dst1 = _mm_packs_pu16(dst1, dst2); /* 0A0R0G0B(res1), 0A0R0G0B(res2) -> dst1(ARGBARGB) */ + dst1 = _mm_or_si64(dst1, dsta); /* dsta | dst1 -> dst1 */ + + *(__m64*)dstp = dst1; /* dst1 -> 2 x pixel */ + + srcp += 2; + dstp += 2; + } + srcp += srcskip; + dstp += dstskip; + } + _mm_empty(); + } +} + +/* fast ARGB888->(A)RGB888 blending with pixel alpha */ +static void BlitRGBtoRGBPixelAlphaMMX(SDL_BlitInfo *info) +{ + int width = info->d_width; + int height = info->d_height; + Uint32 *srcp = (Uint32 *)info->s_pixels; + int srcskip = info->s_skip >> 2; + Uint32 *dstp = (Uint32 *)info->d_pixels; + int dstskip = info->d_skip >> 2; + SDL_PixelFormat* sf = info->src; + Uint32 chanmask = sf->Rmask | sf->Gmask | sf->Bmask; + Uint32 amask = sf->Amask; + Uint32 ashift = sf->Ashift; + Uint64 multmask; + + __m64 src1, dst1, mm_alpha, mm_zero, dmask; + + mm_zero = _mm_setzero_si64(); /* 0 -> mm_zero */ + multmask = ~(0xFFFFi64 << (ashift * 2)); + dmask = *(__m64*) &multmask; /* dst alpha mask -> dmask */ + + while(height--) { + DUFFS_LOOP4({ + Uint32 alpha = *srcp & amask; + if (alpha == 0) { + /* do nothing */ + } else if (alpha == amask) { + /* opaque alpha -- copy RGB, keep dst alpha */ + *dstp = (*srcp & chanmask) | (*dstp & ~chanmask); + } else { + src1 = _mm_cvtsi32_si64(*srcp); /* src(ARGB) -> src1 (0000ARGB)*/ + src1 = _mm_unpacklo_pi8(src1, mm_zero); /* 0A0R0G0B -> src1 */ + + dst1 = _mm_cvtsi32_si64(*dstp); /* dst(ARGB) -> dst1 (0000ARGB)*/ + dst1 = _mm_unpacklo_pi8(dst1, mm_zero); /* 0A0R0G0B -> dst1 */ + + mm_alpha = _mm_cvtsi32_si64(alpha); /* alpha -> mm_alpha (0000000A) */ + mm_alpha = _mm_srli_si64(mm_alpha, ashift); /* mm_alpha >> ashift -> mm_alpha(0000000A) */ + mm_alpha = _mm_unpacklo_pi16(mm_alpha, mm_alpha); /* 00000A0A -> mm_alpha */ + mm_alpha = _mm_unpacklo_pi32(mm_alpha, mm_alpha); /* 0A0A0A0A -> mm_alpha */ + mm_alpha = _mm_and_si64(mm_alpha, dmask); /* 000A0A0A -> mm_alpha, preserve dst alpha on add */ + + /* blend */ + src1 = _mm_sub_pi16(src1, dst1);/* src1 - dst1 -> src1 */ + src1 = _mm_mullo_pi16(src1, mm_alpha); /* (src1 - dst1) * alpha -> src1 */ + src1 = _mm_srli_pi16(src1, 8); /* src1 >> 8 -> src1(000R0G0B) */ + dst1 = _mm_add_pi8(src1, dst1); /* src1 + dst1 -> dst1(0A0R0G0B) */ + dst1 = _mm_packs_pu16(dst1, mm_zero); /* 0000ARGB -> dst1 */ + + *dstp = _mm_cvtsi64_si32(dst1); /* dst1 -> pixel */ + } + ++srcp; + ++dstp; + }, width); + srcp += srcskip; + dstp += dstskip; + } + _mm_empty(); +} +/* End MSVC_ASMBLIT */ + +#endif /* GCC_ASMBLIT, MSVC_ASMBLIT */ + +#if SDL_ALTIVEC_BLITTERS +#if __MWERKS__ +#pragma altivec_model on +#endif +#if HAVE_ALTIVEC_H +#include <altivec.h> +#endif +#include <assert.h> + +#if (defined(__MACOSX__) && (__GNUC__ < 4)) + #define VECUINT8_LITERAL(a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p) \ + (vector unsigned char) ( a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p ) + #define VECUINT16_LITERAL(a,b,c,d,e,f,g,h) \ + (vector unsigned short) ( a,b,c,d,e,f,g,h ) +#else + #define VECUINT8_LITERAL(a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p) \ + (vector unsigned char) { a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p } + #define VECUINT16_LITERAL(a,b,c,d,e,f,g,h) \ + (vector unsigned short) { a,b,c,d,e,f,g,h } +#endif + +#define UNALIGNED_PTR(x) (((size_t) x) & 0x0000000F) +#define VECPRINT(msg, v) do { \ + vector unsigned int tmpvec = (vector unsigned int)(v); \ + unsigned int *vp = (unsigned int *)&tmpvec; \ + printf("%s = %08X %08X %08X %08X\n", msg, vp[0], vp[1], vp[2], vp[3]); \ +} while (0) + +/* the permuation vector that takes the high bytes out of all the appropriate shorts + (vector unsigned char)( + 0x00, 0x10, 0x02, 0x12, + 0x04, 0x14, 0x06, 0x16, + 0x08, 0x18, 0x0A, 0x1A, + 0x0C, 0x1C, 0x0E, 0x1E ); +*/ +#define VEC_MERGE_PERMUTE() (vec_add(vec_lvsl(0, (int*)NULL), (vector unsigned char)vec_splat_u16(0x0F))) +#define VEC_U32_24() (vec_add(vec_splat_u32(12), vec_splat_u32(12))) +#define VEC_ALPHA_MASK() ((vector unsigned char)vec_sl((vector unsigned int)vec_splat_s8(-1), VEC_U32_24())) +#define VEC_ALIGNER(src) ((UNALIGNED_PTR(src)) \ + ? vec_lvsl(0, src) \ + : vec_add(vec_lvsl(8, src), vec_splat_u8(8))) + + +#define VEC_MULTIPLY_ALPHA(vs, vd, valpha, mergePermute, v1_16, v8_16) do { \ + /* vtemp1 contains source AAGGAAGGAAGGAAGG */ \ + vector unsigned short vtemp1 = vec_mule(vs, valpha); \ + /* vtemp2 contains source RRBBRRBBRRBBRRBB */ \ + vector unsigned short vtemp2 = vec_mulo(vs, valpha); \ + /* valpha2 is 255-alpha */ \ + vector unsigned char valpha2 = vec_nor(valpha, valpha); \ + /* vtemp3 contains dest AAGGAAGGAAGGAAGG */ \ + vector unsigned short vtemp3 = vec_mule(vd, valpha2); \ + /* vtemp4 contains dest RRBBRRBBRRBBRRBB */ \ + vector unsigned short vtemp4 = vec_mulo(vd, valpha2); \ + /* add source and dest */ \ + vtemp1 = vec_add(vtemp1, vtemp3); \ + vtemp2 = vec_add(vtemp2, vtemp4); \ + /* vtemp1 = (vtemp1 + 1) + ((vtemp1 + 1) >> 8) */ \ + vtemp1 = vec_add(vtemp1, v1_16); \ + vtemp3 = vec_sr(vtemp1, v8_16); \ + vtemp1 = vec_add(vtemp1, vtemp3); \ + /* vtemp2 = (vtemp2 + 1) + ((vtemp2 + 1) >> 8) */ \ + vtemp2 = vec_add(vtemp2, v1_16); \ + vtemp4 = vec_sr(vtemp2, v8_16); \ + vtemp2 = vec_add(vtemp2, vtemp4); \ + /* (>>8) and get ARGBARGBARGBARGB */ \ + vd = (vector unsigned char)vec_perm(vtemp1, vtemp2, mergePermute); \ +} while (0) + +/* Calculate the permute vector used for 32->32 swizzling */ +static vector unsigned char calc_swizzle32(const SDL_PixelFormat *srcfmt, + const SDL_PixelFormat *dstfmt) +{ + /* + * We have to assume that the bits that aren't used by other + * colors is alpha, and it's one complete byte, since some formats + * leave alpha with a zero mask, but we should still swizzle the bits. + */ + /* ARGB */ + const static struct SDL_PixelFormat default_pixel_format = { + NULL, 0, 0, + 0, 0, 0, 0, + 16, 8, 0, 24, + 0x00FF0000, 0x0000FF00, 0x000000FF, 0xFF000000, + 0, 0}; + if (!srcfmt) { + srcfmt = &default_pixel_format; + } + if (!dstfmt) { + dstfmt = &default_pixel_format; + } + const vector unsigned char plus = VECUINT8_LITERAL + ( 0x00, 0x00, 0x00, 0x00, + 0x04, 0x04, 0x04, 0x04, + 0x08, 0x08, 0x08, 0x08, + 0x0C, 0x0C, 0x0C, 0x0C ); + vector unsigned char vswiz; + vector unsigned int srcvec; +#define RESHIFT(X) (3 - ((X) >> 3)) + Uint32 rmask = RESHIFT(srcfmt->Rshift) << (dstfmt->Rshift); + Uint32 gmask = RESHIFT(srcfmt->Gshift) << (dstfmt->Gshift); + Uint32 bmask = RESHIFT(srcfmt->Bshift) << (dstfmt->Bshift); + Uint32 amask; + /* Use zero for alpha if either surface doesn't have alpha */ + if (dstfmt->Amask) { + amask = ((srcfmt->Amask) ? RESHIFT(srcfmt->Ashift) : 0x10) << (dstfmt->Ashift); + } else { + amask = 0x10101010 & ((dstfmt->Rmask | dstfmt->Gmask | dstfmt->Bmask) ^ 0xFFFFFFFF); + } +#undef RESHIFT + ((unsigned int *)(char*)&srcvec)[0] = (rmask | gmask | bmask | amask); + vswiz = vec_add(plus, (vector unsigned char)vec_splat(srcvec, 0)); + return(vswiz); +} + +static void Blit32to565PixelAlphaAltivec(SDL_BlitInfo *info) +{ + int height = info->d_height; + Uint8 *src = (Uint8 *)info->s_pixels; + int srcskip = info->s_skip; + Uint8 *dst = (Uint8 *)info->d_pixels; + int dstskip = info->d_skip; + SDL_PixelFormat *srcfmt = info->src; + + vector unsigned char v0 = vec_splat_u8(0); + vector unsigned short v8_16 = vec_splat_u16(8); + vector unsigned short v1_16 = vec_splat_u16(1); + vector unsigned short v2_16 = vec_splat_u16(2); + vector unsigned short v3_16 = vec_splat_u16(3); + vector unsigned int v8_32 = vec_splat_u32(8); + vector unsigned int v16_32 = vec_add(v8_32, v8_32); + vector unsigned short v3f = VECUINT16_LITERAL( + 0x003f, 0x003f, 0x003f, 0x003f, + 0x003f, 0x003f, 0x003f, 0x003f); + vector unsigned short vfc = VECUINT16_LITERAL( + 0x00fc, 0x00fc, 0x00fc, 0x00fc, + 0x00fc, 0x00fc, 0x00fc, 0x00fc); + + /* + 0x10 - 0x1f is the alpha + 0x00 - 0x0e evens are the red + 0x01 - 0x0f odds are zero + */ + vector unsigned char vredalpha1 = VECUINT8_LITERAL( + 0x10, 0x00, 0x01, 0x01, + 0x10, 0x02, 0x01, 0x01, + 0x10, 0x04, 0x01, 0x01, + 0x10, 0x06, 0x01, 0x01 + ); + vector unsigned char vredalpha2 = (vector unsigned char)( + vec_add((vector unsigned int)vredalpha1, vec_sl(v8_32, v16_32)) + ); + /* + 0x00 - 0x0f is ARxx ARxx ARxx ARxx + 0x11 - 0x0f odds are blue + */ + vector unsigned char vblue1 = VECUINT8_LITERAL( + 0x00, 0x01, 0x02, 0x11, + 0x04, 0x05, 0x06, 0x13, + 0x08, 0x09, 0x0a, 0x15, + 0x0c, 0x0d, 0x0e, 0x17 + ); + vector unsigned char vblue2 = (vector unsigned char)( + vec_add((vector unsigned int)vblue1, v8_32) + ); + /* + 0x00 - 0x0f is ARxB ARxB ARxB ARxB + 0x10 - 0x0e evens are green + */ + vector unsigned char vgreen1 = VECUINT8_LITERAL( + 0x00, 0x01, 0x10, 0x03, + 0x04, 0x05, 0x12, 0x07, + 0x08, 0x09, 0x14, 0x0b, + 0x0c, 0x0d, 0x16, 0x0f + ); + vector unsigned char vgreen2 = (vector unsigned char)( + vec_add((vector unsigned int)vgreen1, vec_sl(v8_32, v8_32)) + ); + vector unsigned char vgmerge = VECUINT8_LITERAL( + 0x00, 0x02, 0x00, 0x06, + 0x00, 0x0a, 0x00, 0x0e, + 0x00, 0x12, 0x00, 0x16, + 0x00, 0x1a, 0x00, 0x1e); + vector unsigned char mergePermute = VEC_MERGE_PERMUTE(); + vector unsigned char vpermute = calc_swizzle32(srcfmt, NULL); + vector unsigned char valphaPermute = vec_and(vec_lvsl(0, (int *)NULL), vec_splat_u8(0xC)); + + vector unsigned short vf800 = (vector unsigned short)vec_splat_u8(-7); + vf800 = vec_sl(vf800, vec_splat_u16(8)); + + while(height--) { + int extrawidth; + vector unsigned char valigner; + vector unsigned char vsrc; + vector unsigned char voverflow; + int width = info->d_width; + +#define ONE_PIXEL_BLEND(condition, widthvar) \ + while (condition) { \ + Uint32 Pixel; \ + unsigned sR, sG, sB, dR, dG, dB, sA; \ + DISEMBLE_RGBA(src, 4, srcfmt, Pixel, sR, sG, sB, sA); \ + if(sA) { \ + unsigned short dstpixel = *((unsigned short *)dst); \ + dR = (dstpixel >> 8) & 0xf8; \ + dG = (dstpixel >> 3) & 0xfc; \ + dB = (dstpixel << 3) & 0xf8; \ + ALPHA_BLEND(sR, sG, sB, sA, dR, dG, dB); \ + *((unsigned short *)dst) = ( \ + ((dR & 0xf8) << 8) | ((dG & 0xfc) << 3) | (dB >> 3) \ + ); \ + } \ + src += 4; \ + dst += 2; \ + widthvar--; \ + } + ONE_PIXEL_BLEND((UNALIGNED_PTR(dst)) && (width), width); + extrawidth = (width % 8); + valigner = VEC_ALIGNER(src); + vsrc = (vector unsigned char)vec_ld(0, src); + width -= extrawidth; + while (width) { + vector unsigned char valpha; + vector unsigned char vsrc1, vsrc2; + vector unsigned char vdst1, vdst2; + vector unsigned short vR, vG, vB; + vector unsigned short vpixel, vrpixel, vgpixel, vbpixel; + + /* Load 8 pixels from src as ARGB */ + voverflow = (vector unsigned char)vec_ld(15, src); + vsrc = vec_perm(vsrc, voverflow, valigner); + vsrc1 = vec_perm(vsrc, vsrc, vpermute); + src += 16; + vsrc = (vector unsigned char)vec_ld(15, src); + voverflow = vec_perm(voverflow, vsrc, valigner); + vsrc2 = vec_perm(voverflow, voverflow, vpermute); + src += 16; + + /* Load 8 pixels from dst as XRGB */ + voverflow = vec_ld(0, dst); + vR = vec_and((vector unsigned short)voverflow, vf800); + vB = vec_sl((vector unsigned short)voverflow, v3_16); + vG = vec_sl(vB, v2_16); + vdst1 = (vector unsigned char)vec_perm((vector unsigned char)vR, (vector unsigned char)vR, vredalpha1); + vdst1 = vec_perm(vdst1, (vector unsigned char)vB, vblue1); + vdst1 = vec_perm(vdst1, (vector unsigned char)vG, vgreen1); + vdst2 = (vector unsigned char)vec_perm((vector unsigned char)vR, (vector unsigned char)vR, vredalpha2); + vdst2 = vec_perm(vdst2, (vector unsigned char)vB, vblue2); + vdst2 = vec_perm(vdst2, (vector unsigned char)vG, vgreen2); + + /* Alpha blend 8 pixels as ARGB */ + valpha = vec_perm(vsrc1, v0, valphaPermute); + VEC_MULTIPLY_ALPHA(vsrc1, vdst1, valpha, mergePermute, v1_16, v8_16); + valpha = vec_perm(vsrc2, v0, valphaPermute); + VEC_MULTIPLY_ALPHA(vsrc2, vdst2, valpha, mergePermute, v1_16, v8_16); + + /* Convert 8 pixels to 565 */ + vpixel = (vector unsigned short)vec_packpx((vector unsigned int)vdst1, (vector unsigned int)vdst2); + vgpixel = (vector unsigned short)vec_perm(vdst1, vdst2, vgmerge); + vgpixel = vec_and(vgpixel, vfc); + vgpixel = vec_sl(vgpixel, v3_16); + vrpixel = vec_sl(vpixel, v1_16); + vrpixel = vec_and(vrpixel, vf800); + vbpixel = vec_and(vpixel, v3f); + vdst1 = vec_or((vector unsigned char)vrpixel, (vector unsigned char)vgpixel); + vdst1 = vec_or(vdst1, (vector unsigned char)vbpixel); + + /* Store 8 pixels */ + vec_st(vdst1, 0, dst); + + width -= 8; + dst += 16; + } + ONE_PIXEL_BLEND((extrawidth), extrawidth); +#undef ONE_PIXEL_BLEND + src += srcskip; + dst += dstskip; + } +} + +static void Blit32to32SurfaceAlphaKeyAltivec(SDL_BlitInfo *info) +{ + unsigned alpha = info->src->alpha; + int height = info->d_height; + Uint32 *srcp = (Uint32 *)info->s_pixels; + int srcskip = info->s_skip >> 2; + Uint32 *dstp = (Uint32 *)info->d_pixels; + int dstskip = info->d_skip >> 2; + SDL_PixelFormat *srcfmt = info->src; + SDL_PixelFormat *dstfmt = info->dst; + unsigned sA = srcfmt->alpha; + unsigned dA = dstfmt->Amask ? SDL_ALPHA_OPAQUE : 0; + Uint32 rgbmask = srcfmt->Rmask | srcfmt->Gmask | srcfmt->Bmask; + Uint32 ckey = info->src->colorkey; + vector unsigned char mergePermute; + vector unsigned char vsrcPermute; + vector unsigned char vdstPermute; + vector unsigned char vsdstPermute; + vector unsigned char valpha; + vector unsigned char valphamask; + vector unsigned char vbits; + vector unsigned char v0; + vector unsigned short v1; + vector unsigned short v8; + vector unsigned int vckey; + vector unsigned int vrgbmask; + + mergePermute = VEC_MERGE_PERMUTE(); + v0 = vec_splat_u8(0); + v1 = vec_splat_u16(1); + v8 = vec_splat_u16(8); + + /* set the alpha to 255 on the destination surf */ + valphamask = VEC_ALPHA_MASK(); + + vsrcPermute = calc_swizzle32(srcfmt, NULL); + vdstPermute = calc_swizzle32(NULL, dstfmt); + vsdstPermute = calc_swizzle32(dstfmt, NULL); + + /* set a vector full of alpha and 255-alpha */ + ((unsigned char *)&valpha)[0] = alpha; + valpha = vec_splat(valpha, 0); + vbits = (vector unsigned char)vec_splat_s8(-1); + + ckey &= rgbmask; + ((unsigned int *)(char*)&vckey)[0] = ckey; + vckey = vec_splat(vckey, 0); + ((unsigned int *)(char*)&vrgbmask)[0] = rgbmask; + vrgbmask = vec_splat(vrgbmask, 0); + + while(height--) { + int width = info->d_width; +#define ONE_PIXEL_BLEND(condition, widthvar) \ + while (condition) { \ + Uint32 Pixel; \ + unsigned sR, sG, sB, dR, dG, dB; \ + RETRIEVE_RGB_PIXEL(((Uint8 *)srcp), 4, Pixel); \ + if(sA && Pixel != ckey) { \ + RGB_FROM_PIXEL(Pixel, srcfmt, sR, sG, sB); \ + DISEMBLE_RGB(((Uint8 *)dstp), 4, dstfmt, Pixel, dR, dG, dB); \ + ALPHA_BLEND(sR, sG, sB, sA, dR, dG, dB); \ + ASSEMBLE_RGBA(((Uint8 *)dstp), 4, dstfmt, dR, dG, dB, dA); \ + } \ + dstp++; \ + srcp++; \ + widthvar--; \ + } + ONE_PIXEL_BLEND((UNALIGNED_PTR(dstp)) && (width), width); + if (width > 0) { + int extrawidth = (width % 4); + vector unsigned char valigner = VEC_ALIGNER(srcp); + vector unsigned char vs = (vector unsigned char)vec_ld(0, srcp); + width -= extrawidth; + while (width) { + vector unsigned char vsel; + vector unsigned char voverflow; + vector unsigned char vd; + vector unsigned char vd_orig; + + /* s = *srcp */ + voverflow = (vector unsigned char)vec_ld(15, srcp); + vs = vec_perm(vs, voverflow, valigner); + + /* vsel is set for items that match the key */ + vsel = (vector unsigned char)vec_and((vector unsigned int)vs, vrgbmask); + vsel = (vector unsigned char)vec_cmpeq((vector unsigned int)vsel, vckey); + + /* permute to source format */ + vs = vec_perm(vs, valpha, vsrcPermute); + + /* d = *dstp */ + vd = (vector unsigned char)vec_ld(0, dstp); + vd_orig = vd = vec_perm(vd, v0, vsdstPermute); + + VEC_MULTIPLY_ALPHA(vs, vd, valpha, mergePermute, v1, v8); + + /* set the alpha channel to full on */ + vd = vec_or(vd, valphamask); + + /* mask out color key */ + vd = vec_sel(vd, vd_orig, vsel); + + /* permute to dest format */ + vd = vec_perm(vd, vbits, vdstPermute); + + /* *dstp = res */ + vec_st((vector unsigned int)vd, 0, dstp); + + srcp += 4; + dstp += 4; + width -= 4; + vs = voverflow; + } + ONE_PIXEL_BLEND((extrawidth), extrawidth); + } +#undef ONE_PIXEL_BLEND + + srcp += srcskip; + dstp += dstskip; + } +} + + +static void Blit32to32PixelAlphaAltivec(SDL_BlitInfo *info) +{ + int width = info->d_width; + int height = info->d_height; + Uint32 *srcp = (Uint32 *)info->s_pixels; + int srcskip = info->s_skip >> 2; + Uint32 *dstp = (Uint32 *)info->d_pixels; + int dstskip = info->d_skip >> 2; + SDL_PixelFormat *srcfmt = info->src; + SDL_PixelFormat *dstfmt = info->dst; + vector unsigned char mergePermute; + vector unsigned char valphaPermute; + vector unsigned char vsrcPermute; + vector unsigned char vdstPermute; + vector unsigned char vsdstPermute; + vector unsigned char valphamask; + vector unsigned char vpixelmask; + vector unsigned char v0; + vector unsigned short v1; + vector unsigned short v8; + + v0 = vec_splat_u8(0); + v1 = vec_splat_u16(1); + v8 = vec_splat_u16(8); + mergePermute = VEC_MERGE_PERMUTE(); + valphamask = VEC_ALPHA_MASK(); + valphaPermute = vec_and(vec_lvsl(0, (int *)NULL), vec_splat_u8(0xC)); + vpixelmask = vec_nor(valphamask, v0); + vsrcPermute = calc_swizzle32(srcfmt, NULL); + vdstPermute = calc_swizzle32(NULL, dstfmt); + vsdstPermute = calc_swizzle32(dstfmt, NULL); + + while ( height-- ) { + width = info->d_width; +#define ONE_PIXEL_BLEND(condition, widthvar) while ((condition)) { \ + Uint32 Pixel; \ + unsigned sR, sG, sB, dR, dG, dB, sA, dA; \ + DISEMBLE_RGBA((Uint8 *)srcp, 4, srcfmt, Pixel, sR, sG, sB, sA); \ + if(sA) { \ + DISEMBLE_RGBA((Uint8 *)dstp, 4, dstfmt, Pixel, dR, dG, dB, dA); \ + ALPHA_BLEND(sR, sG, sB, sA, dR, dG, dB); \ + ASSEMBLE_RGBA((Uint8 *)dstp, 4, dstfmt, dR, dG, dB, dA); \ + } \ + ++srcp; \ + ++dstp; \ + widthvar--; \ + } + ONE_PIXEL_BLEND((UNALIGNED_PTR(dstp)) && (width), width); + if (width > 0) { + /* vsrcPermute */ + /* vdstPermute */ + int extrawidth = (width % 4); + vector unsigned char valigner = VEC_ALIGNER(srcp); + vector unsigned char vs = (vector unsigned char)vec_ld(0, srcp); + width -= extrawidth; + while (width) { + vector unsigned char voverflow; + vector unsigned char vd; + vector unsigned char valpha; + vector unsigned char vdstalpha; + /* s = *srcp */ + voverflow = (vector unsigned char)vec_ld(15, srcp); + vs = vec_perm(vs, voverflow, valigner); + vs = vec_perm(vs, v0, vsrcPermute); + + valpha = vec_perm(vs, v0, valphaPermute); + + /* d = *dstp */ + vd = (vector unsigned char)vec_ld(0, dstp); + vd = vec_perm(vd, v0, vsdstPermute); + vdstalpha = vec_and(vd, valphamask); + + VEC_MULTIPLY_ALPHA(vs, vd, valpha, mergePermute, v1, v8); + + /* set the alpha to the dest alpha */ + vd = vec_and(vd, vpixelmask); + vd = vec_or(vd, vdstalpha); + vd = vec_perm(vd, v0, vdstPermute); + + /* *dstp = res */ + vec_st((vector unsigned int)vd, 0, dstp); + + srcp += 4; + dstp += 4; + width -= 4; + vs = voverflow; + + } + ONE_PIXEL_BLEND((extrawidth), extrawidth); + } + srcp += srcskip; + dstp += dstskip; +#undef ONE_PIXEL_BLEND + } +} + +/* fast ARGB888->(A)RGB888 blending with pixel alpha */ +static void BlitRGBtoRGBPixelAlphaAltivec(SDL_BlitInfo *info) +{ + int width = info->d_width; + int height = info->d_height; + Uint32 *srcp = (Uint32 *)info->s_pixels; + int srcskip = info->s_skip >> 2; + Uint32 *dstp = (Uint32 *)info->d_pixels; + int dstskip = info->d_skip >> 2; + vector unsigned char mergePermute; + vector unsigned char valphaPermute; + vector unsigned char valphamask; + vector unsigned char vpixelmask; + vector unsigned char v0; + vector unsigned short v1; + vector unsigned short v8; + v0 = vec_splat_u8(0); + v1 = vec_splat_u16(1); + v8 = vec_splat_u16(8); + mergePermute = VEC_MERGE_PERMUTE(); + valphamask = VEC_ALPHA_MASK(); + valphaPermute = vec_and(vec_lvsl(0, (int *)NULL), vec_splat_u8(0xC)); + + + vpixelmask = vec_nor(valphamask, v0); + while(height--) { + width = info->d_width; +#define ONE_PIXEL_BLEND(condition, widthvar) \ + while ((condition)) { \ + Uint32 dalpha; \ + Uint32 d; \ + Uint32 s1; \ + Uint32 d1; \ + Uint32 s = *srcp; \ + Uint32 alpha = s >> 24; \ + if(alpha) { \ + if(alpha == SDL_ALPHA_OPAQUE) { \ + *dstp = (s & 0x00ffffff) | (*dstp & 0xff000000); \ + } else { \ + d = *dstp; \ + dalpha = d & 0xff000000; \ + s1 = s & 0xff00ff; \ + d1 = d & 0xff00ff; \ + d1 = (d1 + ((s1 - d1) * alpha >> 8)) & 0xff00ff; \ + s &= 0xff00; \ + d &= 0xff00; \ + d = (d + ((s - d) * alpha >> 8)) & 0xff00; \ + *dstp = d1 | d | dalpha; \ + } \ + } \ + ++srcp; \ + ++dstp; \ + widthvar--; \ + } + ONE_PIXEL_BLEND((UNALIGNED_PTR(dstp)) && (width), width); + if (width > 0) { + int extrawidth = (width % 4); + vector unsigned char valigner = VEC_ALIGNER(srcp); + vector unsigned char vs = (vector unsigned char)vec_ld(0, srcp); + width -= extrawidth; + while (width) { + vector unsigned char voverflow; + vector unsigned char vd; + vector unsigned char valpha; + vector unsigned char vdstalpha; + /* s = *srcp */ + voverflow = (vector unsigned char)vec_ld(15, srcp); + vs = vec_perm(vs, voverflow, valigner); + + valpha = vec_perm(vs, v0, valphaPermute); + + /* d = *dstp */ + vd = (vector unsigned char)vec_ld(0, dstp); + vdstalpha = vec_and(vd, valphamask); + + VEC_MULTIPLY_ALPHA(vs, vd, valpha, mergePermute, v1, v8); + + /* set the alpha to the dest alpha */ + vd = vec_and(vd, vpixelmask); + vd = vec_or(vd, vdstalpha); + + /* *dstp = res */ + vec_st((vector unsigned int)vd, 0, dstp); + + srcp += 4; + dstp += 4; + width -= 4; + vs = voverflow; + } + ONE_PIXEL_BLEND((extrawidth), extrawidth); + } + srcp += srcskip; + dstp += dstskip; + } +#undef ONE_PIXEL_BLEND +} + +static void Blit32to32SurfaceAlphaAltivec(SDL_BlitInfo *info) +{ + /* XXX : 6 */ + unsigned alpha = info->src->alpha; + int height = info->d_height; + Uint32 *srcp = (Uint32 *)info->s_pixels; + int srcskip = info->s_skip >> 2; + Uint32 *dstp = (Uint32 *)info->d_pixels; + int dstskip = info->d_skip >> 2; + SDL_PixelFormat *srcfmt = info->src; + SDL_PixelFormat *dstfmt = info->dst; + unsigned sA = srcfmt->alpha; + unsigned dA = dstfmt->Amask ? SDL_ALPHA_OPAQUE : 0; + vector unsigned char mergePermute; + vector unsigned char vsrcPermute; + vector unsigned char vdstPermute; + vector unsigned char vsdstPermute; + vector unsigned char valpha; + vector unsigned char valphamask; + vector unsigned char vbits; + vector unsigned short v1; + vector unsigned short v8; + + mergePermute = VEC_MERGE_PERMUTE(); + v1 = vec_splat_u16(1); + v8 = vec_splat_u16(8); + + /* set the alpha to 255 on the destination surf */ + valphamask = VEC_ALPHA_MASK(); + + vsrcPermute = calc_swizzle32(srcfmt, NULL); + vdstPermute = calc_swizzle32(NULL, dstfmt); + vsdstPermute = calc_swizzle32(dstfmt, NULL); + + /* set a vector full of alpha and 255-alpha */ + ((unsigned char *)&valpha)[0] = alpha; + valpha = vec_splat(valpha, 0); + vbits = (vector unsigned char)vec_splat_s8(-1); + + while(height--) { + int width = info->d_width; +#define ONE_PIXEL_BLEND(condition, widthvar) while ((condition)) { \ + Uint32 Pixel; \ + unsigned sR, sG, sB, dR, dG, dB; \ + DISEMBLE_RGB(((Uint8 *)srcp), 4, srcfmt, Pixel, sR, sG, sB); \ + DISEMBLE_RGB(((Uint8 *)dstp), 4, dstfmt, Pixel, dR, dG, dB); \ + ALPHA_BLEND(sR, sG, sB, sA, dR, dG, dB); \ + ASSEMBLE_RGBA(((Uint8 *)dstp), 4, dstfmt, dR, dG, dB, dA); \ + ++srcp; \ + ++dstp; \ + widthvar--; \ + } + ONE_PIXEL_BLEND((UNALIGNED_PTR(dstp)) && (width), width); + if (width > 0) { + int extrawidth = (width % 4); + vector unsigned char valigner = VEC_ALIGNER(srcp); + vector unsigned char vs = (vector unsigned char)vec_ld(0, srcp); + width -= extrawidth; + while (width) { + vector unsigned char voverflow; + vector unsigned char vd; + + /* s = *srcp */ + voverflow = (vector unsigned char)vec_ld(15, srcp); + vs = vec_perm(vs, voverflow, valigner); + vs = vec_perm(vs, valpha, vsrcPermute); + + /* d = *dstp */ + vd = (vector unsigned char)vec_ld(0, dstp); + vd = vec_perm(vd, vd, vsdstPermute); + + VEC_MULTIPLY_ALPHA(vs, vd, valpha, mergePermute, v1, v8); + + /* set the alpha channel to full on */ + vd = vec_or(vd, valphamask); + vd = vec_perm(vd, vbits, vdstPermute); + + /* *dstp = res */ + vec_st((vector unsigned int)vd, 0, dstp); + + srcp += 4; + dstp += 4; + width -= 4; + vs = voverflow; + } + ONE_PIXEL_BLEND((extrawidth), extrawidth); + } +#undef ONE_PIXEL_BLEND + + srcp += srcskip; + dstp += dstskip; + } + +} + + +/* fast RGB888->(A)RGB888 blending */ +static void BlitRGBtoRGBSurfaceAlphaAltivec(SDL_BlitInfo *info) +{ + unsigned alpha = info->src->alpha; + int height = info->d_height; + Uint32 *srcp = (Uint32 *)info->s_pixels; + int srcskip = info->s_skip >> 2; + Uint32 *dstp = (Uint32 *)info->d_pixels; + int dstskip = info->d_skip >> 2; + vector unsigned char mergePermute; + vector unsigned char valpha; + vector unsigned char valphamask; + vector unsigned short v1; + vector unsigned short v8; + + mergePermute = VEC_MERGE_PERMUTE(); + v1 = vec_splat_u16(1); + v8 = vec_splat_u16(8); + + /* set the alpha to 255 on the destination surf */ + valphamask = VEC_ALPHA_MASK(); + + /* set a vector full of alpha and 255-alpha */ + ((unsigned char *)&valpha)[0] = alpha; + valpha = vec_splat(valpha, 0); + + while(height--) { + int width = info->d_width; +#define ONE_PIXEL_BLEND(condition, widthvar) while ((condition)) { \ + Uint32 s = *srcp; \ + Uint32 d = *dstp; \ + Uint32 s1 = s & 0xff00ff; \ + Uint32 d1 = d & 0xff00ff; \ + d1 = (d1 + ((s1 - d1) * alpha >> 8)) \ + & 0xff00ff; \ + s &= 0xff00; \ + d &= 0xff00; \ + d = (d + ((s - d) * alpha >> 8)) & 0xff00; \ + *dstp = d1 | d | 0xff000000; \ + ++srcp; \ + ++dstp; \ + widthvar--; \ + } + ONE_PIXEL_BLEND((UNALIGNED_PTR(dstp)) && (width), width); + if (width > 0) { + int extrawidth = (width % 4); + vector unsigned char valigner = VEC_ALIGNER(srcp); + vector unsigned char vs = (vector unsigned char)vec_ld(0, srcp); + width -= extrawidth; + while (width) { + vector unsigned char voverflow; + vector unsigned char vd; + + /* s = *srcp */ + voverflow = (vector unsigned char)vec_ld(15, srcp); + vs = vec_perm(vs, voverflow, valigner); + + /* d = *dstp */ + vd = (vector unsigned char)vec_ld(0, dstp); + + VEC_MULTIPLY_ALPHA(vs, vd, valpha, mergePermute, v1, v8); + + /* set the alpha channel to full on */ + vd = vec_or(vd, valphamask); + + /* *dstp = res */ + vec_st((vector unsigned int)vd, 0, dstp); + + srcp += 4; + dstp += 4; + width -= 4; + vs = voverflow; + } + ONE_PIXEL_BLEND((extrawidth), extrawidth); + } +#undef ONE_PIXEL_BLEND + + srcp += srcskip; + dstp += dstskip; + } +} +#if __MWERKS__ +#pragma altivec_model off +#endif +#endif /* SDL_ALTIVEC_BLITTERS */ + +/* fast RGB888->(A)RGB888 blending with surface alpha=128 special case */ +static void BlitRGBtoRGBSurfaceAlpha128(SDL_BlitInfo *info) +{ + int width = info->d_width; + int height = info->d_height; + Uint32 *srcp = (Uint32 *)info->s_pixels; + int srcskip = info->s_skip >> 2; + Uint32 *dstp = (Uint32 *)info->d_pixels; + int dstskip = info->d_skip >> 2; + + while(height--) { + DUFFS_LOOP4({ + Uint32 s = *srcp++; + Uint32 d = *dstp; + *dstp++ = ((((s & 0x00fefefe) + (d & 0x00fefefe)) >> 1) + + (s & d & 0x00010101)) | 0xff000000; + }, width); + srcp += srcskip; + dstp += dstskip; + } +} + +/* fast RGB888->(A)RGB888 blending with surface alpha */ +static void BlitRGBtoRGBSurfaceAlpha(SDL_BlitInfo *info) +{ + unsigned alpha = info->src->alpha; + if(alpha == 128) { + BlitRGBtoRGBSurfaceAlpha128(info); + } else { + int width = info->d_width; + int height = info->d_height; + Uint32 *srcp = (Uint32 *)info->s_pixels; + int srcskip = info->s_skip >> 2; + Uint32 *dstp = (Uint32 *)info->d_pixels; + int dstskip = info->d_skip >> 2; + Uint32 s; + Uint32 d; + Uint32 s1; + Uint32 d1; + + while(height--) { + DUFFS_LOOP_DOUBLE2({ + /* One Pixel Blend */ + s = *srcp; + d = *dstp; + s1 = s & 0xff00ff; + d1 = d & 0xff00ff; + d1 = (d1 + ((s1 - d1) * alpha >> 8)) + & 0xff00ff; + s &= 0xff00; + d &= 0xff00; + d = (d + ((s - d) * alpha >> 8)) & 0xff00; + *dstp = d1 | d | 0xff000000; + ++srcp; + ++dstp; + },{ + /* Two Pixels Blend */ + s = *srcp; + d = *dstp; + s1 = s & 0xff00ff; + d1 = d & 0xff00ff; + d1 += (s1 - d1) * alpha >> 8; + d1 &= 0xff00ff; + + s = ((s & 0xff00) >> 8) | + ((srcp[1] & 0xff00) << 8); + d = ((d & 0xff00) >> 8) | + ((dstp[1] & 0xff00) << 8); + d += (s - d) * alpha >> 8; + d &= 0x00ff00ff; + + *dstp++ = d1 | ((d << 8) & 0xff00) | 0xff000000; + ++srcp; + + s1 = *srcp; + d1 = *dstp; + s1 &= 0xff00ff; + d1 &= 0xff00ff; + d1 += (s1 - d1) * alpha >> 8; + d1 &= 0xff00ff; + + *dstp = d1 | ((d >> 8) & 0xff00) | 0xff000000; + ++srcp; + ++dstp; + }, width); + srcp += srcskip; + dstp += dstskip; + } + } +} + +/* fast ARGB888->(A)RGB888 blending with pixel alpha */ +static void BlitRGBtoRGBPixelAlpha(SDL_BlitInfo *info) +{ + int width = info->d_width; + int height = info->d_height; + Uint32 *srcp = (Uint32 *)info->s_pixels; + int srcskip = info->s_skip >> 2; + Uint32 *dstp = (Uint32 *)info->d_pixels; + int dstskip = info->d_skip >> 2; + + while(height--) { + DUFFS_LOOP4({ + Uint32 dalpha; + Uint32 d; + Uint32 s1; + Uint32 d1; + Uint32 s = *srcp; + Uint32 alpha = s >> 24; + /* FIXME: Here we special-case opaque alpha since the + compositioning used (>>8 instead of /255) doesn't handle + it correctly. Also special-case alpha=0 for speed? + Benchmark this! */ + if(alpha) { + if(alpha == SDL_ALPHA_OPAQUE) { + *dstp = (s & 0x00ffffff) | (*dstp & 0xff000000); + } else { + /* + * take out the middle component (green), and process + * the other two in parallel. One multiply less. + */ + d = *dstp; + dalpha = d & 0xff000000; + s1 = s & 0xff00ff; + d1 = d & 0xff00ff; + d1 = (d1 + ((s1 - d1) * alpha >> 8)) & 0xff00ff; + s &= 0xff00; + d &= 0xff00; + d = (d + ((s - d) * alpha >> 8)) & 0xff00; + *dstp = d1 | d | dalpha; + } + } + ++srcp; + ++dstp; + }, width); + srcp += srcskip; + dstp += dstskip; + } +} + +#if GCC_ASMBLIT +/* fast (as in MMX with prefetch) ARGB888->(A)RGB888 blending with pixel alpha */ +static void BlitRGBtoRGBPixelAlphaMMX3DNOW(SDL_BlitInfo *info) +{ + int width = info->d_width; + int height = info->d_height; + Uint32 *srcp = (Uint32 *)info->s_pixels; + int srcskip = info->s_skip >> 2; + Uint32 *dstp = (Uint32 *)info->d_pixels; + int dstskip = info->d_skip >> 2; + SDL_PixelFormat* sf = info->src; + Uint32 amask = sf->Amask; + + __asm__ ( + /* make mm6 all zeros. */ + "pxor %%mm6, %%mm6\n" + + /* Make a mask to preserve the alpha. */ + "movd %0, %%mm7\n\t" /* 0000F000 -> mm7 */ + "punpcklbw %%mm7, %%mm7\n\t" /* FF000000 -> mm7 */ + "pcmpeqb %%mm4, %%mm4\n\t" /* FFFFFFFF -> mm4 */ + "movq %%mm4, %%mm3\n\t" /* FFFFFFFF -> mm3 (for later) */ + "pxor %%mm4, %%mm7\n\t" /* 00FFFFFF -> mm7 (mult mask) */ + + /* form channel masks */ + "movq %%mm7, %%mm4\n\t" /* 00FFFFFF -> mm4 */ + "packsswb %%mm6, %%mm4\n\t" /* 00000FFF -> mm4 (channel mask) */ + "packsswb %%mm6, %%mm3\n\t" /* 0000FFFF -> mm3 */ + "pxor %%mm4, %%mm3\n\t" /* 0000F000 -> mm3 (~channel mask) */ + + /* get alpha channel shift */ + "movd %1, %%mm5\n\t" /* Ashift -> mm5 */ + + : /* nothing */ : "rm" (amask), "rm" ((Uint32) sf->Ashift) ); + + while(height--) { + + DUFFS_LOOP4({ + Uint32 alpha; + + __asm__ ( + "prefetch 64(%0)\n" + "prefetch 64(%1)\n" + : : "r" (srcp), "r" (dstp) ); + + alpha = *srcp & amask; + /* FIXME: Here we special-case opaque alpha since the + compositioning used (>>8 instead of /255) doesn't handle + it correctly. Also special-case alpha=0 for speed? + Benchmark this! */ + if(alpha == 0) { + /* do nothing */ + } + else if(alpha == amask) { + /* opaque alpha -- copy RGB, keep dst alpha */ + /* using MMX here to free up regular registers for other things */ + __asm__ ( + "movd (%0), %%mm0\n\t" /* src(ARGB) -> mm0 (0000ARGB)*/ + "movd (%1), %%mm1\n\t" /* dst(ARGB) -> mm1 (0000ARGB)*/ + "pand %%mm4, %%mm0\n\t" /* src & chanmask -> mm0 */ + "pand %%mm3, %%mm1\n\t" /* dst & ~chanmask -> mm2 */ + "por %%mm0, %%mm1\n\t" /* src | dst -> mm1 */ + "movd %%mm1, (%1) \n\t" /* mm1 -> dst */ + + : : "r" (srcp), "r" (dstp) ); + } + + else { + __asm__ ( + /* load in the source, and dst. */ + "movd (%0), %%mm0\n" /* mm0(s) = 0 0 0 0 | As Rs Gs Bs */ + "movd (%1), %%mm1\n" /* mm1(d) = 0 0 0 0 | Ad Rd Gd Bd */ + + /* Move the src alpha into mm2 */ + + /* if supporting pshufw */ + /*"pshufw $0x55, %%mm0, %%mm2\n" */ /* mm2 = 0 As 0 As | 0 As 0 As */ + /*"psrlw $8, %%mm2\n" */ + + /* else: */ + "movd %2, %%mm2\n" + "psrld %%mm5, %%mm2\n" /* mm2 = 0 0 0 0 | 0 0 0 As */ + "punpcklwd %%mm2, %%mm2\n" /* mm2 = 0 0 0 0 | 0 As 0 As */ + "punpckldq %%mm2, %%mm2\n" /* mm2 = 0 As 0 As | 0 As 0 As */ + "pand %%mm7, %%mm2\n" /* to preserve dest alpha */ + + /* move the colors into words. */ + "punpcklbw %%mm6, %%mm0\n" /* mm0 = 0 As 0 Rs | 0 Gs 0 Bs */ + "punpcklbw %%mm6, %%mm1\n" /* mm0 = 0 Ad 0 Rd | 0 Gd 0 Bd */ + + /* src - dst */ + "psubw %%mm1, %%mm0\n" /* mm0 = As-Ad Rs-Rd | Gs-Gd Bs-Bd */ + + /* A * (src-dst) */ + "pmullw %%mm2, %%mm0\n" /* mm0 = 0*As-d As*Rs-d | As*Gs-d As*Bs-d */ + "psrlw $8, %%mm0\n" /* mm0 = 0>>8 Rc>>8 | Gc>>8 Bc>>8 */ + "paddb %%mm1, %%mm0\n" /* mm0 = 0+Ad Rc+Rd | Gc+Gd Bc+Bd */ + + "packuswb %%mm0, %%mm0\n" /* mm0 = | Ac Rc Gc Bc */ + + "movd %%mm0, (%1)\n" /* result in mm0 */ + + : : "r" (srcp), "r" (dstp), "r" (alpha) ); + + } + ++srcp; + ++dstp; + }, width); + srcp += srcskip; + dstp += dstskip; + } + + __asm__ ( + "emms\n" + : ); +} +/* End GCC_ASMBLIT*/ + +#elif MSVC_ASMBLIT +/* fast (as in MMX with prefetch) ARGB888->(A)RGB888 blending with pixel alpha */ +static void BlitRGBtoRGBPixelAlphaMMX3DNOW(SDL_BlitInfo *info) +{ + int width = info->d_width; + int height = info->d_height; + Uint32 *srcp = (Uint32 *)info->s_pixels; + int srcskip = info->s_skip >> 2; + Uint32 *dstp = (Uint32 *)info->d_pixels; + int dstskip = info->d_skip >> 2; + SDL_PixelFormat* sf = info->src; + Uint32 chanmask = sf->Rmask | sf->Gmask | sf->Bmask; + Uint32 amask = sf->Amask; + Uint32 ashift = sf->Ashift; + Uint64 multmask; + + __m64 src1, dst1, mm_alpha, mm_zero, dmask; + + mm_zero = _mm_setzero_si64(); /* 0 -> mm_zero */ + multmask = ~(0xFFFFi64 << (ashift * 2)); + dmask = *(__m64*) &multmask; /* dst alpha mask -> dmask */ + + while(height--) { + DUFFS_LOOP4({ + Uint32 alpha; + + _m_prefetch(srcp + 16); + _m_prefetch(dstp + 16); + + alpha = *srcp & amask; + if (alpha == 0) { + /* do nothing */ + } else if (alpha == amask) { + /* copy RGB, keep dst alpha */ + *dstp = (*srcp & chanmask) | (*dstp & ~chanmask); + } else { + src1 = _mm_cvtsi32_si64(*srcp); /* src(ARGB) -> src1 (0000ARGB)*/ + src1 = _mm_unpacklo_pi8(src1, mm_zero); /* 0A0R0G0B -> src1 */ + + dst1 = _mm_cvtsi32_si64(*dstp); /* dst(ARGB) -> dst1 (0000ARGB)*/ + dst1 = _mm_unpacklo_pi8(dst1, mm_zero); /* 0A0R0G0B -> dst1 */ + + mm_alpha = _mm_cvtsi32_si64(alpha); /* alpha -> mm_alpha (0000000A) */ + mm_alpha = _mm_srli_si64(mm_alpha, ashift); /* mm_alpha >> ashift -> mm_alpha(0000000A) */ + mm_alpha = _mm_unpacklo_pi16(mm_alpha, mm_alpha); /* 00000A0A -> mm_alpha */ + mm_alpha = _mm_unpacklo_pi32(mm_alpha, mm_alpha); /* 0A0A0A0A -> mm_alpha */ + mm_alpha = _mm_and_si64(mm_alpha, dmask); /* 000A0A0A -> mm_alpha, preserve dst alpha on add */ + + /* blend */ + src1 = _mm_sub_pi16(src1, dst1);/* src - dst -> src1 */ + src1 = _mm_mullo_pi16(src1, mm_alpha); /* (src - dst) * alpha -> src1 */ + src1 = _mm_srli_pi16(src1, 8); /* src1 >> 8 -> src1(000R0G0B) */ + dst1 = _mm_add_pi8(src1, dst1); /* src1 + dst1(dst) -> dst1(0A0R0G0B) */ + dst1 = _mm_packs_pu16(dst1, mm_zero); /* 0000ARGB -> dst1 */ + + *dstp = _mm_cvtsi64_si32(dst1); /* dst1 -> pixel */ + } + ++srcp; + ++dstp; + }, width); + srcp += srcskip; + dstp += dstskip; + } + _mm_empty(); +} +/* End MSVC_ASMBLIT */ + +#endif /* GCC_ASMBLIT, MSVC_ASMBLIT */ + +/* 16bpp special case for per-surface alpha=50%: blend 2 pixels in parallel */ + +/* blend a single 16 bit pixel at 50% */ +#define BLEND16_50(d, s, mask) \ + ((((s & mask) + (d & mask)) >> 1) + (s & d & (~mask & 0xffff))) + +/* blend two 16 bit pixels at 50% */ +#define BLEND2x16_50(d, s, mask) \ + (((s & (mask | mask << 16)) >> 1) + ((d & (mask | mask << 16)) >> 1) \ + + (s & d & (~(mask | mask << 16)))) + +static void Blit16to16SurfaceAlpha128(SDL_BlitInfo *info, Uint16 mask) +{ + int width = info->d_width; + int height = info->d_height; + Uint16 *srcp = (Uint16 *)info->s_pixels; + int srcskip = info->s_skip >> 1; + Uint16 *dstp = (Uint16 *)info->d_pixels; + int dstskip = info->d_skip >> 1; + + while(height--) { + if(((uintptr_t)srcp ^ (uintptr_t)dstp) & 2) { + /* + * Source and destination not aligned, pipeline it. + * This is mostly a win for big blits but no loss for + * small ones + */ + Uint32 prev_sw; + int w = width; + + /* handle odd destination */ + if((uintptr_t)dstp & 2) { + Uint16 d = *dstp, s = *srcp; + *dstp = BLEND16_50(d, s, mask); + dstp++; + srcp++; + w--; + } + srcp++; /* srcp is now 32-bit aligned */ + + /* bootstrap pipeline with first halfword */ + prev_sw = ((Uint32 *)srcp)[-1]; + + while(w > 1) { + Uint32 sw, dw, s; + sw = *(Uint32 *)srcp; + dw = *(Uint32 *)dstp; +#if SDL_BYTEORDER == SDL_BIG_ENDIAN + s = (prev_sw << 16) + (sw >> 16); +#else + s = (prev_sw >> 16) + (sw << 16); +#endif + prev_sw = sw; + *(Uint32 *)dstp = BLEND2x16_50(dw, s, mask); + dstp += 2; + srcp += 2; + w -= 2; + } + + /* final pixel if any */ + if(w) { + Uint16 d = *dstp, s; +#if SDL_BYTEORDER == SDL_BIG_ENDIAN + s = (Uint16)prev_sw; +#else + s = (Uint16)(prev_sw >> 16); +#endif + *dstp = BLEND16_50(d, s, mask); + srcp++; + dstp++; + } + srcp += srcskip - 1; + dstp += dstskip; + } else { + /* source and destination are aligned */ + int w = width; + + /* first odd pixel? */ + if((uintptr_t)srcp & 2) { + Uint16 d = *dstp, s = *srcp; + *dstp = BLEND16_50(d, s, mask); + srcp++; + dstp++; + w--; + } + /* srcp and dstp are now 32-bit aligned */ + + while(w > 1) { + Uint32 sw = *(Uint32 *)srcp; + Uint32 dw = *(Uint32 *)dstp; + *(Uint32 *)dstp = BLEND2x16_50(dw, sw, mask); + srcp += 2; + dstp += 2; + w -= 2; + } + + /* last odd pixel? */ + if(w) { + Uint16 d = *dstp, s = *srcp; + *dstp = BLEND16_50(d, s, mask); + srcp++; + dstp++; + } + srcp += srcskip; + dstp += dstskip; + } + } +} + +#if GCC_ASMBLIT +/* fast RGB565->RGB565 blending with surface alpha */ +static void Blit565to565SurfaceAlphaMMX(SDL_BlitInfo *info) +{ + unsigned alpha = info->src->alpha; /* downscale alpha to 5 bits */ + if(alpha == 128) { + Blit16to16SurfaceAlpha128(info, 0xf7de); + } else { + int width = info->d_width; + int height = info->d_height; + Uint16 *srcp = (Uint16 *)info->s_pixels; + int srcskip = info->s_skip >> 1; + Uint16 *dstp = (Uint16 *)info->d_pixels; + int dstskip = info->d_skip >> 1; + Uint32 s, d; + Uint64 load; + + alpha &= ~(1+2+4); /* cut alpha to get the exact same behaviour */ + load = alpha; + alpha >>= 3; /* downscale alpha to 5 bits */ + + movq_m2r(load, mm0); /* alpha(0000000A) -> mm0 */ + punpcklwd_r2r(mm0, mm0); /* 00000A0A -> mm0 */ + punpcklwd_r2r(mm0, mm0); /* 0A0A0A0A -> mm0 */ + /* position alpha to allow for mullo and mulhi on diff channels + to reduce the number of operations */ + psllq_i2r(3, mm0); + + /* Setup the 565 color channel masks */ + load = 0x07E007E007E007E0ULL; + movq_m2r(load, mm4); /* MASKGREEN -> mm4 */ + load = 0x001F001F001F001FULL; + movq_m2r(load, mm7); /* MASKBLUE -> mm7 */ + while(height--) { + DUFFS_LOOP_QUATRO2( + { + s = *srcp++; + d = *dstp; + /* + * shift out the middle component (green) to + * the high 16 bits, and process all three RGB + * components at the same time. + */ + s = (s | s << 16) & 0x07e0f81f; + d = (d | d << 16) & 0x07e0f81f; + d += (s - d) * alpha >> 5; + d &= 0x07e0f81f; + *dstp++ = d | d >> 16; + },{ + s = *srcp++; + d = *dstp; + /* + * shift out the middle component (green) to + * the high 16 bits, and process all three RGB + * components at the same time. + */ + s = (s | s << 16) & 0x07e0f81f; + d = (d | d << 16) & 0x07e0f81f; + d += (s - d) * alpha >> 5; + d &= 0x07e0f81f; + *dstp++ = d | d >> 16; + s = *srcp++; + d = *dstp; + /* + * shift out the middle component (green) to + * the high 16 bits, and process all three RGB + * components at the same time. + */ + s = (s | s << 16) & 0x07e0f81f; + d = (d | d << 16) & 0x07e0f81f; + d += (s - d) * alpha >> 5; + d &= 0x07e0f81f; + *dstp++ = d | d >> 16; + },{ + movq_m2r((*srcp), mm2);/* 4 src pixels -> mm2 */ + movq_m2r((*dstp), mm3);/* 4 dst pixels -> mm3 */ + + /* red -- does not need a mask since the right shift clears + the uninteresting bits */ + movq_r2r(mm2, mm5); /* src -> mm5 */ + movq_r2r(mm3, mm6); /* dst -> mm6 */ + psrlw_i2r(11, mm5); /* mm5 >> 11 -> mm5 [000r 000r 000r 000r] */ + psrlw_i2r(11, mm6); /* mm6 >> 11 -> mm6 [000r 000r 000r 000r] */ + + /* blend */ + psubw_r2r(mm6, mm5);/* src - dst -> mm5 */ + pmullw_r2r(mm0, mm5); /* mm5 * alpha -> mm5 */ + /* alpha used is actually 11 bits + 11 + 5 = 16 bits, so the sign bits are lost */ + psrlw_i2r(11, mm5); /* mm5 >> 11 -> mm5 */ + paddw_r2r(mm5, mm6); /* mm5 + mm6(dst) -> mm6 */ + psllw_i2r(11, mm6); /* mm6 << 11 -> mm6 */ + + movq_r2r(mm6, mm1); /* save new reds in dsts */ + + /* green -- process the bits in place */ + movq_r2r(mm2, mm5); /* src -> mm5 */ + movq_r2r(mm3, mm6); /* dst -> mm6 */ + pand_r2r(mm4, mm5); /* src & MASKGREEN -> mm5 */ + pand_r2r(mm4, mm6); /* dst & MASKGREEN -> mm6 */ + + /* blend */ + psubw_r2r(mm6, mm5);/* src - dst -> mm5 */ + pmulhw_r2r(mm0, mm5); /* mm5 * alpha -> mm5 */ + /* 11 + 11 - 16 = 6 bits, so all the lower uninteresting + bits are gone and the sign bits present */ + psllw_i2r(5, mm5); /* mm5 << 5 -> mm5 */ + paddw_r2r(mm5, mm6); /* mm5 + mm6(dst) -> mm6 */ + + por_r2r(mm6, mm1); /* save new greens in dsts */ + + /* blue */ + movq_r2r(mm2, mm5); /* src -> mm5 */ + movq_r2r(mm3, mm6); /* dst -> mm6 */ + pand_r2r(mm7, mm5); /* src & MASKBLUE -> mm5[000b 000b 000b 000b] */ + pand_r2r(mm7, mm6); /* dst & MASKBLUE -> mm6[000b 000b 000b 000b] */ + + /* blend */ + psubw_r2r(mm6, mm5);/* src - dst -> mm5 */ + pmullw_r2r(mm0, mm5); /* mm5 * alpha -> mm5 */ + /* 11 + 5 = 16 bits, so the sign bits are lost and + the interesting bits will need to be MASKed */ + psrlw_i2r(11, mm5); /* mm5 >> 11 -> mm5 */ + paddw_r2r(mm5, mm6); /* mm5 + mm6(dst) -> mm6 */ + pand_r2r(mm7, mm6); /* mm6 & MASKBLUE -> mm6[000b 000b 000b 000b] */ + + por_r2r(mm6, mm1); /* save new blues in dsts */ + + movq_r2m(mm1, *dstp); /* mm1 -> 4 dst pixels */ + + srcp += 4; + dstp += 4; + }, width); + srcp += srcskip; + dstp += dstskip; + } + emms(); + } +} + +/* fast RGB555->RGB555 blending with surface alpha */ +static void Blit555to555SurfaceAlphaMMX(SDL_BlitInfo *info) +{ + unsigned alpha = info->src->alpha; /* downscale alpha to 5 bits */ + if(alpha == 128) { + Blit16to16SurfaceAlpha128(info, 0xfbde); + } else { + int width = info->d_width; + int height = info->d_height; + Uint16 *srcp = (Uint16 *)info->s_pixels; + int srcskip = info->s_skip >> 1; + Uint16 *dstp = (Uint16 *)info->d_pixels; + int dstskip = info->d_skip >> 1; + Uint32 s, d; + Uint64 load; + + alpha &= ~(1+2+4); /* cut alpha to get the exact same behaviour */ + load = alpha; + alpha >>= 3; /* downscale alpha to 5 bits */ + + movq_m2r(load, mm0); /* alpha(0000000A) -> mm0 */ + punpcklwd_r2r(mm0, mm0); /* 00000A0A -> mm0 */ + punpcklwd_r2r(mm0, mm0); /* 0A0A0A0A -> mm0 */ + /* position alpha to allow for mullo and mulhi on diff channels + to reduce the number of operations */ + psllq_i2r(3, mm0); + + /* Setup the 555 color channel masks */ + load = 0x03E003E003E003E0ULL; + movq_m2r(load, mm4); /* MASKGREEN -> mm4 */ + load = 0x001F001F001F001FULL; + movq_m2r(load, mm7); /* MASKBLUE -> mm7 */ + while(height--) { + DUFFS_LOOP_QUATRO2( + { + s = *srcp++; + d = *dstp; + /* + * shift out the middle component (green) to + * the high 16 bits, and process all three RGB + * components at the same time. + */ + s = (s | s << 16) & 0x03e07c1f; + d = (d | d << 16) & 0x03e07c1f; + d += (s - d) * alpha >> 5; + d &= 0x03e07c1f; + *dstp++ = d | d >> 16; + },{ + s = *srcp++; + d = *dstp; + /* + * shift out the middle component (green) to + * the high 16 bits, and process all three RGB + * components at the same time. + */ + s = (s | s << 16) & 0x03e07c1f; + d = (d | d << 16) & 0x03e07c1f; + d += (s - d) * alpha >> 5; + d &= 0x03e07c1f; + *dstp++ = d | d >> 16; + s = *srcp++; + d = *dstp; + /* + * shift out the middle component (green) to + * the high 16 bits, and process all three RGB + * components at the same time. + */ + s = (s | s << 16) & 0x03e07c1f; + d = (d | d << 16) & 0x03e07c1f; + d += (s - d) * alpha >> 5; + d &= 0x03e07c1f; + *dstp++ = d | d >> 16; + },{ + movq_m2r((*srcp), mm2);/* 4 src pixels -> mm2 */ + movq_m2r((*dstp), mm3);/* 4 dst pixels -> mm3 */ + + /* red -- process the bits in place */ + psllq_i2r(5, mm4); /* turn MASKGREEN into MASKRED */ + /* by reusing the GREEN mask we free up another mmx + register to accumulate the result */ + + movq_r2r(mm2, mm5); /* src -> mm5 */ + movq_r2r(mm3, mm6); /* dst -> mm6 */ + pand_r2r(mm4, mm5); /* src & MASKRED -> mm5 */ + pand_r2r(mm4, mm6); /* dst & MASKRED -> mm6 */ + + /* blend */ + psubw_r2r(mm6, mm5);/* src - dst -> mm5 */ + pmulhw_r2r(mm0, mm5); /* mm5 * alpha -> mm5 */ + /* 11 + 15 - 16 = 10 bits, uninteresting bits will be + cleared by a MASK below */ + psllw_i2r(5, mm5); /* mm5 << 5 -> mm5 */ + paddw_r2r(mm5, mm6); /* mm5 + mm6(dst) -> mm6 */ + pand_r2r(mm4, mm6); /* mm6 & MASKRED -> mm6 */ + + psrlq_i2r(5, mm4); /* turn MASKRED back into MASKGREEN */ + + movq_r2r(mm6, mm1); /* save new reds in dsts */ + + /* green -- process the bits in place */ + movq_r2r(mm2, mm5); /* src -> mm5 */ + movq_r2r(mm3, mm6); /* dst -> mm6 */ + pand_r2r(mm4, mm5); /* src & MASKGREEN -> mm5 */ + pand_r2r(mm4, mm6); /* dst & MASKGREEN -> mm6 */ + + /* blend */ + psubw_r2r(mm6, mm5);/* src - dst -> mm5 */ + pmulhw_r2r(mm0, mm5); /* mm5 * alpha -> mm5 */ + /* 11 + 10 - 16 = 5 bits, so all the lower uninteresting + bits are gone and the sign bits present */ + psllw_i2r(5, mm5); /* mm5 << 5 -> mm5 */ + paddw_r2r(mm5, mm6); /* mm5 + mm6(dst) -> mm6 */ + + por_r2r(mm6, mm1); /* save new greens in dsts */ + + /* blue */ + movq_r2r(mm2, mm5); /* src -> mm5 */ + movq_r2r(mm3, mm6); /* dst -> mm6 */ + pand_r2r(mm7, mm5); /* src & MASKBLUE -> mm5[000b 000b 000b 000b] */ + pand_r2r(mm7, mm6); /* dst & MASKBLUE -> mm6[000b 000b 000b 000b] */ + + /* blend */ + psubw_r2r(mm6, mm5);/* src - dst -> mm5 */ + pmullw_r2r(mm0, mm5); /* mm5 * alpha -> mm5 */ + /* 11 + 5 = 16 bits, so the sign bits are lost and + the interesting bits will need to be MASKed */ + psrlw_i2r(11, mm5); /* mm5 >> 11 -> mm5 */ + paddw_r2r(mm5, mm6); /* mm5 + mm6(dst) -> mm6 */ + pand_r2r(mm7, mm6); /* mm6 & MASKBLUE -> mm6[000b 000b 000b 000b] */ + + por_r2r(mm6, mm1); /* save new blues in dsts */ + + movq_r2m(mm1, *dstp);/* mm1 -> 4 dst pixels */ + + srcp += 4; + dstp += 4; + }, width); + srcp += srcskip; + dstp += dstskip; + } + emms(); + } +} +/* End GCC_ASMBLIT */ + +#elif MSVC_ASMBLIT +/* fast RGB565->RGB565 blending with surface alpha */ +static void Blit565to565SurfaceAlphaMMX(SDL_BlitInfo *info) +{ + unsigned alpha = info->src->alpha; + if(alpha == 128) { + Blit16to16SurfaceAlpha128(info, 0xf7de); + } else { + int width = info->d_width; + int height = info->d_height; + Uint16 *srcp = (Uint16 *)info->s_pixels; + int srcskip = info->s_skip >> 1; + Uint16 *dstp = (Uint16 *)info->d_pixels; + int dstskip = info->d_skip >> 1; + Uint32 s, d; + + __m64 src1, dst1, src2, dst2, gmask, bmask, mm_res, mm_alpha; + + alpha &= ~(1+2+4); /* cut alpha to get the exact same behaviour */ + mm_alpha = _mm_set_pi32(0, alpha); /* 0000000A -> mm_alpha */ + alpha >>= 3; /* downscale alpha to 5 bits */ + + mm_alpha = _mm_unpacklo_pi16(mm_alpha, mm_alpha); /* 00000A0A -> mm_alpha */ + mm_alpha = _mm_unpacklo_pi32(mm_alpha, mm_alpha); /* 0A0A0A0A -> mm_alpha */ + /* position alpha to allow for mullo and mulhi on diff channels + to reduce the number of operations */ + mm_alpha = _mm_slli_si64(mm_alpha, 3); + + /* Setup the 565 color channel masks */ + gmask = _mm_set_pi32(0x07E007E0, 0x07E007E0); /* MASKGREEN -> gmask */ + bmask = _mm_set_pi32(0x001F001F, 0x001F001F); /* MASKBLUE -> bmask */ + + while(height--) { + DUFFS_LOOP_QUATRO2( + { + s = *srcp++; + d = *dstp; + /* + * shift out the middle component (green) to + * the high 16 bits, and process all three RGB + * components at the same time. + */ + s = (s | s << 16) & 0x07e0f81f; + d = (d | d << 16) & 0x07e0f81f; + d += (s - d) * alpha >> 5; + d &= 0x07e0f81f; + *dstp++ = (Uint16)(d | d >> 16); + },{ + s = *srcp++; + d = *dstp; + /* + * shift out the middle component (green) to + * the high 16 bits, and process all three RGB + * components at the same time. + */ + s = (s | s << 16) & 0x07e0f81f; + d = (d | d << 16) & 0x07e0f81f; + d += (s - d) * alpha >> 5; + d &= 0x07e0f81f; + *dstp++ = (Uint16)(d | d >> 16); + s = *srcp++; + d = *dstp; + /* + * shift out the middle component (green) to + * the high 16 bits, and process all three RGB + * components at the same time. + */ + s = (s | s << 16) & 0x07e0f81f; + d = (d | d << 16) & 0x07e0f81f; + d += (s - d) * alpha >> 5; + d &= 0x07e0f81f; + *dstp++ = (Uint16)(d | d >> 16); + },{ + src1 = *(__m64*)srcp; /* 4 src pixels -> src1 */ + dst1 = *(__m64*)dstp; /* 4 dst pixels -> dst1 */ + + /* red */ + src2 = src1; + src2 = _mm_srli_pi16(src2, 11); /* src2 >> 11 -> src2 [000r 000r 000r 000r] */ + + dst2 = dst1; + dst2 = _mm_srli_pi16(dst2, 11); /* dst2 >> 11 -> dst2 [000r 000r 000r 000r] */ + + /* blend */ + src2 = _mm_sub_pi16(src2, dst2);/* src - dst -> src2 */ + src2 = _mm_mullo_pi16(src2, mm_alpha); /* src2 * alpha -> src2 */ + src2 = _mm_srli_pi16(src2, 11); /* src2 >> 11 -> src2 */ + dst2 = _mm_add_pi16(src2, dst2); /* src2 + dst2 -> dst2 */ + dst2 = _mm_slli_pi16(dst2, 11); /* dst2 << 11 -> dst2 */ + + mm_res = dst2; /* RED -> mm_res */ + + /* green -- process the bits in place */ + src2 = src1; + src2 = _mm_and_si64(src2, gmask); /* src & MASKGREEN -> src2 */ + + dst2 = dst1; + dst2 = _mm_and_si64(dst2, gmask); /* dst & MASKGREEN -> dst2 */ + + /* blend */ + src2 = _mm_sub_pi16(src2, dst2);/* src - dst -> src2 */ + src2 = _mm_mulhi_pi16(src2, mm_alpha); /* src2 * alpha -> src2 */ + src2 = _mm_slli_pi16(src2, 5); /* src2 << 5 -> src2 */ + dst2 = _mm_add_pi16(src2, dst2); /* src2 + dst2 -> dst2 */ + + mm_res = _mm_or_si64(mm_res, dst2); /* RED | GREEN -> mm_res */ + + /* blue */ + src2 = src1; + src2 = _mm_and_si64(src2, bmask); /* src & MASKBLUE -> src2[000b 000b 000b 000b] */ + + dst2 = dst1; + dst2 = _mm_and_si64(dst2, bmask); /* dst & MASKBLUE -> dst2[000b 000b 000b 000b] */ + + /* blend */ + src2 = _mm_sub_pi16(src2, dst2);/* src - dst -> src2 */ + src2 = _mm_mullo_pi16(src2, mm_alpha); /* src2 * alpha -> src2 */ + src2 = _mm_srli_pi16(src2, 11); /* src2 >> 11 -> src2 */ + dst2 = _mm_add_pi16(src2, dst2); /* src2 + dst2 -> dst2 */ + dst2 = _mm_and_si64(dst2, bmask); /* dst2 & MASKBLUE -> dst2 */ + + mm_res = _mm_or_si64(mm_res, dst2); /* RED | GREEN | BLUE -> mm_res */ + + *(__m64*)dstp = mm_res; /* mm_res -> 4 dst pixels */ + + srcp += 4; + dstp += 4; + }, width); + srcp += srcskip; + dstp += dstskip; + } + _mm_empty(); + } +} + +/* fast RGB555->RGB555 blending with surface alpha */ +static void Blit555to555SurfaceAlphaMMX(SDL_BlitInfo *info) +{ + unsigned alpha = info->src->alpha; + if(alpha == 128) { + Blit16to16SurfaceAlpha128(info, 0xfbde); + } else { + int width = info->d_width; + int height = info->d_height; + Uint16 *srcp = (Uint16 *)info->s_pixels; + int srcskip = info->s_skip >> 1; + Uint16 *dstp = (Uint16 *)info->d_pixels; + int dstskip = info->d_skip >> 1; + Uint32 s, d; + + __m64 src1, dst1, src2, dst2, rmask, gmask, bmask, mm_res, mm_alpha; + + alpha &= ~(1+2+4); /* cut alpha to get the exact same behaviour */ + mm_alpha = _mm_set_pi32(0, alpha); /* 0000000A -> mm_alpha */ + alpha >>= 3; /* downscale alpha to 5 bits */ + + mm_alpha = _mm_unpacklo_pi16(mm_alpha, mm_alpha); /* 00000A0A -> mm_alpha */ + mm_alpha = _mm_unpacklo_pi32(mm_alpha, mm_alpha); /* 0A0A0A0A -> mm_alpha */ + /* position alpha to allow for mullo and mulhi on diff channels + to reduce the number of operations */ + mm_alpha = _mm_slli_si64(mm_alpha, 3); + + /* Setup the 555 color channel masks */ + rmask = _mm_set_pi32(0x7C007C00, 0x7C007C00); /* MASKRED -> rmask */ + gmask = _mm_set_pi32(0x03E003E0, 0x03E003E0); /* MASKGREEN -> gmask */ + bmask = _mm_set_pi32(0x001F001F, 0x001F001F); /* MASKBLUE -> bmask */ + + while(height--) { + DUFFS_LOOP_QUATRO2( + { + s = *srcp++; + d = *dstp; + /* + * shift out the middle component (green) to + * the high 16 bits, and process all three RGB + * components at the same time. + */ + s = (s | s << 16) & 0x03e07c1f; + d = (d | d << 16) & 0x03e07c1f; + d += (s - d) * alpha >> 5; + d &= 0x03e07c1f; + *dstp++ = (Uint16)(d | d >> 16); + },{ + s = *srcp++; + d = *dstp; + /* + * shift out the middle component (green) to + * the high 16 bits, and process all three RGB + * components at the same time. + */ + s = (s | s << 16) & 0x03e07c1f; + d = (d | d << 16) & 0x03e07c1f; + d += (s - d) * alpha >> 5; + d &= 0x03e07c1f; + *dstp++ = (Uint16)(d | d >> 16); + s = *srcp++; + d = *dstp; + /* + * shift out the middle component (green) to + * the high 16 bits, and process all three RGB + * components at the same time. + */ + s = (s | s << 16) & 0x03e07c1f; + d = (d | d << 16) & 0x03e07c1f; + d += (s - d) * alpha >> 5; + d &= 0x03e07c1f; + *dstp++ = (Uint16)(d | d >> 16); + },{ + src1 = *(__m64*)srcp; /* 4 src pixels -> src1 */ + dst1 = *(__m64*)dstp; /* 4 dst pixels -> dst1 */ + + /* red -- process the bits in place */ + src2 = src1; + src2 = _mm_and_si64(src2, rmask); /* src & MASKRED -> src2 */ + + dst2 = dst1; + dst2 = _mm_and_si64(dst2, rmask); /* dst & MASKRED -> dst2 */ + + /* blend */ + src2 = _mm_sub_pi16(src2, dst2);/* src - dst -> src2 */ + src2 = _mm_mulhi_pi16(src2, mm_alpha); /* src2 * alpha -> src2 */ + src2 = _mm_slli_pi16(src2, 5); /* src2 << 5 -> src2 */ + dst2 = _mm_add_pi16(src2, dst2); /* src2 + dst2 -> dst2 */ + dst2 = _mm_and_si64(dst2, rmask); /* dst2 & MASKRED -> dst2 */ + + mm_res = dst2; /* RED -> mm_res */ + + /* green -- process the bits in place */ + src2 = src1; + src2 = _mm_and_si64(src2, gmask); /* src & MASKGREEN -> src2 */ + + dst2 = dst1; + dst2 = _mm_and_si64(dst2, gmask); /* dst & MASKGREEN -> dst2 */ + + /* blend */ + src2 = _mm_sub_pi16(src2, dst2);/* src - dst -> src2 */ + src2 = _mm_mulhi_pi16(src2, mm_alpha); /* src2 * alpha -> src2 */ + src2 = _mm_slli_pi16(src2, 5); /* src2 << 5 -> src2 */ + dst2 = _mm_add_pi16(src2, dst2); /* src2 + dst2 -> dst2 */ + + mm_res = _mm_or_si64(mm_res, dst2); /* RED | GREEN -> mm_res */ + + /* blue */ + src2 = src1; /* src -> src2 */ + src2 = _mm_and_si64(src2, bmask); /* src & MASKBLUE -> src2[000b 000b 000b 000b] */ + + dst2 = dst1; /* dst -> dst2 */ + dst2 = _mm_and_si64(dst2, bmask); /* dst & MASKBLUE -> dst2[000b 000b 000b 000b] */ + + /* blend */ + src2 = _mm_sub_pi16(src2, dst2);/* src - dst -> src2 */ + src2 = _mm_mullo_pi16(src2, mm_alpha); /* src2 * alpha -> src2 */ + src2 = _mm_srli_pi16(src2, 11); /* src2 >> 11 -> src2 */ + dst2 = _mm_add_pi16(src2, dst2); /* src2 + dst2 -> dst2 */ + dst2 = _mm_and_si64(dst2, bmask); /* dst2 & MASKBLUE -> dst2 */ + + mm_res = _mm_or_si64(mm_res, dst2); /* RED | GREEN | BLUE -> mm_res */ + + *(__m64*)dstp = mm_res; /* mm_res -> 4 dst pixels */ + + srcp += 4; + dstp += 4; + }, width); + srcp += srcskip; + dstp += dstskip; + } + _mm_empty(); + } +} +#endif /* GCC_ASMBLIT, MSVC_ASMBLIT */ + +/* fast RGB565->RGB565 blending with surface alpha */ +static void Blit565to565SurfaceAlpha(SDL_BlitInfo *info) +{ + unsigned alpha = info->src->alpha; + if(alpha == 128) { + Blit16to16SurfaceAlpha128(info, 0xf7de); + } else { + int width = info->d_width; + int height = info->d_height; + Uint16 *srcp = (Uint16 *)info->s_pixels; + int srcskip = info->s_skip >> 1; + Uint16 *dstp = (Uint16 *)info->d_pixels; + int dstskip = info->d_skip >> 1; + alpha >>= 3; /* downscale alpha to 5 bits */ + + while(height--) { + DUFFS_LOOP4({ + Uint32 s = *srcp++; + Uint32 d = *dstp; + /* + * shift out the middle component (green) to + * the high 16 bits, and process all three RGB + * components at the same time. + */ + s = (s | s << 16) & 0x07e0f81f; + d = (d | d << 16) & 0x07e0f81f; + d += (s - d) * alpha >> 5; + d &= 0x07e0f81f; + *dstp++ = (Uint16)(d | d >> 16); + }, width); + srcp += srcskip; + dstp += dstskip; + } + } +} + +/* fast RGB555->RGB555 blending with surface alpha */ +static void Blit555to555SurfaceAlpha(SDL_BlitInfo *info) +{ + unsigned alpha = info->src->alpha; /* downscale alpha to 5 bits */ + if(alpha == 128) { + Blit16to16SurfaceAlpha128(info, 0xfbde); + } else { + int width = info->d_width; + int height = info->d_height; + Uint16 *srcp = (Uint16 *)info->s_pixels; + int srcskip = info->s_skip >> 1; + Uint16 *dstp = (Uint16 *)info->d_pixels; + int dstskip = info->d_skip >> 1; + alpha >>= 3; /* downscale alpha to 5 bits */ + + while(height--) { + DUFFS_LOOP4({ + Uint32 s = *srcp++; + Uint32 d = *dstp; + /* + * shift out the middle component (green) to + * the high 16 bits, and process all three RGB + * components at the same time. + */ + s = (s | s << 16) & 0x03e07c1f; + d = (d | d << 16) & 0x03e07c1f; + d += (s - d) * alpha >> 5; + d &= 0x03e07c1f; + *dstp++ = (Uint16)(d | d >> 16); + }, width); + srcp += srcskip; + dstp += dstskip; + } + } +} + +/* fast ARGB8888->RGB565 blending with pixel alpha */ +static void BlitARGBto565PixelAlpha(SDL_BlitInfo *info) +{ + int width = info->d_width; + int height = info->d_height; + Uint32 *srcp = (Uint32 *)info->s_pixels; + int srcskip = info->s_skip >> 2; + Uint16 *dstp = (Uint16 *)info->d_pixels; + int dstskip = info->d_skip >> 1; + + while(height--) { + DUFFS_LOOP4({ + Uint32 s = *srcp; + unsigned alpha = s >> 27; /* downscale alpha to 5 bits */ + /* FIXME: Here we special-case opaque alpha since the + compositioning used (>>8 instead of /255) doesn't handle + it correctly. Also special-case alpha=0 for speed? + Benchmark this! */ + if(alpha) { + if(alpha == (SDL_ALPHA_OPAQUE >> 3)) { + *dstp = (Uint16)((s >> 8 & 0xf800) + (s >> 5 & 0x7e0) + (s >> 3 & 0x1f)); + } else { + Uint32 d = *dstp; + /* + * convert source and destination to G0RAB65565 + * and blend all components at the same time + */ + s = ((s & 0xfc00) << 11) + (s >> 8 & 0xf800) + + (s >> 3 & 0x1f); + d = (d | d << 16) & 0x07e0f81f; + d += (s - d) * alpha >> 5; + d &= 0x07e0f81f; + *dstp = (Uint16)(d | d >> 16); + } + } + srcp++; + dstp++; + }, width); + srcp += srcskip; + dstp += dstskip; + } +} + +/* fast ARGB8888->RGB555 blending with pixel alpha */ +static void BlitARGBto555PixelAlpha(SDL_BlitInfo *info) +{ + int width = info->d_width; + int height = info->d_height; + Uint32 *srcp = (Uint32 *)info->s_pixels; + int srcskip = info->s_skip >> 2; + Uint16 *dstp = (Uint16 *)info->d_pixels; + int dstskip = info->d_skip >> 1; + + while(height--) { + DUFFS_LOOP4({ + unsigned alpha; + Uint32 s = *srcp; + alpha = s >> 27; /* downscale alpha to 5 bits */ + /* FIXME: Here we special-case opaque alpha since the + compositioning used (>>8 instead of /255) doesn't handle + it correctly. Also special-case alpha=0 for speed? + Benchmark this! */ + if(alpha) { + if(alpha == (SDL_ALPHA_OPAQUE >> 3)) { + *dstp = (Uint16)((s >> 9 & 0x7c00) + (s >> 6 & 0x3e0) + (s >> 3 & 0x1f)); + } else { + Uint32 d = *dstp; + /* + * convert source and destination to G0RAB65565 + * and blend all components at the same time + */ + s = ((s & 0xf800) << 10) + (s >> 9 & 0x7c00) + + (s >> 3 & 0x1f); + d = (d | d << 16) & 0x03e07c1f; + d += (s - d) * alpha >> 5; + d &= 0x03e07c1f; + *dstp = (Uint16)(d | d >> 16); + } + } + srcp++; + dstp++; + }, width); + srcp += srcskip; + dstp += dstskip; + } +} + +/* General (slow) N->N blending with per-surface alpha */ +static void BlitNtoNSurfaceAlpha(SDL_BlitInfo *info) +{ + int width = info->d_width; + int height = info->d_height; + Uint8 *src = info->s_pixels; + int srcskip = info->s_skip; + Uint8 *dst = info->d_pixels; + int dstskip = info->d_skip; + SDL_PixelFormat *srcfmt = info->src; + SDL_PixelFormat *dstfmt = info->dst; + int srcbpp = srcfmt->BytesPerPixel; + int dstbpp = dstfmt->BytesPerPixel; + unsigned sA = srcfmt->alpha; + unsigned dA = dstfmt->Amask ? SDL_ALPHA_OPAQUE : 0; + + if(sA) { + while ( height-- ) { + DUFFS_LOOP4( + { + Uint32 Pixel; + unsigned sR; + unsigned sG; + unsigned sB; + unsigned dR; + unsigned dG; + unsigned dB; + DISEMBLE_RGB(src, srcbpp, srcfmt, Pixel, sR, sG, sB); + DISEMBLE_RGB(dst, dstbpp, dstfmt, Pixel, dR, dG, dB); + ALPHA_BLEND(sR, sG, sB, sA, dR, dG, dB); + ASSEMBLE_RGBA(dst, dstbpp, dstfmt, dR, dG, dB, dA); + src += srcbpp; + dst += dstbpp; + }, + width); + src += srcskip; + dst += dstskip; + } + } +} + +/* General (slow) colorkeyed N->N blending with per-surface alpha */ +static void BlitNtoNSurfaceAlphaKey(SDL_BlitInfo *info) +{ + int width = info->d_width; + int height = info->d_height; + Uint8 *src = info->s_pixels; + int srcskip = info->s_skip; + Uint8 *dst = info->d_pixels; + int dstskip = info->d_skip; + SDL_PixelFormat *srcfmt = info->src; + SDL_PixelFormat *dstfmt = info->dst; + Uint32 ckey = srcfmt->colorkey; + int srcbpp = srcfmt->BytesPerPixel; + int dstbpp = dstfmt->BytesPerPixel; + unsigned sA = srcfmt->alpha; + unsigned dA = dstfmt->Amask ? SDL_ALPHA_OPAQUE : 0; + + while ( height-- ) { + DUFFS_LOOP4( + { + Uint32 Pixel; + unsigned sR; + unsigned sG; + unsigned sB; + unsigned dR; + unsigned dG; + unsigned dB; + RETRIEVE_RGB_PIXEL(src, srcbpp, Pixel); + if(sA && Pixel != ckey) { + RGB_FROM_PIXEL(Pixel, srcfmt, sR, sG, sB); + DISEMBLE_RGB(dst, dstbpp, dstfmt, Pixel, dR, dG, dB); + ALPHA_BLEND(sR, sG, sB, sA, dR, dG, dB); + ASSEMBLE_RGBA(dst, dstbpp, dstfmt, dR, dG, dB, dA); + } + src += srcbpp; + dst += dstbpp; + }, + width); + src += srcskip; + dst += dstskip; + } +} + +/* General (slow) N->N blending with pixel alpha */ +static void BlitNtoNPixelAlpha(SDL_BlitInfo *info) +{ + int width = info->d_width; + int height = info->d_height; + Uint8 *src = info->s_pixels; + int srcskip = info->s_skip; + Uint8 *dst = info->d_pixels; + int dstskip = info->d_skip; + SDL_PixelFormat *srcfmt = info->src; + SDL_PixelFormat *dstfmt = info->dst; + + int srcbpp; + int dstbpp; + + /* Set up some basic variables */ + srcbpp = srcfmt->BytesPerPixel; + dstbpp = dstfmt->BytesPerPixel; + + /* FIXME: for 8bpp source alpha, this doesn't get opaque values + quite right. for <8bpp source alpha, it gets them very wrong + (check all macros!) + It is unclear whether there is a good general solution that doesn't + need a branch (or a divide). */ + while ( height-- ) { + DUFFS_LOOP4( + { + Uint32 Pixel; + unsigned sR; + unsigned sG; + unsigned sB; + unsigned dR; + unsigned dG; + unsigned dB; + unsigned sA; + unsigned dA; + DISEMBLE_RGBA(src, srcbpp, srcfmt, Pixel, sR, sG, sB, sA); + if(sA) { + DISEMBLE_RGBA(dst, dstbpp, dstfmt, Pixel, dR, dG, dB, dA); + ALPHA_BLEND(sR, sG, sB, sA, dR, dG, dB); + ASSEMBLE_RGBA(dst, dstbpp, dstfmt, dR, dG, dB, dA); + } + src += srcbpp; + dst += dstbpp; + }, + width); + src += srcskip; + dst += dstskip; + } +} + + +SDL_loblit SDL_CalculateAlphaBlit(SDL_Surface *surface, int blit_index) +{ + SDL_PixelFormat *sf = surface->format; + SDL_PixelFormat *df = surface->map->dst->format; + + if(sf->Amask == 0) { + if((surface->flags & SDL_SRCCOLORKEY) == SDL_SRCCOLORKEY) { + if(df->BytesPerPixel == 1) + return BlitNto1SurfaceAlphaKey; + else +#if SDL_ALTIVEC_BLITTERS + if (sf->BytesPerPixel == 4 && df->BytesPerPixel == 4 && + !(surface->map->dst->flags & SDL_HWSURFACE) && SDL_HasAltiVec()) + return Blit32to32SurfaceAlphaKeyAltivec; + else +#endif + return BlitNtoNSurfaceAlphaKey; + } else { + /* Per-surface alpha blits */ + switch(df->BytesPerPixel) { + case 1: + return BlitNto1SurfaceAlpha; + + case 2: + if(surface->map->identity) { + if(df->Gmask == 0x7e0) + { +#if MMX_ASMBLIT + if(SDL_HasMMX()) + return Blit565to565SurfaceAlphaMMX; + else +#endif + return Blit565to565SurfaceAlpha; + } + else if(df->Gmask == 0x3e0) + { +#if MMX_ASMBLIT + if(SDL_HasMMX()) + return Blit555to555SurfaceAlphaMMX; + else +#endif + return Blit555to555SurfaceAlpha; + } + } + return BlitNtoNSurfaceAlpha; + + case 4: + if(sf->Rmask == df->Rmask + && sf->Gmask == df->Gmask + && sf->Bmask == df->Bmask + && sf->BytesPerPixel == 4) + { +#if MMX_ASMBLIT + if(sf->Rshift % 8 == 0 + && sf->Gshift % 8 == 0 + && sf->Bshift % 8 == 0 + && SDL_HasMMX()) + return BlitRGBtoRGBSurfaceAlphaMMX; +#endif + if((sf->Rmask | sf->Gmask | sf->Bmask) == 0xffffff) + { +#if SDL_ALTIVEC_BLITTERS + if(!(surface->map->dst->flags & SDL_HWSURFACE) + && SDL_HasAltiVec()) + return BlitRGBtoRGBSurfaceAlphaAltivec; +#endif + return BlitRGBtoRGBSurfaceAlpha; + } + } +#if SDL_ALTIVEC_BLITTERS + if((sf->BytesPerPixel == 4) && + !(surface->map->dst->flags & SDL_HWSURFACE) && SDL_HasAltiVec()) + return Blit32to32SurfaceAlphaAltivec; + else +#endif + return BlitNtoNSurfaceAlpha; + + case 3: + default: + return BlitNtoNSurfaceAlpha; + } + } + } else { + /* Per-pixel alpha blits */ + switch(df->BytesPerPixel) { + case 1: + return BlitNto1PixelAlpha; + + case 2: +#if SDL_ALTIVEC_BLITTERS + if(sf->BytesPerPixel == 4 && !(surface->map->dst->flags & SDL_HWSURFACE) && + df->Gmask == 0x7e0 && + df->Bmask == 0x1f && SDL_HasAltiVec()) + return Blit32to565PixelAlphaAltivec; + else +#endif + if(sf->BytesPerPixel == 4 && sf->Amask == 0xff000000 + && sf->Gmask == 0xff00 + && ((sf->Rmask == 0xff && df->Rmask == 0x1f) + || (sf->Bmask == 0xff && df->Bmask == 0x1f))) { + if(df->Gmask == 0x7e0) + return BlitARGBto565PixelAlpha; + else if(df->Gmask == 0x3e0) + return BlitARGBto555PixelAlpha; + } + return BlitNtoNPixelAlpha; + + case 4: + if(sf->Rmask == df->Rmask + && sf->Gmask == df->Gmask + && sf->Bmask == df->Bmask + && sf->BytesPerPixel == 4) + { +#if MMX_ASMBLIT + if(sf->Rshift % 8 == 0 + && sf->Gshift % 8 == 0 + && sf->Bshift % 8 == 0 + && sf->Ashift % 8 == 0 + && sf->Aloss == 0) + { + if(SDL_Has3DNow()) + return BlitRGBtoRGBPixelAlphaMMX3DNOW; + if(SDL_HasMMX()) + return BlitRGBtoRGBPixelAlphaMMX; + } +#endif + if(sf->Amask == 0xff000000) + { +#if SDL_ALTIVEC_BLITTERS + if(!(surface->map->dst->flags & SDL_HWSURFACE) + && SDL_HasAltiVec()) + return BlitRGBtoRGBPixelAlphaAltivec; +#endif + return BlitRGBtoRGBPixelAlpha; + } + } +#if SDL_ALTIVEC_BLITTERS + if (sf->Amask && sf->BytesPerPixel == 4 && + !(surface->map->dst->flags & SDL_HWSURFACE) && SDL_HasAltiVec()) + return Blit32to32PixelAlphaAltivec; + else +#endif + return BlitNtoNPixelAlpha; + + case 3: + default: + return BlitNtoNPixelAlpha; + } + } +} + diff --git a/3rdparty/SDL/src/video/SDL_blit_N.c b/3rdparty/SDL/src/video/SDL_blit_N.c new file mode 100644 index 0000000..858cee5 --- /dev/null +++ b/3rdparty/SDL/src/video/SDL_blit_N.c @@ -0,0 +1,2492 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#include "SDL_video.h" +#include "SDL_endian.h" +#include "SDL_cpuinfo.h" +#include "SDL_blit.h" + +/* Functions to blit from N-bit surfaces to other surfaces */ + +#if SDL_ALTIVEC_BLITTERS +#if __MWERKS__ +#pragma altivec_model on +#endif +#ifdef HAVE_ALTIVEC_H +#include <altivec.h> +#endif +#define assert(X) +#ifdef __MACOSX__ +#include <sys/sysctl.h> +static size_t GetL3CacheSize( void ) +{ + const char key[] = "hw.l3cachesize"; + u_int64_t result = 0; + size_t typeSize = sizeof( result ); + + + int err = sysctlbyname( key, &result, &typeSize, NULL, 0 ); + if( 0 != err ) return 0; + + return result; +} +#else +static size_t GetL3CacheSize( void ) +{ + /* XXX: Just guess G4 */ + return 2097152; +} +#endif /* __MACOSX__ */ + +#if (defined(__MACOSX__) && (__GNUC__ < 4)) + #define VECUINT8_LITERAL(a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p) \ + (vector unsigned char) ( a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p ) + #define VECUINT16_LITERAL(a,b,c,d,e,f,g,h) \ + (vector unsigned short) ( a,b,c,d,e,f,g,h ) +#else + #define VECUINT8_LITERAL(a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p) \ + (vector unsigned char) { a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p } + #define VECUINT16_LITERAL(a,b,c,d,e,f,g,h) \ + (vector unsigned short) { a,b,c,d,e,f,g,h } +#endif + +#define UNALIGNED_PTR(x) (((size_t) x) & 0x0000000F) +#define VSWIZZLE32(a,b,c,d) (vector unsigned char) \ + ( 0x00+a, 0x00+b, 0x00+c, 0x00+d, \ + 0x04+a, 0x04+b, 0x04+c, 0x04+d, \ + 0x08+a, 0x08+b, 0x08+c, 0x08+d, \ + 0x0C+a, 0x0C+b, 0x0C+c, 0x0C+d ) + +#define MAKE8888(dstfmt, r, g, b, a) \ + ( ((r<<dstfmt->Rshift)&dstfmt->Rmask) | \ + ((g<<dstfmt->Gshift)&dstfmt->Gmask) | \ + ((b<<dstfmt->Bshift)&dstfmt->Bmask) | \ + ((a<<dstfmt->Ashift)&dstfmt->Amask) ) + +/* + * Data Stream Touch...Altivec cache prefetching. + * + * Don't use this on a G5...however, the speed boost is very significant + * on a G4. + */ +#define DST_CHAN_SRC 1 +#define DST_CHAN_DEST 2 + +/* macro to set DST control word value... */ +#define DST_CTRL(size, count, stride) \ + (((size) << 24) | ((count) << 16) | (stride)) + +#define VEC_ALIGNER(src) ((UNALIGNED_PTR(src)) \ + ? vec_lvsl(0, src) \ + : vec_add(vec_lvsl(8, src), vec_splat_u8(8))) + +/* Calculate the permute vector used for 32->32 swizzling */ +static vector unsigned char calc_swizzle32(const SDL_PixelFormat *srcfmt, + const SDL_PixelFormat *dstfmt) +{ + /* + * We have to assume that the bits that aren't used by other + * colors is alpha, and it's one complete byte, since some formats + * leave alpha with a zero mask, but we should still swizzle the bits. + */ + /* ARGB */ + const static struct SDL_PixelFormat default_pixel_format = { + NULL, 0, 0, + 0, 0, 0, 0, + 16, 8, 0, 24, + 0x00FF0000, 0x0000FF00, 0x000000FF, 0xFF000000, + 0, 0}; + if (!srcfmt) { + srcfmt = &default_pixel_format; + } + if (!dstfmt) { + dstfmt = &default_pixel_format; + } + const vector unsigned char plus = VECUINT8_LITERAL( + 0x00, 0x00, 0x00, 0x00, + 0x04, 0x04, 0x04, 0x04, + 0x08, 0x08, 0x08, 0x08, + 0x0C, 0x0C, 0x0C, 0x0C ); + vector unsigned char vswiz; + vector unsigned int srcvec; +#define RESHIFT(X) (3 - ((X) >> 3)) + Uint32 rmask = RESHIFT(srcfmt->Rshift) << (dstfmt->Rshift); + Uint32 gmask = RESHIFT(srcfmt->Gshift) << (dstfmt->Gshift); + Uint32 bmask = RESHIFT(srcfmt->Bshift) << (dstfmt->Bshift); + Uint32 amask; + /* Use zero for alpha if either surface doesn't have alpha */ + if (dstfmt->Amask) { + amask = ((srcfmt->Amask) ? RESHIFT(srcfmt->Ashift) : 0x10) << (dstfmt->Ashift); + } else { + amask = 0x10101010 & ((dstfmt->Rmask | dstfmt->Gmask | dstfmt->Bmask) ^ 0xFFFFFFFF); + } +#undef RESHIFT + ((unsigned int *)(char*)&srcvec)[0] = (rmask | gmask | bmask | amask); + vswiz = vec_add(plus, (vector unsigned char)vec_splat(srcvec, 0)); + return(vswiz); +} + +static void Blit_RGB888_RGB565(SDL_BlitInfo *info); +static void Blit_RGB888_RGB565Altivec(SDL_BlitInfo *info) { + int height = info->d_height; + Uint8 *src = (Uint8 *) info->s_pixels; + int srcskip = info->s_skip; + Uint8 *dst = (Uint8 *) info->d_pixels; + int dstskip = info->d_skip; + SDL_PixelFormat *srcfmt = info->src; + vector unsigned char valpha = vec_splat_u8(0); + vector unsigned char vpermute = calc_swizzle32(srcfmt, NULL); + vector unsigned char vgmerge = VECUINT8_LITERAL( + 0x00, 0x02, 0x00, 0x06, + 0x00, 0x0a, 0x00, 0x0e, + 0x00, 0x12, 0x00, 0x16, + 0x00, 0x1a, 0x00, 0x1e); + vector unsigned short v1 = vec_splat_u16(1); + vector unsigned short v3 = vec_splat_u16(3); + vector unsigned short v3f = VECUINT16_LITERAL( + 0x003f, 0x003f, 0x003f, 0x003f, + 0x003f, 0x003f, 0x003f, 0x003f); + vector unsigned short vfc = VECUINT16_LITERAL( + 0x00fc, 0x00fc, 0x00fc, 0x00fc, + 0x00fc, 0x00fc, 0x00fc, 0x00fc); + vector unsigned short vf800 = (vector unsigned short)vec_splat_u8(-7); + vf800 = vec_sl(vf800, vec_splat_u16(8)); + + while (height--) { + vector unsigned char valigner; + vector unsigned char voverflow; + vector unsigned char vsrc; + + int width = info->d_width; + int extrawidth; + + /* do scalar until we can align... */ +#define ONE_PIXEL_BLEND(condition, widthvar) \ + while (condition) { \ + Uint32 Pixel; \ + unsigned sR, sG, sB, sA; \ + DISEMBLE_RGBA((Uint8 *)src, 4, srcfmt, Pixel, \ + sR, sG, sB, sA); \ + *(Uint16 *)(dst) = (((sR << 8) & 0x0000F800) | \ + ((sG << 3) & 0x000007E0) | \ + ((sB >> 3) & 0x0000001F)); \ + dst += 2; \ + src += 4; \ + widthvar--; \ + } + + ONE_PIXEL_BLEND(((UNALIGNED_PTR(dst)) && (width)), width); + + /* After all that work, here's the vector part! */ + extrawidth = (width % 8); /* trailing unaligned stores */ + width -= extrawidth; + vsrc = vec_ld(0, src); + valigner = VEC_ALIGNER(src); + + while (width) { + vector unsigned short vpixel, vrpixel, vgpixel, vbpixel; + vector unsigned int vsrc1, vsrc2; + vector unsigned char vdst; + + voverflow = vec_ld(15, src); + vsrc = vec_perm(vsrc, voverflow, valigner); + vsrc1 = (vector unsigned int)vec_perm(vsrc, valpha, vpermute); + src += 16; + vsrc = voverflow; + voverflow = vec_ld(15, src); + vsrc = vec_perm(vsrc, voverflow, valigner); + vsrc2 = (vector unsigned int)vec_perm(vsrc, valpha, vpermute); + /* 1555 */ + vpixel = (vector unsigned short)vec_packpx(vsrc1, vsrc2); + vgpixel = (vector unsigned short)vec_perm(vsrc1, vsrc2, vgmerge); + vgpixel = vec_and(vgpixel, vfc); + vgpixel = vec_sl(vgpixel, v3); + vrpixel = vec_sl(vpixel, v1); + vrpixel = vec_and(vrpixel, vf800); + vbpixel = vec_and(vpixel, v3f); + vdst = vec_or((vector unsigned char)vrpixel, (vector unsigned char)vgpixel); + /* 565 */ + vdst = vec_or(vdst, (vector unsigned char)vbpixel); + vec_st(vdst, 0, dst); + + width -= 8; + src += 16; + dst += 16; + vsrc = voverflow; + } + + assert(width == 0); + + /* do scalar until we can align... */ + ONE_PIXEL_BLEND((extrawidth), extrawidth); +#undef ONE_PIXEL_BLEND + + src += srcskip; /* move to next row, accounting for pitch. */ + dst += dstskip; + } + + +} + +static void Blit_RGB565_32Altivec(SDL_BlitInfo *info) { + int height = info->d_height; + Uint8 *src = (Uint8 *) info->s_pixels; + int srcskip = info->s_skip; + Uint8 *dst = (Uint8 *) info->d_pixels; + int dstskip = info->d_skip; + SDL_PixelFormat *srcfmt = info->src; + SDL_PixelFormat *dstfmt = info->dst; + unsigned alpha; + vector unsigned char valpha; + vector unsigned char vpermute; + vector unsigned short vf800; + vector unsigned int v8 = vec_splat_u32(8); + vector unsigned int v16 = vec_add(v8, v8); + vector unsigned short v2 = vec_splat_u16(2); + vector unsigned short v3 = vec_splat_u16(3); + /* + 0x10 - 0x1f is the alpha + 0x00 - 0x0e evens are the red + 0x01 - 0x0f odds are zero + */ + vector unsigned char vredalpha1 = VECUINT8_LITERAL( + 0x10, 0x00, 0x01, 0x01, + 0x10, 0x02, 0x01, 0x01, + 0x10, 0x04, 0x01, 0x01, + 0x10, 0x06, 0x01, 0x01 + ); + vector unsigned char vredalpha2 = (vector unsigned char) ( + vec_add((vector unsigned int)vredalpha1, vec_sl(v8, v16)) + ); + /* + 0x00 - 0x0f is ARxx ARxx ARxx ARxx + 0x11 - 0x0f odds are blue + */ + vector unsigned char vblue1 = VECUINT8_LITERAL( + 0x00, 0x01, 0x02, 0x11, + 0x04, 0x05, 0x06, 0x13, + 0x08, 0x09, 0x0a, 0x15, + 0x0c, 0x0d, 0x0e, 0x17 + ); + vector unsigned char vblue2 = (vector unsigned char)( + vec_add((vector unsigned int)vblue1, v8) + ); + /* + 0x00 - 0x0f is ARxB ARxB ARxB ARxB + 0x10 - 0x0e evens are green + */ + vector unsigned char vgreen1 = VECUINT8_LITERAL( + 0x00, 0x01, 0x10, 0x03, + 0x04, 0x05, 0x12, 0x07, + 0x08, 0x09, 0x14, 0x0b, + 0x0c, 0x0d, 0x16, 0x0f + ); + vector unsigned char vgreen2 = (vector unsigned char)( + vec_add((vector unsigned int)vgreen1, vec_sl(v8, v8)) + ); + + + assert(srcfmt->BytesPerPixel == 2); + assert(dstfmt->BytesPerPixel == 4); + + vf800 = (vector unsigned short)vec_splat_u8(-7); + vf800 = vec_sl(vf800, vec_splat_u16(8)); + + if (dstfmt->Amask && srcfmt->alpha) { + ((unsigned char *)&valpha)[0] = alpha = srcfmt->alpha; + valpha = vec_splat(valpha, 0); + } else { + alpha = 0; + valpha = vec_splat_u8(0); + } + + vpermute = calc_swizzle32(NULL, dstfmt); + while (height--) { + vector unsigned char valigner; + vector unsigned char voverflow; + vector unsigned char vsrc; + + int width = info->d_width; + int extrawidth; + + /* do scalar until we can align... */ +#define ONE_PIXEL_BLEND(condition, widthvar) \ + while (condition) { \ + unsigned sR, sG, sB; \ + unsigned short Pixel = *((unsigned short *)src); \ + sR = (Pixel >> 8) & 0xf8; \ + sG = (Pixel >> 3) & 0xfc; \ + sB = (Pixel << 3) & 0xf8; \ + ASSEMBLE_RGBA(dst, 4, dstfmt, sR, sG, sB, alpha); \ + src += 2; \ + dst += 4; \ + widthvar--; \ + } + ONE_PIXEL_BLEND(((UNALIGNED_PTR(dst)) && (width)), width); + + /* After all that work, here's the vector part! */ + extrawidth = (width % 8); /* trailing unaligned stores */ + width -= extrawidth; + vsrc = vec_ld(0, src); + valigner = VEC_ALIGNER(src); + + while (width) { + vector unsigned short vR, vG, vB; + vector unsigned char vdst1, vdst2; + + voverflow = vec_ld(15, src); + vsrc = vec_perm(vsrc, voverflow, valigner); + + vR = vec_and((vector unsigned short)vsrc, vf800); + vB = vec_sl((vector unsigned short)vsrc, v3); + vG = vec_sl(vB, v2); + + vdst1 = (vector unsigned char)vec_perm((vector unsigned char)vR, valpha, vredalpha1); + vdst1 = vec_perm(vdst1, (vector unsigned char)vB, vblue1); + vdst1 = vec_perm(vdst1, (vector unsigned char)vG, vgreen1); + vdst1 = vec_perm(vdst1, valpha, vpermute); + vec_st(vdst1, 0, dst); + + vdst2 = (vector unsigned char)vec_perm((vector unsigned char)vR, valpha, vredalpha2); + vdst2 = vec_perm(vdst2, (vector unsigned char)vB, vblue2); + vdst2 = vec_perm(vdst2, (vector unsigned char)vG, vgreen2); + vdst2 = vec_perm(vdst2, valpha, vpermute); + vec_st(vdst2, 16, dst); + + width -= 8; + dst += 32; + src += 16; + vsrc = voverflow; + } + + assert(width == 0); + + + /* do scalar until we can align... */ + ONE_PIXEL_BLEND((extrawidth), extrawidth); +#undef ONE_PIXEL_BLEND + + src += srcskip; /* move to next row, accounting for pitch. */ + dst += dstskip; + } + +} + + +static void Blit_RGB555_32Altivec(SDL_BlitInfo *info) { + int height = info->d_height; + Uint8 *src = (Uint8 *) info->s_pixels; + int srcskip = info->s_skip; + Uint8 *dst = (Uint8 *) info->d_pixels; + int dstskip = info->d_skip; + SDL_PixelFormat *srcfmt = info->src; + SDL_PixelFormat *dstfmt = info->dst; + unsigned alpha; + vector unsigned char valpha; + vector unsigned char vpermute; + vector unsigned short vf800; + vector unsigned int v8 = vec_splat_u32(8); + vector unsigned int v16 = vec_add(v8, v8); + vector unsigned short v1 = vec_splat_u16(1); + vector unsigned short v3 = vec_splat_u16(3); + /* + 0x10 - 0x1f is the alpha + 0x00 - 0x0e evens are the red + 0x01 - 0x0f odds are zero + */ + vector unsigned char vredalpha1 = VECUINT8_LITERAL( + 0x10, 0x00, 0x01, 0x01, + 0x10, 0x02, 0x01, 0x01, + 0x10, 0x04, 0x01, 0x01, + 0x10, 0x06, 0x01, 0x01 + ); + vector unsigned char vredalpha2 = (vector unsigned char)( + vec_add((vector unsigned int)vredalpha1, vec_sl(v8, v16)) + ); + /* + 0x00 - 0x0f is ARxx ARxx ARxx ARxx + 0x11 - 0x0f odds are blue + */ + vector unsigned char vblue1 = VECUINT8_LITERAL( + 0x00, 0x01, 0x02, 0x11, + 0x04, 0x05, 0x06, 0x13, + 0x08, 0x09, 0x0a, 0x15, + 0x0c, 0x0d, 0x0e, 0x17 + ); + vector unsigned char vblue2 = (vector unsigned char)( + vec_add((vector unsigned int)vblue1, v8) + ); + /* + 0x00 - 0x0f is ARxB ARxB ARxB ARxB + 0x10 - 0x0e evens are green + */ + vector unsigned char vgreen1 = VECUINT8_LITERAL( + 0x00, 0x01, 0x10, 0x03, + 0x04, 0x05, 0x12, 0x07, + 0x08, 0x09, 0x14, 0x0b, + 0x0c, 0x0d, 0x16, 0x0f + ); + vector unsigned char vgreen2 = (vector unsigned char)( + vec_add((vector unsigned int)vgreen1, vec_sl(v8, v8)) + ); + + + assert(srcfmt->BytesPerPixel == 2); + assert(dstfmt->BytesPerPixel == 4); + + vf800 = (vector unsigned short)vec_splat_u8(-7); + vf800 = vec_sl(vf800, vec_splat_u16(8)); + + if (dstfmt->Amask && srcfmt->alpha) { + ((unsigned char *)&valpha)[0] = alpha = srcfmt->alpha; + valpha = vec_splat(valpha, 0); + } else { + alpha = 0; + valpha = vec_splat_u8(0); + } + + vpermute = calc_swizzle32(NULL, dstfmt); + while (height--) { + vector unsigned char valigner; + vector unsigned char voverflow; + vector unsigned char vsrc; + + int width = info->d_width; + int extrawidth; + + /* do scalar until we can align... */ +#define ONE_PIXEL_BLEND(condition, widthvar) \ + while (condition) { \ + unsigned sR, sG, sB; \ + unsigned short Pixel = *((unsigned short *)src); \ + sR = (Pixel >> 7) & 0xf8; \ + sG = (Pixel >> 2) & 0xf8; \ + sB = (Pixel << 3) & 0xf8; \ + ASSEMBLE_RGBA(dst, 4, dstfmt, sR, sG, sB, alpha); \ + src += 2; \ + dst += 4; \ + widthvar--; \ + } + ONE_PIXEL_BLEND(((UNALIGNED_PTR(dst)) && (width)), width); + + /* After all that work, here's the vector part! */ + extrawidth = (width % 8); /* trailing unaligned stores */ + width -= extrawidth; + vsrc = vec_ld(0, src); + valigner = VEC_ALIGNER(src); + + while (width) { + vector unsigned short vR, vG, vB; + vector unsigned char vdst1, vdst2; + + voverflow = vec_ld(15, src); + vsrc = vec_perm(vsrc, voverflow, valigner); + + vR = vec_and(vec_sl((vector unsigned short)vsrc,v1), vf800); + vB = vec_sl((vector unsigned short)vsrc, v3); + vG = vec_sl(vB, v3); + + vdst1 = (vector unsigned char)vec_perm((vector unsigned char)vR, valpha, vredalpha1); + vdst1 = vec_perm(vdst1, (vector unsigned char)vB, vblue1); + vdst1 = vec_perm(vdst1, (vector unsigned char)vG, vgreen1); + vdst1 = vec_perm(vdst1, valpha, vpermute); + vec_st(vdst1, 0, dst); + + vdst2 = (vector unsigned char)vec_perm((vector unsigned char)vR, valpha, vredalpha2); + vdst2 = vec_perm(vdst2, (vector unsigned char)vB, vblue2); + vdst2 = vec_perm(vdst2, (vector unsigned char)vG, vgreen2); + vdst2 = vec_perm(vdst2, valpha, vpermute); + vec_st(vdst2, 16, dst); + + width -= 8; + dst += 32; + src += 16; + vsrc = voverflow; + } + + assert(width == 0); + + + /* do scalar until we can align... */ + ONE_PIXEL_BLEND((extrawidth), extrawidth); +#undef ONE_PIXEL_BLEND + + src += srcskip; /* move to next row, accounting for pitch. */ + dst += dstskip; + } + +} + +static void BlitNtoNKey(SDL_BlitInfo *info); +static void BlitNtoNKeyCopyAlpha(SDL_BlitInfo *info); +static void Blit32to32KeyAltivec(SDL_BlitInfo *info) +{ + int height = info->d_height; + Uint32 *srcp = (Uint32 *) info->s_pixels; + int srcskip = info->s_skip; + Uint32 *dstp = (Uint32 *) info->d_pixels; + int dstskip = info->d_skip; + SDL_PixelFormat *srcfmt = info->src; + int srcbpp = srcfmt->BytesPerPixel; + SDL_PixelFormat *dstfmt = info->dst; + int dstbpp = dstfmt->BytesPerPixel; + int copy_alpha = (srcfmt->Amask && dstfmt->Amask); + unsigned alpha = dstfmt->Amask ? srcfmt->alpha : 0; + Uint32 rgbmask = srcfmt->Rmask | srcfmt->Gmask | srcfmt->Bmask; + Uint32 ckey = info->src->colorkey; + vector unsigned int valpha; + vector unsigned char vpermute; + vector unsigned char vzero; + vector unsigned int vckey; + vector unsigned int vrgbmask; + vpermute = calc_swizzle32(srcfmt, dstfmt); + if (info->d_width < 16) { + if(copy_alpha) { + BlitNtoNKeyCopyAlpha(info); + } else { + BlitNtoNKey(info); + } + return; + } + vzero = vec_splat_u8(0); + if (alpha) { + ((unsigned char *)&valpha)[0] = (unsigned char)alpha; + valpha = (vector unsigned int)vec_splat((vector unsigned char)valpha, 0); + } else { + valpha = (vector unsigned int)vzero; + } + ckey &= rgbmask; + ((unsigned int *)(char*)&vckey)[0] = ckey; + vckey = vec_splat(vckey, 0); + ((unsigned int *)(char*)&vrgbmask)[0] = rgbmask; + vrgbmask = vec_splat(vrgbmask, 0); + + while (height--) { +#define ONE_PIXEL_BLEND(condition, widthvar) \ + if (copy_alpha) { \ + while (condition) { \ + Uint32 Pixel; \ + unsigned sR, sG, sB, sA; \ + DISEMBLE_RGBA((Uint8 *)srcp, srcbpp, srcfmt, Pixel, \ + sR, sG, sB, sA); \ + if ( (Pixel & rgbmask) != ckey ) { \ + ASSEMBLE_RGBA((Uint8 *)dstp, dstbpp, dstfmt, \ + sR, sG, sB, sA); \ + } \ + dstp = (Uint32 *) (((Uint8 *) dstp) + dstbpp); \ + srcp = (Uint32 *) (((Uint8 *) srcp) + srcbpp); \ + widthvar--; \ + } \ + } else { \ + while (condition) { \ + Uint32 Pixel; \ + unsigned sR, sG, sB; \ + RETRIEVE_RGB_PIXEL((Uint8 *)srcp, srcbpp, Pixel); \ + if ( Pixel != ckey ) { \ + RGB_FROM_PIXEL(Pixel, srcfmt, sR, sG, sB); \ + ASSEMBLE_RGBA((Uint8 *)dstp, dstbpp, dstfmt, \ + sR, sG, sB, alpha); \ + } \ + dstp = (Uint32 *) (((Uint8 *)dstp) + dstbpp); \ + srcp = (Uint32 *) (((Uint8 *)srcp) + srcbpp); \ + widthvar--; \ + } \ + } + int width = info->d_width; + ONE_PIXEL_BLEND((UNALIGNED_PTR(dstp)) && (width), width); + assert(width > 0); + if (width > 0) { + int extrawidth = (width % 4); + vector unsigned char valigner = VEC_ALIGNER(srcp); + vector unsigned int vs = vec_ld(0, srcp); + width -= extrawidth; + assert(width >= 4); + while (width) { + vector unsigned char vsel; + vector unsigned int vd; + vector unsigned int voverflow = vec_ld(15, srcp); + /* load the source vec */ + vs = vec_perm(vs, voverflow, valigner); + /* vsel is set for items that match the key */ + vsel = (vector unsigned char)vec_and(vs, vrgbmask); + vsel = (vector unsigned char)vec_cmpeq(vs, vckey); + /* permute the src vec to the dest format */ + vs = vec_perm(vs, valpha, vpermute); + /* load the destination vec */ + vd = vec_ld(0, dstp); + /* select the source and dest into vs */ + vd = (vector unsigned int)vec_sel((vector unsigned char)vs, (vector unsigned char)vd, vsel); + + vec_st(vd, 0, dstp); + srcp += 4; + width -= 4; + dstp += 4; + vs = voverflow; + } + ONE_PIXEL_BLEND((extrawidth), extrawidth); +#undef ONE_PIXEL_BLEND + srcp += srcskip >> 2; + dstp += dstskip >> 2; + } + } +} + +/* Altivec code to swizzle one 32-bit surface to a different 32-bit format. */ +/* Use this on a G5 */ +static void ConvertAltivec32to32_noprefetch(SDL_BlitInfo *info) +{ + int height = info->d_height; + Uint32 *src = (Uint32 *) info->s_pixels; + int srcskip = info->s_skip; + Uint32 *dst = (Uint32 *) info->d_pixels; + int dstskip = info->d_skip; + SDL_PixelFormat *srcfmt = info->src; + SDL_PixelFormat *dstfmt = info->dst; + vector unsigned int vzero = vec_splat_u32(0); + vector unsigned char vpermute = calc_swizzle32(srcfmt, dstfmt); + if (dstfmt->Amask && !srcfmt->Amask) { + if (srcfmt->alpha) { + vector unsigned char valpha; + ((unsigned char *)&valpha)[0] = srcfmt->alpha; + vzero = (vector unsigned int)vec_splat(valpha, 0); + } + } + + assert(srcfmt->BytesPerPixel == 4); + assert(dstfmt->BytesPerPixel == 4); + + while (height--) { + vector unsigned char valigner; + vector unsigned int vbits; + vector unsigned int voverflow; + Uint32 bits; + Uint8 r, g, b, a; + + int width = info->d_width; + int extrawidth; + + /* do scalar until we can align... */ + while ((UNALIGNED_PTR(dst)) && (width)) { + bits = *(src++); + RGBA_FROM_8888(bits, srcfmt, r, g, b, a); + *(dst++) = MAKE8888(dstfmt, r, g, b, a); + width--; + } + + /* After all that work, here's the vector part! */ + extrawidth = (width % 4); + width -= extrawidth; + valigner = VEC_ALIGNER(src); + vbits = vec_ld(0, src); + + while (width) { + voverflow = vec_ld(15, src); + src += 4; + width -= 4; + vbits = vec_perm(vbits, voverflow, valigner); /* src is ready. */ + vbits = vec_perm(vbits, vzero, vpermute); /* swizzle it. */ + vec_st(vbits, 0, dst); /* store it back out. */ + dst += 4; + vbits = voverflow; + } + + assert(width == 0); + + /* cover pixels at the end of the row that didn't fit in 16 bytes. */ + while (extrawidth) { + bits = *(src++); /* max 7 pixels, don't bother with prefetch. */ + RGBA_FROM_8888(bits, srcfmt, r, g, b, a); + *(dst++) = MAKE8888(dstfmt, r, g, b, a); + extrawidth--; + } + + src += srcskip >> 2; /* move to next row, accounting for pitch. */ + dst += dstskip >> 2; + } + +} + +/* Altivec code to swizzle one 32-bit surface to a different 32-bit format. */ +/* Use this on a G4 */ +static void ConvertAltivec32to32_prefetch(SDL_BlitInfo *info) +{ + const int scalar_dst_lead = sizeof (Uint32) * 4; + const int vector_dst_lead = sizeof (Uint32) * 16; + + int height = info->d_height; + Uint32 *src = (Uint32 *) info->s_pixels; + int srcskip = info->s_skip; + Uint32 *dst = (Uint32 *) info->d_pixels; + int dstskip = info->d_skip; + SDL_PixelFormat *srcfmt = info->src; + SDL_PixelFormat *dstfmt = info->dst; + vector unsigned int vzero = vec_splat_u32(0); + vector unsigned char vpermute = calc_swizzle32(srcfmt, dstfmt); + if (dstfmt->Amask && !srcfmt->Amask) { + if (srcfmt->alpha) { + vector unsigned char valpha; + ((unsigned char *)&valpha)[0] = srcfmt->alpha; + vzero = (vector unsigned int)vec_splat(valpha, 0); + } + } + + assert(srcfmt->BytesPerPixel == 4); + assert(dstfmt->BytesPerPixel == 4); + + while (height--) { + vector unsigned char valigner; + vector unsigned int vbits; + vector unsigned int voverflow; + Uint32 bits; + Uint8 r, g, b, a; + + int width = info->d_width; + int extrawidth; + + /* do scalar until we can align... */ + while ((UNALIGNED_PTR(dst)) && (width)) { + vec_dstt(src+scalar_dst_lead, DST_CTRL(2,32,1024), DST_CHAN_SRC); + vec_dstst(dst+scalar_dst_lead, DST_CTRL(2,32,1024), DST_CHAN_DEST); + bits = *(src++); + RGBA_FROM_8888(bits, srcfmt, r, g, b, a); + *(dst++) = MAKE8888(dstfmt, r, g, b, a); + width--; + } + + /* After all that work, here's the vector part! */ + extrawidth = (width % 4); + width -= extrawidth; + valigner = VEC_ALIGNER(src); + vbits = vec_ld(0, src); + + while (width) { + vec_dstt(src+vector_dst_lead, DST_CTRL(2,32,1024), DST_CHAN_SRC); + vec_dstst(dst+vector_dst_lead, DST_CTRL(2,32,1024), DST_CHAN_DEST); + voverflow = vec_ld(15, src); + src += 4; + width -= 4; + vbits = vec_perm(vbits, voverflow, valigner); /* src is ready. */ + vbits = vec_perm(vbits, vzero, vpermute); /* swizzle it. */ + vec_st(vbits, 0, dst); /* store it back out. */ + dst += 4; + vbits = voverflow; + } + + assert(width == 0); + + /* cover pixels at the end of the row that didn't fit in 16 bytes. */ + while (extrawidth) { + bits = *(src++); /* max 7 pixels, don't bother with prefetch. */ + RGBA_FROM_8888(bits, srcfmt, r, g, b, a); + *(dst++) = MAKE8888(dstfmt, r, g, b, a); + extrawidth--; + } + + src += srcskip >> 2; /* move to next row, accounting for pitch. */ + dst += dstskip >> 2; + } + + vec_dss(DST_CHAN_SRC); + vec_dss(DST_CHAN_DEST); +} + +static Uint32 GetBlitFeatures( void ) +{ + static Uint32 features = 0xffffffff; + if (features == 0xffffffff) { + /* Provide an override for testing .. */ + char *override = SDL_getenv("SDL_ALTIVEC_BLIT_FEATURES"); + if (override) { + features = 0; + SDL_sscanf(override, "%u", &features); + } else { + features = ( 0 + /* Feature 1 is has-MMX */ + | ((SDL_HasMMX()) ? 1 : 0) + /* Feature 2 is has-AltiVec */ + | ((SDL_HasAltiVec()) ? 2 : 0) + /* Feature 4 is dont-use-prefetch */ + /* !!!! FIXME: Check for G5 or later, not the cache size! Always prefetch on a G4. */ + | ((GetL3CacheSize() == 0) ? 4 : 0) + ); + } + } + return features; +} +#if __MWERKS__ +#pragma altivec_model off +#endif +#else +/* Feature 1 is has-MMX */ +#define GetBlitFeatures() ((Uint32)(SDL_HasMMX() ? 1 : 0)) +#endif + +/* This is now endian dependent */ +#if SDL_BYTEORDER == SDL_LIL_ENDIAN +#define HI 1 +#define LO 0 +#else /* SDL_BYTEORDER == SDL_BIG_ENDIAN */ +#define HI 0 +#define LO 1 +#endif + +#if SDL_HERMES_BLITTERS + +/* Heheheh, we coerce Hermes into using SDL blit information */ +#define X86_ASSEMBLER +#define HermesConverterInterface SDL_BlitInfo +#define HermesClearInterface void +#define STACKCALL + +#include "../hermes/HeadMMX.h" +#include "../hermes/HeadX86.h" + +#else + +/* Special optimized blit for RGB 8-8-8 --> RGB 3-3-2 */ +#define RGB888_RGB332(dst, src) { \ + dst = (Uint8)((((src)&0x00E00000)>>16)| \ + (((src)&0x0000E000)>>11)| \ + (((src)&0x000000C0)>>6)); \ +} +static void Blit_RGB888_index8(SDL_BlitInfo *info) +{ +#ifndef USE_DUFFS_LOOP + int c; +#endif + int width, height; + Uint32 *src; + const Uint8 *map; + Uint8 *dst; + int srcskip, dstskip; + + /* Set up some basic variables */ + width = info->d_width; + height = info->d_height; + src = (Uint32 *)info->s_pixels; + srcskip = info->s_skip/4; + dst = info->d_pixels; + dstskip = info->d_skip; + map = info->table; + + if ( map == NULL ) { + while ( height-- ) { +#ifdef USE_DUFFS_LOOP + DUFFS_LOOP( + RGB888_RGB332(*dst++, *src); + , width); +#else + for ( c=width/4; c; --c ) { + /* Pack RGB into 8bit pixel */ + ++src; + RGB888_RGB332(*dst++, *src); + ++src; + RGB888_RGB332(*dst++, *src); + ++src; + RGB888_RGB332(*dst++, *src); + ++src; + } + switch ( width & 3 ) { + case 3: + RGB888_RGB332(*dst++, *src); + ++src; + case 2: + RGB888_RGB332(*dst++, *src); + ++src; + case 1: + RGB888_RGB332(*dst++, *src); + ++src; + } +#endif /* USE_DUFFS_LOOP */ + src += srcskip; + dst += dstskip; + } + } else { + int Pixel; + + while ( height-- ) { +#ifdef USE_DUFFS_LOOP + DUFFS_LOOP( + RGB888_RGB332(Pixel, *src); + *dst++ = map[Pixel]; + ++src; + , width); +#else + for ( c=width/4; c; --c ) { + /* Pack RGB into 8bit pixel */ + RGB888_RGB332(Pixel, *src); + *dst++ = map[Pixel]; + ++src; + RGB888_RGB332(Pixel, *src); + *dst++ = map[Pixel]; + ++src; + RGB888_RGB332(Pixel, *src); + *dst++ = map[Pixel]; + ++src; + RGB888_RGB332(Pixel, *src); + *dst++ = map[Pixel]; + ++src; + } + switch ( width & 3 ) { + case 3: + RGB888_RGB332(Pixel, *src); + *dst++ = map[Pixel]; + ++src; + case 2: + RGB888_RGB332(Pixel, *src); + *dst++ = map[Pixel]; + ++src; + case 1: + RGB888_RGB332(Pixel, *src); + *dst++ = map[Pixel]; + ++src; + } +#endif /* USE_DUFFS_LOOP */ + src += srcskip; + dst += dstskip; + } + } +} +/* Special optimized blit for RGB 8-8-8 --> RGB 5-5-5 */ +#define RGB888_RGB555(dst, src) { \ + *(Uint16 *)(dst) = (Uint16)((((*src)&0x00F80000)>>9)| \ + (((*src)&0x0000F800)>>6)| \ + (((*src)&0x000000F8)>>3)); \ +} +#define RGB888_RGB555_TWO(dst, src) { \ + *(Uint32 *)(dst) = (((((src[HI])&0x00F80000)>>9)| \ + (((src[HI])&0x0000F800)>>6)| \ + (((src[HI])&0x000000F8)>>3))<<16)| \ + (((src[LO])&0x00F80000)>>9)| \ + (((src[LO])&0x0000F800)>>6)| \ + (((src[LO])&0x000000F8)>>3); \ +} +static void Blit_RGB888_RGB555(SDL_BlitInfo *info) +{ +#ifndef USE_DUFFS_LOOP + int c; +#endif + int width, height; + Uint32 *src; + Uint16 *dst; + int srcskip, dstskip; + + /* Set up some basic variables */ + width = info->d_width; + height = info->d_height; + src = (Uint32 *)info->s_pixels; + srcskip = info->s_skip/4; + dst = (Uint16 *)info->d_pixels; + dstskip = info->d_skip/2; + +#ifdef USE_DUFFS_LOOP + while ( height-- ) { + DUFFS_LOOP( + RGB888_RGB555(dst, src); + ++src; + ++dst; + , width); + src += srcskip; + dst += dstskip; + } +#else + /* Memory align at 4-byte boundary, if necessary */ + if ( (long)dst & 0x03 ) { + /* Don't do anything if width is 0 */ + if ( width == 0 ) { + return; + } + --width; + + while ( height-- ) { + /* Perform copy alignment */ + RGB888_RGB555(dst, src); + ++src; + ++dst; + + /* Copy in 4 pixel chunks */ + for ( c=width/4; c; --c ) { + RGB888_RGB555_TWO(dst, src); + src += 2; + dst += 2; + RGB888_RGB555_TWO(dst, src); + src += 2; + dst += 2; + } + /* Get any leftovers */ + switch (width & 3) { + case 3: + RGB888_RGB555(dst, src); + ++src; + ++dst; + case 2: + RGB888_RGB555_TWO(dst, src); + src += 2; + dst += 2; + break; + case 1: + RGB888_RGB555(dst, src); + ++src; + ++dst; + break; + } + src += srcskip; + dst += dstskip; + } + } else { + while ( height-- ) { + /* Copy in 4 pixel chunks */ + for ( c=width/4; c; --c ) { + RGB888_RGB555_TWO(dst, src); + src += 2; + dst += 2; + RGB888_RGB555_TWO(dst, src); + src += 2; + dst += 2; + } + /* Get any leftovers */ + switch (width & 3) { + case 3: + RGB888_RGB555(dst, src); + ++src; + ++dst; + case 2: + RGB888_RGB555_TWO(dst, src); + src += 2; + dst += 2; + break; + case 1: + RGB888_RGB555(dst, src); + ++src; + ++dst; + break; + } + src += srcskip; + dst += dstskip; + } + } +#endif /* USE_DUFFS_LOOP */ +} +/* Special optimized blit for RGB 8-8-8 --> RGB 5-6-5 */ +#define RGB888_RGB565(dst, src) { \ + *(Uint16 *)(dst) = (Uint16)((((*src)&0x00F80000)>>8)| \ + (((*src)&0x0000FC00)>>5)| \ + (((*src)&0x000000F8)>>3)); \ +} +#define RGB888_RGB565_TWO(dst, src) { \ + *(Uint32 *)(dst) = (((((src[HI])&0x00F80000)>>8)| \ + (((src[HI])&0x0000FC00)>>5)| \ + (((src[HI])&0x000000F8)>>3))<<16)| \ + (((src[LO])&0x00F80000)>>8)| \ + (((src[LO])&0x0000FC00)>>5)| \ + (((src[LO])&0x000000F8)>>3); \ +} +static void Blit_RGB888_RGB565(SDL_BlitInfo *info) +{ +#ifndef USE_DUFFS_LOOP + int c; +#endif + int width, height; + Uint32 *src; + Uint16 *dst; + int srcskip, dstskip; + + /* Set up some basic variables */ + width = info->d_width; + height = info->d_height; + src = (Uint32 *)info->s_pixels; + srcskip = info->s_skip/4; + dst = (Uint16 *)info->d_pixels; + dstskip = info->d_skip/2; + +#ifdef USE_DUFFS_LOOP + while ( height-- ) { + DUFFS_LOOP( + RGB888_RGB565(dst, src); + ++src; + ++dst; + , width); + src += srcskip; + dst += dstskip; + } +#else + /* Memory align at 4-byte boundary, if necessary */ + if ( (long)dst & 0x03 ) { + /* Don't do anything if width is 0 */ + if ( width == 0 ) { + return; + } + --width; + + while ( height-- ) { + /* Perform copy alignment */ + RGB888_RGB565(dst, src); + ++src; + ++dst; + + /* Copy in 4 pixel chunks */ + for ( c=width/4; c; --c ) { + RGB888_RGB565_TWO(dst, src); + src += 2; + dst += 2; + RGB888_RGB565_TWO(dst, src); + src += 2; + dst += 2; + } + /* Get any leftovers */ + switch (width & 3) { + case 3: + RGB888_RGB565(dst, src); + ++src; + ++dst; + case 2: + RGB888_RGB565_TWO(dst, src); + src += 2; + dst += 2; + break; + case 1: + RGB888_RGB565(dst, src); + ++src; + ++dst; + break; + } + src += srcskip; + dst += dstskip; + } + } else { + while ( height-- ) { + /* Copy in 4 pixel chunks */ + for ( c=width/4; c; --c ) { + RGB888_RGB565_TWO(dst, src); + src += 2; + dst += 2; + RGB888_RGB565_TWO(dst, src); + src += 2; + dst += 2; + } + /* Get any leftovers */ + switch (width & 3) { + case 3: + RGB888_RGB565(dst, src); + ++src; + ++dst; + case 2: + RGB888_RGB565_TWO(dst, src); + src += 2; + dst += 2; + break; + case 1: + RGB888_RGB565(dst, src); + ++src; + ++dst; + break; + } + src += srcskip; + dst += dstskip; + } + } +#endif /* USE_DUFFS_LOOP */ +} + +#endif /* SDL_HERMES_BLITTERS */ + + +/* Special optimized blit for RGB 5-6-5 --> 32-bit RGB surfaces */ +#define RGB565_32(dst, src, map) (map[src[LO]*2] + map[src[HI]*2+1]) +static void Blit_RGB565_32(SDL_BlitInfo *info, const Uint32 *map) +{ +#ifndef USE_DUFFS_LOOP + int c; +#endif + int width, height; + Uint8 *src; + Uint32 *dst; + int srcskip, dstskip; + + /* Set up some basic variables */ + width = info->d_width; + height = info->d_height; + src = (Uint8 *)info->s_pixels; + srcskip = info->s_skip; + dst = (Uint32 *)info->d_pixels; + dstskip = info->d_skip/4; + +#ifdef USE_DUFFS_LOOP + while ( height-- ) { + DUFFS_LOOP( + { + *dst++ = RGB565_32(dst, src, map); + src += 2; + }, + width); + src += srcskip; + dst += dstskip; + } +#else + while ( height-- ) { + /* Copy in 4 pixel chunks */ + for ( c=width/4; c; --c ) { + *dst++ = RGB565_32(dst, src, map); + src += 2; + *dst++ = RGB565_32(dst, src, map); + src += 2; + *dst++ = RGB565_32(dst, src, map); + src += 2; + *dst++ = RGB565_32(dst, src, map); + src += 2; + } + /* Get any leftovers */ + switch (width & 3) { + case 3: + *dst++ = RGB565_32(dst, src, map); + src += 2; + case 2: + *dst++ = RGB565_32(dst, src, map); + src += 2; + case 1: + *dst++ = RGB565_32(dst, src, map); + src += 2; + break; + } + src += srcskip; + dst += dstskip; + } +#endif /* USE_DUFFS_LOOP */ +} + +/* Special optimized blit for RGB 5-6-5 --> ARGB 8-8-8-8 */ +static const Uint32 RGB565_ARGB8888_LUT[512] = { + 0x00000000, 0xff000000, 0x00000008, 0xff002000, + 0x00000010, 0xff004000, 0x00000018, 0xff006100, + 0x00000020, 0xff008100, 0x00000029, 0xff00a100, + 0x00000031, 0xff00c200, 0x00000039, 0xff00e200, + 0x00000041, 0xff080000, 0x0000004a, 0xff082000, + 0x00000052, 0xff084000, 0x0000005a, 0xff086100, + 0x00000062, 0xff088100, 0x0000006a, 0xff08a100, + 0x00000073, 0xff08c200, 0x0000007b, 0xff08e200, + 0x00000083, 0xff100000, 0x0000008b, 0xff102000, + 0x00000094, 0xff104000, 0x0000009c, 0xff106100, + 0x000000a4, 0xff108100, 0x000000ac, 0xff10a100, + 0x000000b4, 0xff10c200, 0x000000bd, 0xff10e200, + 0x000000c5, 0xff180000, 0x000000cd, 0xff182000, + 0x000000d5, 0xff184000, 0x000000de, 0xff186100, + 0x000000e6, 0xff188100, 0x000000ee, 0xff18a100, + 0x000000f6, 0xff18c200, 0x000000ff, 0xff18e200, + 0x00000400, 0xff200000, 0x00000408, 0xff202000, + 0x00000410, 0xff204000, 0x00000418, 0xff206100, + 0x00000420, 0xff208100, 0x00000429, 0xff20a100, + 0x00000431, 0xff20c200, 0x00000439, 0xff20e200, + 0x00000441, 0xff290000, 0x0000044a, 0xff292000, + 0x00000452, 0xff294000, 0x0000045a, 0xff296100, + 0x00000462, 0xff298100, 0x0000046a, 0xff29a100, + 0x00000473, 0xff29c200, 0x0000047b, 0xff29e200, + 0x00000483, 0xff310000, 0x0000048b, 0xff312000, + 0x00000494, 0xff314000, 0x0000049c, 0xff316100, + 0x000004a4, 0xff318100, 0x000004ac, 0xff31a100, + 0x000004b4, 0xff31c200, 0x000004bd, 0xff31e200, + 0x000004c5, 0xff390000, 0x000004cd, 0xff392000, + 0x000004d5, 0xff394000, 0x000004de, 0xff396100, + 0x000004e6, 0xff398100, 0x000004ee, 0xff39a100, + 0x000004f6, 0xff39c200, 0x000004ff, 0xff39e200, + 0x00000800, 0xff410000, 0x00000808, 0xff412000, + 0x00000810, 0xff414000, 0x00000818, 0xff416100, + 0x00000820, 0xff418100, 0x00000829, 0xff41a100, + 0x00000831, 0xff41c200, 0x00000839, 0xff41e200, + 0x00000841, 0xff4a0000, 0x0000084a, 0xff4a2000, + 0x00000852, 0xff4a4000, 0x0000085a, 0xff4a6100, + 0x00000862, 0xff4a8100, 0x0000086a, 0xff4aa100, + 0x00000873, 0xff4ac200, 0x0000087b, 0xff4ae200, + 0x00000883, 0xff520000, 0x0000088b, 0xff522000, + 0x00000894, 0xff524000, 0x0000089c, 0xff526100, + 0x000008a4, 0xff528100, 0x000008ac, 0xff52a100, + 0x000008b4, 0xff52c200, 0x000008bd, 0xff52e200, + 0x000008c5, 0xff5a0000, 0x000008cd, 0xff5a2000, + 0x000008d5, 0xff5a4000, 0x000008de, 0xff5a6100, + 0x000008e6, 0xff5a8100, 0x000008ee, 0xff5aa100, + 0x000008f6, 0xff5ac200, 0x000008ff, 0xff5ae200, + 0x00000c00, 0xff620000, 0x00000c08, 0xff622000, + 0x00000c10, 0xff624000, 0x00000c18, 0xff626100, + 0x00000c20, 0xff628100, 0x00000c29, 0xff62a100, + 0x00000c31, 0xff62c200, 0x00000c39, 0xff62e200, + 0x00000c41, 0xff6a0000, 0x00000c4a, 0xff6a2000, + 0x00000c52, 0xff6a4000, 0x00000c5a, 0xff6a6100, + 0x00000c62, 0xff6a8100, 0x00000c6a, 0xff6aa100, + 0x00000c73, 0xff6ac200, 0x00000c7b, 0xff6ae200, + 0x00000c83, 0xff730000, 0x00000c8b, 0xff732000, + 0x00000c94, 0xff734000, 0x00000c9c, 0xff736100, + 0x00000ca4, 0xff738100, 0x00000cac, 0xff73a100, + 0x00000cb4, 0xff73c200, 0x00000cbd, 0xff73e200, + 0x00000cc5, 0xff7b0000, 0x00000ccd, 0xff7b2000, + 0x00000cd5, 0xff7b4000, 0x00000cde, 0xff7b6100, + 0x00000ce6, 0xff7b8100, 0x00000cee, 0xff7ba100, + 0x00000cf6, 0xff7bc200, 0x00000cff, 0xff7be200, + 0x00001000, 0xff830000, 0x00001008, 0xff832000, + 0x00001010, 0xff834000, 0x00001018, 0xff836100, + 0x00001020, 0xff838100, 0x00001029, 0xff83a100, + 0x00001031, 0xff83c200, 0x00001039, 0xff83e200, + 0x00001041, 0xff8b0000, 0x0000104a, 0xff8b2000, + 0x00001052, 0xff8b4000, 0x0000105a, 0xff8b6100, + 0x00001062, 0xff8b8100, 0x0000106a, 0xff8ba100, + 0x00001073, 0xff8bc200, 0x0000107b, 0xff8be200, + 0x00001083, 0xff940000, 0x0000108b, 0xff942000, + 0x00001094, 0xff944000, 0x0000109c, 0xff946100, + 0x000010a4, 0xff948100, 0x000010ac, 0xff94a100, + 0x000010b4, 0xff94c200, 0x000010bd, 0xff94e200, + 0x000010c5, 0xff9c0000, 0x000010cd, 0xff9c2000, + 0x000010d5, 0xff9c4000, 0x000010de, 0xff9c6100, + 0x000010e6, 0xff9c8100, 0x000010ee, 0xff9ca100, + 0x000010f6, 0xff9cc200, 0x000010ff, 0xff9ce200, + 0x00001400, 0xffa40000, 0x00001408, 0xffa42000, + 0x00001410, 0xffa44000, 0x00001418, 0xffa46100, + 0x00001420, 0xffa48100, 0x00001429, 0xffa4a100, + 0x00001431, 0xffa4c200, 0x00001439, 0xffa4e200, + 0x00001441, 0xffac0000, 0x0000144a, 0xffac2000, + 0x00001452, 0xffac4000, 0x0000145a, 0xffac6100, + 0x00001462, 0xffac8100, 0x0000146a, 0xffaca100, + 0x00001473, 0xffacc200, 0x0000147b, 0xfface200, + 0x00001483, 0xffb40000, 0x0000148b, 0xffb42000, + 0x00001494, 0xffb44000, 0x0000149c, 0xffb46100, + 0x000014a4, 0xffb48100, 0x000014ac, 0xffb4a100, + 0x000014b4, 0xffb4c200, 0x000014bd, 0xffb4e200, + 0x000014c5, 0xffbd0000, 0x000014cd, 0xffbd2000, + 0x000014d5, 0xffbd4000, 0x000014de, 0xffbd6100, + 0x000014e6, 0xffbd8100, 0x000014ee, 0xffbda100, + 0x000014f6, 0xffbdc200, 0x000014ff, 0xffbde200, + 0x00001800, 0xffc50000, 0x00001808, 0xffc52000, + 0x00001810, 0xffc54000, 0x00001818, 0xffc56100, + 0x00001820, 0xffc58100, 0x00001829, 0xffc5a100, + 0x00001831, 0xffc5c200, 0x00001839, 0xffc5e200, + 0x00001841, 0xffcd0000, 0x0000184a, 0xffcd2000, + 0x00001852, 0xffcd4000, 0x0000185a, 0xffcd6100, + 0x00001862, 0xffcd8100, 0x0000186a, 0xffcda100, + 0x00001873, 0xffcdc200, 0x0000187b, 0xffcde200, + 0x00001883, 0xffd50000, 0x0000188b, 0xffd52000, + 0x00001894, 0xffd54000, 0x0000189c, 0xffd56100, + 0x000018a4, 0xffd58100, 0x000018ac, 0xffd5a100, + 0x000018b4, 0xffd5c200, 0x000018bd, 0xffd5e200, + 0x000018c5, 0xffde0000, 0x000018cd, 0xffde2000, + 0x000018d5, 0xffde4000, 0x000018de, 0xffde6100, + 0x000018e6, 0xffde8100, 0x000018ee, 0xffdea100, + 0x000018f6, 0xffdec200, 0x000018ff, 0xffdee200, + 0x00001c00, 0xffe60000, 0x00001c08, 0xffe62000, + 0x00001c10, 0xffe64000, 0x00001c18, 0xffe66100, + 0x00001c20, 0xffe68100, 0x00001c29, 0xffe6a100, + 0x00001c31, 0xffe6c200, 0x00001c39, 0xffe6e200, + 0x00001c41, 0xffee0000, 0x00001c4a, 0xffee2000, + 0x00001c52, 0xffee4000, 0x00001c5a, 0xffee6100, + 0x00001c62, 0xffee8100, 0x00001c6a, 0xffeea100, + 0x00001c73, 0xffeec200, 0x00001c7b, 0xffeee200, + 0x00001c83, 0xfff60000, 0x00001c8b, 0xfff62000, + 0x00001c94, 0xfff64000, 0x00001c9c, 0xfff66100, + 0x00001ca4, 0xfff68100, 0x00001cac, 0xfff6a100, + 0x00001cb4, 0xfff6c200, 0x00001cbd, 0xfff6e200, + 0x00001cc5, 0xffff0000, 0x00001ccd, 0xffff2000, + 0x00001cd5, 0xffff4000, 0x00001cde, 0xffff6100, + 0x00001ce6, 0xffff8100, 0x00001cee, 0xffffa100, + 0x00001cf6, 0xffffc200, 0x00001cff, 0xffffe200 +}; +static void Blit_RGB565_ARGB8888(SDL_BlitInfo *info) +{ + Blit_RGB565_32(info, RGB565_ARGB8888_LUT); +} + +/* Special optimized blit for RGB 5-6-5 --> ABGR 8-8-8-8 */ +static const Uint32 RGB565_ABGR8888_LUT[512] = { + 0xff000000, 0x00000000, 0xff080000, 0x00002000, + 0xff100000, 0x00004000, 0xff180000, 0x00006100, + 0xff200000, 0x00008100, 0xff290000, 0x0000a100, + 0xff310000, 0x0000c200, 0xff390000, 0x0000e200, + 0xff410000, 0x00000008, 0xff4a0000, 0x00002008, + 0xff520000, 0x00004008, 0xff5a0000, 0x00006108, + 0xff620000, 0x00008108, 0xff6a0000, 0x0000a108, + 0xff730000, 0x0000c208, 0xff7b0000, 0x0000e208, + 0xff830000, 0x00000010, 0xff8b0000, 0x00002010, + 0xff940000, 0x00004010, 0xff9c0000, 0x00006110, + 0xffa40000, 0x00008110, 0xffac0000, 0x0000a110, + 0xffb40000, 0x0000c210, 0xffbd0000, 0x0000e210, + 0xffc50000, 0x00000018, 0xffcd0000, 0x00002018, + 0xffd50000, 0x00004018, 0xffde0000, 0x00006118, + 0xffe60000, 0x00008118, 0xffee0000, 0x0000a118, + 0xfff60000, 0x0000c218, 0xffff0000, 0x0000e218, + 0xff000400, 0x00000020, 0xff080400, 0x00002020, + 0xff100400, 0x00004020, 0xff180400, 0x00006120, + 0xff200400, 0x00008120, 0xff290400, 0x0000a120, + 0xff310400, 0x0000c220, 0xff390400, 0x0000e220, + 0xff410400, 0x00000029, 0xff4a0400, 0x00002029, + 0xff520400, 0x00004029, 0xff5a0400, 0x00006129, + 0xff620400, 0x00008129, 0xff6a0400, 0x0000a129, + 0xff730400, 0x0000c229, 0xff7b0400, 0x0000e229, + 0xff830400, 0x00000031, 0xff8b0400, 0x00002031, + 0xff940400, 0x00004031, 0xff9c0400, 0x00006131, + 0xffa40400, 0x00008131, 0xffac0400, 0x0000a131, + 0xffb40400, 0x0000c231, 0xffbd0400, 0x0000e231, + 0xffc50400, 0x00000039, 0xffcd0400, 0x00002039, + 0xffd50400, 0x00004039, 0xffde0400, 0x00006139, + 0xffe60400, 0x00008139, 0xffee0400, 0x0000a139, + 0xfff60400, 0x0000c239, 0xffff0400, 0x0000e239, + 0xff000800, 0x00000041, 0xff080800, 0x00002041, + 0xff100800, 0x00004041, 0xff180800, 0x00006141, + 0xff200800, 0x00008141, 0xff290800, 0x0000a141, + 0xff310800, 0x0000c241, 0xff390800, 0x0000e241, + 0xff410800, 0x0000004a, 0xff4a0800, 0x0000204a, + 0xff520800, 0x0000404a, 0xff5a0800, 0x0000614a, + 0xff620800, 0x0000814a, 0xff6a0800, 0x0000a14a, + 0xff730800, 0x0000c24a, 0xff7b0800, 0x0000e24a, + 0xff830800, 0x00000052, 0xff8b0800, 0x00002052, + 0xff940800, 0x00004052, 0xff9c0800, 0x00006152, + 0xffa40800, 0x00008152, 0xffac0800, 0x0000a152, + 0xffb40800, 0x0000c252, 0xffbd0800, 0x0000e252, + 0xffc50800, 0x0000005a, 0xffcd0800, 0x0000205a, + 0xffd50800, 0x0000405a, 0xffde0800, 0x0000615a, + 0xffe60800, 0x0000815a, 0xffee0800, 0x0000a15a, + 0xfff60800, 0x0000c25a, 0xffff0800, 0x0000e25a, + 0xff000c00, 0x00000062, 0xff080c00, 0x00002062, + 0xff100c00, 0x00004062, 0xff180c00, 0x00006162, + 0xff200c00, 0x00008162, 0xff290c00, 0x0000a162, + 0xff310c00, 0x0000c262, 0xff390c00, 0x0000e262, + 0xff410c00, 0x0000006a, 0xff4a0c00, 0x0000206a, + 0xff520c00, 0x0000406a, 0xff5a0c00, 0x0000616a, + 0xff620c00, 0x0000816a, 0xff6a0c00, 0x0000a16a, + 0xff730c00, 0x0000c26a, 0xff7b0c00, 0x0000e26a, + 0xff830c00, 0x00000073, 0xff8b0c00, 0x00002073, + 0xff940c00, 0x00004073, 0xff9c0c00, 0x00006173, + 0xffa40c00, 0x00008173, 0xffac0c00, 0x0000a173, + 0xffb40c00, 0x0000c273, 0xffbd0c00, 0x0000e273, + 0xffc50c00, 0x0000007b, 0xffcd0c00, 0x0000207b, + 0xffd50c00, 0x0000407b, 0xffde0c00, 0x0000617b, + 0xffe60c00, 0x0000817b, 0xffee0c00, 0x0000a17b, + 0xfff60c00, 0x0000c27b, 0xffff0c00, 0x0000e27b, + 0xff001000, 0x00000083, 0xff081000, 0x00002083, + 0xff101000, 0x00004083, 0xff181000, 0x00006183, + 0xff201000, 0x00008183, 0xff291000, 0x0000a183, + 0xff311000, 0x0000c283, 0xff391000, 0x0000e283, + 0xff411000, 0x0000008b, 0xff4a1000, 0x0000208b, + 0xff521000, 0x0000408b, 0xff5a1000, 0x0000618b, + 0xff621000, 0x0000818b, 0xff6a1000, 0x0000a18b, + 0xff731000, 0x0000c28b, 0xff7b1000, 0x0000e28b, + 0xff831000, 0x00000094, 0xff8b1000, 0x00002094, + 0xff941000, 0x00004094, 0xff9c1000, 0x00006194, + 0xffa41000, 0x00008194, 0xffac1000, 0x0000a194, + 0xffb41000, 0x0000c294, 0xffbd1000, 0x0000e294, + 0xffc51000, 0x0000009c, 0xffcd1000, 0x0000209c, + 0xffd51000, 0x0000409c, 0xffde1000, 0x0000619c, + 0xffe61000, 0x0000819c, 0xffee1000, 0x0000a19c, + 0xfff61000, 0x0000c29c, 0xffff1000, 0x0000e29c, + 0xff001400, 0x000000a4, 0xff081400, 0x000020a4, + 0xff101400, 0x000040a4, 0xff181400, 0x000061a4, + 0xff201400, 0x000081a4, 0xff291400, 0x0000a1a4, + 0xff311400, 0x0000c2a4, 0xff391400, 0x0000e2a4, + 0xff411400, 0x000000ac, 0xff4a1400, 0x000020ac, + 0xff521400, 0x000040ac, 0xff5a1400, 0x000061ac, + 0xff621400, 0x000081ac, 0xff6a1400, 0x0000a1ac, + 0xff731400, 0x0000c2ac, 0xff7b1400, 0x0000e2ac, + 0xff831400, 0x000000b4, 0xff8b1400, 0x000020b4, + 0xff941400, 0x000040b4, 0xff9c1400, 0x000061b4, + 0xffa41400, 0x000081b4, 0xffac1400, 0x0000a1b4, + 0xffb41400, 0x0000c2b4, 0xffbd1400, 0x0000e2b4, + 0xffc51400, 0x000000bd, 0xffcd1400, 0x000020bd, + 0xffd51400, 0x000040bd, 0xffde1400, 0x000061bd, + 0xffe61400, 0x000081bd, 0xffee1400, 0x0000a1bd, + 0xfff61400, 0x0000c2bd, 0xffff1400, 0x0000e2bd, + 0xff001800, 0x000000c5, 0xff081800, 0x000020c5, + 0xff101800, 0x000040c5, 0xff181800, 0x000061c5, + 0xff201800, 0x000081c5, 0xff291800, 0x0000a1c5, + 0xff311800, 0x0000c2c5, 0xff391800, 0x0000e2c5, + 0xff411800, 0x000000cd, 0xff4a1800, 0x000020cd, + 0xff521800, 0x000040cd, 0xff5a1800, 0x000061cd, + 0xff621800, 0x000081cd, 0xff6a1800, 0x0000a1cd, + 0xff731800, 0x0000c2cd, 0xff7b1800, 0x0000e2cd, + 0xff831800, 0x000000d5, 0xff8b1800, 0x000020d5, + 0xff941800, 0x000040d5, 0xff9c1800, 0x000061d5, + 0xffa41800, 0x000081d5, 0xffac1800, 0x0000a1d5, + 0xffb41800, 0x0000c2d5, 0xffbd1800, 0x0000e2d5, + 0xffc51800, 0x000000de, 0xffcd1800, 0x000020de, + 0xffd51800, 0x000040de, 0xffde1800, 0x000061de, + 0xffe61800, 0x000081de, 0xffee1800, 0x0000a1de, + 0xfff61800, 0x0000c2de, 0xffff1800, 0x0000e2de, + 0xff001c00, 0x000000e6, 0xff081c00, 0x000020e6, + 0xff101c00, 0x000040e6, 0xff181c00, 0x000061e6, + 0xff201c00, 0x000081e6, 0xff291c00, 0x0000a1e6, + 0xff311c00, 0x0000c2e6, 0xff391c00, 0x0000e2e6, + 0xff411c00, 0x000000ee, 0xff4a1c00, 0x000020ee, + 0xff521c00, 0x000040ee, 0xff5a1c00, 0x000061ee, + 0xff621c00, 0x000081ee, 0xff6a1c00, 0x0000a1ee, + 0xff731c00, 0x0000c2ee, 0xff7b1c00, 0x0000e2ee, + 0xff831c00, 0x000000f6, 0xff8b1c00, 0x000020f6, + 0xff941c00, 0x000040f6, 0xff9c1c00, 0x000061f6, + 0xffa41c00, 0x000081f6, 0xffac1c00, 0x0000a1f6, + 0xffb41c00, 0x0000c2f6, 0xffbd1c00, 0x0000e2f6, + 0xffc51c00, 0x000000ff, 0xffcd1c00, 0x000020ff, + 0xffd51c00, 0x000040ff, 0xffde1c00, 0x000061ff, + 0xffe61c00, 0x000081ff, 0xffee1c00, 0x0000a1ff, + 0xfff61c00, 0x0000c2ff, 0xffff1c00, 0x0000e2ff +}; +static void Blit_RGB565_ABGR8888(SDL_BlitInfo *info) +{ + Blit_RGB565_32(info, RGB565_ABGR8888_LUT); +} + +/* Special optimized blit for RGB 5-6-5 --> RGBA 8-8-8-8 */ +static const Uint32 RGB565_RGBA8888_LUT[512] = { + 0x000000ff, 0x00000000, 0x000008ff, 0x00200000, + 0x000010ff, 0x00400000, 0x000018ff, 0x00610000, + 0x000020ff, 0x00810000, 0x000029ff, 0x00a10000, + 0x000031ff, 0x00c20000, 0x000039ff, 0x00e20000, + 0x000041ff, 0x08000000, 0x00004aff, 0x08200000, + 0x000052ff, 0x08400000, 0x00005aff, 0x08610000, + 0x000062ff, 0x08810000, 0x00006aff, 0x08a10000, + 0x000073ff, 0x08c20000, 0x00007bff, 0x08e20000, + 0x000083ff, 0x10000000, 0x00008bff, 0x10200000, + 0x000094ff, 0x10400000, 0x00009cff, 0x10610000, + 0x0000a4ff, 0x10810000, 0x0000acff, 0x10a10000, + 0x0000b4ff, 0x10c20000, 0x0000bdff, 0x10e20000, + 0x0000c5ff, 0x18000000, 0x0000cdff, 0x18200000, + 0x0000d5ff, 0x18400000, 0x0000deff, 0x18610000, + 0x0000e6ff, 0x18810000, 0x0000eeff, 0x18a10000, + 0x0000f6ff, 0x18c20000, 0x0000ffff, 0x18e20000, + 0x000400ff, 0x20000000, 0x000408ff, 0x20200000, + 0x000410ff, 0x20400000, 0x000418ff, 0x20610000, + 0x000420ff, 0x20810000, 0x000429ff, 0x20a10000, + 0x000431ff, 0x20c20000, 0x000439ff, 0x20e20000, + 0x000441ff, 0x29000000, 0x00044aff, 0x29200000, + 0x000452ff, 0x29400000, 0x00045aff, 0x29610000, + 0x000462ff, 0x29810000, 0x00046aff, 0x29a10000, + 0x000473ff, 0x29c20000, 0x00047bff, 0x29e20000, + 0x000483ff, 0x31000000, 0x00048bff, 0x31200000, + 0x000494ff, 0x31400000, 0x00049cff, 0x31610000, + 0x0004a4ff, 0x31810000, 0x0004acff, 0x31a10000, + 0x0004b4ff, 0x31c20000, 0x0004bdff, 0x31e20000, + 0x0004c5ff, 0x39000000, 0x0004cdff, 0x39200000, + 0x0004d5ff, 0x39400000, 0x0004deff, 0x39610000, + 0x0004e6ff, 0x39810000, 0x0004eeff, 0x39a10000, + 0x0004f6ff, 0x39c20000, 0x0004ffff, 0x39e20000, + 0x000800ff, 0x41000000, 0x000808ff, 0x41200000, + 0x000810ff, 0x41400000, 0x000818ff, 0x41610000, + 0x000820ff, 0x41810000, 0x000829ff, 0x41a10000, + 0x000831ff, 0x41c20000, 0x000839ff, 0x41e20000, + 0x000841ff, 0x4a000000, 0x00084aff, 0x4a200000, + 0x000852ff, 0x4a400000, 0x00085aff, 0x4a610000, + 0x000862ff, 0x4a810000, 0x00086aff, 0x4aa10000, + 0x000873ff, 0x4ac20000, 0x00087bff, 0x4ae20000, + 0x000883ff, 0x52000000, 0x00088bff, 0x52200000, + 0x000894ff, 0x52400000, 0x00089cff, 0x52610000, + 0x0008a4ff, 0x52810000, 0x0008acff, 0x52a10000, + 0x0008b4ff, 0x52c20000, 0x0008bdff, 0x52e20000, + 0x0008c5ff, 0x5a000000, 0x0008cdff, 0x5a200000, + 0x0008d5ff, 0x5a400000, 0x0008deff, 0x5a610000, + 0x0008e6ff, 0x5a810000, 0x0008eeff, 0x5aa10000, + 0x0008f6ff, 0x5ac20000, 0x0008ffff, 0x5ae20000, + 0x000c00ff, 0x62000000, 0x000c08ff, 0x62200000, + 0x000c10ff, 0x62400000, 0x000c18ff, 0x62610000, + 0x000c20ff, 0x62810000, 0x000c29ff, 0x62a10000, + 0x000c31ff, 0x62c20000, 0x000c39ff, 0x62e20000, + 0x000c41ff, 0x6a000000, 0x000c4aff, 0x6a200000, + 0x000c52ff, 0x6a400000, 0x000c5aff, 0x6a610000, + 0x000c62ff, 0x6a810000, 0x000c6aff, 0x6aa10000, + 0x000c73ff, 0x6ac20000, 0x000c7bff, 0x6ae20000, + 0x000c83ff, 0x73000000, 0x000c8bff, 0x73200000, + 0x000c94ff, 0x73400000, 0x000c9cff, 0x73610000, + 0x000ca4ff, 0x73810000, 0x000cacff, 0x73a10000, + 0x000cb4ff, 0x73c20000, 0x000cbdff, 0x73e20000, + 0x000cc5ff, 0x7b000000, 0x000ccdff, 0x7b200000, + 0x000cd5ff, 0x7b400000, 0x000cdeff, 0x7b610000, + 0x000ce6ff, 0x7b810000, 0x000ceeff, 0x7ba10000, + 0x000cf6ff, 0x7bc20000, 0x000cffff, 0x7be20000, + 0x001000ff, 0x83000000, 0x001008ff, 0x83200000, + 0x001010ff, 0x83400000, 0x001018ff, 0x83610000, + 0x001020ff, 0x83810000, 0x001029ff, 0x83a10000, + 0x001031ff, 0x83c20000, 0x001039ff, 0x83e20000, + 0x001041ff, 0x8b000000, 0x00104aff, 0x8b200000, + 0x001052ff, 0x8b400000, 0x00105aff, 0x8b610000, + 0x001062ff, 0x8b810000, 0x00106aff, 0x8ba10000, + 0x001073ff, 0x8bc20000, 0x00107bff, 0x8be20000, + 0x001083ff, 0x94000000, 0x00108bff, 0x94200000, + 0x001094ff, 0x94400000, 0x00109cff, 0x94610000, + 0x0010a4ff, 0x94810000, 0x0010acff, 0x94a10000, + 0x0010b4ff, 0x94c20000, 0x0010bdff, 0x94e20000, + 0x0010c5ff, 0x9c000000, 0x0010cdff, 0x9c200000, + 0x0010d5ff, 0x9c400000, 0x0010deff, 0x9c610000, + 0x0010e6ff, 0x9c810000, 0x0010eeff, 0x9ca10000, + 0x0010f6ff, 0x9cc20000, 0x0010ffff, 0x9ce20000, + 0x001400ff, 0xa4000000, 0x001408ff, 0xa4200000, + 0x001410ff, 0xa4400000, 0x001418ff, 0xa4610000, + 0x001420ff, 0xa4810000, 0x001429ff, 0xa4a10000, + 0x001431ff, 0xa4c20000, 0x001439ff, 0xa4e20000, + 0x001441ff, 0xac000000, 0x00144aff, 0xac200000, + 0x001452ff, 0xac400000, 0x00145aff, 0xac610000, + 0x001462ff, 0xac810000, 0x00146aff, 0xaca10000, + 0x001473ff, 0xacc20000, 0x00147bff, 0xace20000, + 0x001483ff, 0xb4000000, 0x00148bff, 0xb4200000, + 0x001494ff, 0xb4400000, 0x00149cff, 0xb4610000, + 0x0014a4ff, 0xb4810000, 0x0014acff, 0xb4a10000, + 0x0014b4ff, 0xb4c20000, 0x0014bdff, 0xb4e20000, + 0x0014c5ff, 0xbd000000, 0x0014cdff, 0xbd200000, + 0x0014d5ff, 0xbd400000, 0x0014deff, 0xbd610000, + 0x0014e6ff, 0xbd810000, 0x0014eeff, 0xbda10000, + 0x0014f6ff, 0xbdc20000, 0x0014ffff, 0xbde20000, + 0x001800ff, 0xc5000000, 0x001808ff, 0xc5200000, + 0x001810ff, 0xc5400000, 0x001818ff, 0xc5610000, + 0x001820ff, 0xc5810000, 0x001829ff, 0xc5a10000, + 0x001831ff, 0xc5c20000, 0x001839ff, 0xc5e20000, + 0x001841ff, 0xcd000000, 0x00184aff, 0xcd200000, + 0x001852ff, 0xcd400000, 0x00185aff, 0xcd610000, + 0x001862ff, 0xcd810000, 0x00186aff, 0xcda10000, + 0x001873ff, 0xcdc20000, 0x00187bff, 0xcde20000, + 0x001883ff, 0xd5000000, 0x00188bff, 0xd5200000, + 0x001894ff, 0xd5400000, 0x00189cff, 0xd5610000, + 0x0018a4ff, 0xd5810000, 0x0018acff, 0xd5a10000, + 0x0018b4ff, 0xd5c20000, 0x0018bdff, 0xd5e20000, + 0x0018c5ff, 0xde000000, 0x0018cdff, 0xde200000, + 0x0018d5ff, 0xde400000, 0x0018deff, 0xde610000, + 0x0018e6ff, 0xde810000, 0x0018eeff, 0xdea10000, + 0x0018f6ff, 0xdec20000, 0x0018ffff, 0xdee20000, + 0x001c00ff, 0xe6000000, 0x001c08ff, 0xe6200000, + 0x001c10ff, 0xe6400000, 0x001c18ff, 0xe6610000, + 0x001c20ff, 0xe6810000, 0x001c29ff, 0xe6a10000, + 0x001c31ff, 0xe6c20000, 0x001c39ff, 0xe6e20000, + 0x001c41ff, 0xee000000, 0x001c4aff, 0xee200000, + 0x001c52ff, 0xee400000, 0x001c5aff, 0xee610000, + 0x001c62ff, 0xee810000, 0x001c6aff, 0xeea10000, + 0x001c73ff, 0xeec20000, 0x001c7bff, 0xeee20000, + 0x001c83ff, 0xf6000000, 0x001c8bff, 0xf6200000, + 0x001c94ff, 0xf6400000, 0x001c9cff, 0xf6610000, + 0x001ca4ff, 0xf6810000, 0x001cacff, 0xf6a10000, + 0x001cb4ff, 0xf6c20000, 0x001cbdff, 0xf6e20000, + 0x001cc5ff, 0xff000000, 0x001ccdff, 0xff200000, + 0x001cd5ff, 0xff400000, 0x001cdeff, 0xff610000, + 0x001ce6ff, 0xff810000, 0x001ceeff, 0xffa10000, + 0x001cf6ff, 0xffc20000, 0x001cffff, 0xffe20000, +}; +static void Blit_RGB565_RGBA8888(SDL_BlitInfo *info) +{ + Blit_RGB565_32(info, RGB565_RGBA8888_LUT); +} + +/* Special optimized blit for RGB 5-6-5 --> BGRA 8-8-8-8 */ +static const Uint32 RGB565_BGRA8888_LUT[512] = { + 0x00000000, 0x000000ff, 0x08000000, 0x002000ff, + 0x10000000, 0x004000ff, 0x18000000, 0x006100ff, + 0x20000000, 0x008100ff, 0x29000000, 0x00a100ff, + 0x31000000, 0x00c200ff, 0x39000000, 0x00e200ff, + 0x41000000, 0x000008ff, 0x4a000000, 0x002008ff, + 0x52000000, 0x004008ff, 0x5a000000, 0x006108ff, + 0x62000000, 0x008108ff, 0x6a000000, 0x00a108ff, + 0x73000000, 0x00c208ff, 0x7b000000, 0x00e208ff, + 0x83000000, 0x000010ff, 0x8b000000, 0x002010ff, + 0x94000000, 0x004010ff, 0x9c000000, 0x006110ff, + 0xa4000000, 0x008110ff, 0xac000000, 0x00a110ff, + 0xb4000000, 0x00c210ff, 0xbd000000, 0x00e210ff, + 0xc5000000, 0x000018ff, 0xcd000000, 0x002018ff, + 0xd5000000, 0x004018ff, 0xde000000, 0x006118ff, + 0xe6000000, 0x008118ff, 0xee000000, 0x00a118ff, + 0xf6000000, 0x00c218ff, 0xff000000, 0x00e218ff, + 0x00040000, 0x000020ff, 0x08040000, 0x002020ff, + 0x10040000, 0x004020ff, 0x18040000, 0x006120ff, + 0x20040000, 0x008120ff, 0x29040000, 0x00a120ff, + 0x31040000, 0x00c220ff, 0x39040000, 0x00e220ff, + 0x41040000, 0x000029ff, 0x4a040000, 0x002029ff, + 0x52040000, 0x004029ff, 0x5a040000, 0x006129ff, + 0x62040000, 0x008129ff, 0x6a040000, 0x00a129ff, + 0x73040000, 0x00c229ff, 0x7b040000, 0x00e229ff, + 0x83040000, 0x000031ff, 0x8b040000, 0x002031ff, + 0x94040000, 0x004031ff, 0x9c040000, 0x006131ff, + 0xa4040000, 0x008131ff, 0xac040000, 0x00a131ff, + 0xb4040000, 0x00c231ff, 0xbd040000, 0x00e231ff, + 0xc5040000, 0x000039ff, 0xcd040000, 0x002039ff, + 0xd5040000, 0x004039ff, 0xde040000, 0x006139ff, + 0xe6040000, 0x008139ff, 0xee040000, 0x00a139ff, + 0xf6040000, 0x00c239ff, 0xff040000, 0x00e239ff, + 0x00080000, 0x000041ff, 0x08080000, 0x002041ff, + 0x10080000, 0x004041ff, 0x18080000, 0x006141ff, + 0x20080000, 0x008141ff, 0x29080000, 0x00a141ff, + 0x31080000, 0x00c241ff, 0x39080000, 0x00e241ff, + 0x41080000, 0x00004aff, 0x4a080000, 0x00204aff, + 0x52080000, 0x00404aff, 0x5a080000, 0x00614aff, + 0x62080000, 0x00814aff, 0x6a080000, 0x00a14aff, + 0x73080000, 0x00c24aff, 0x7b080000, 0x00e24aff, + 0x83080000, 0x000052ff, 0x8b080000, 0x002052ff, + 0x94080000, 0x004052ff, 0x9c080000, 0x006152ff, + 0xa4080000, 0x008152ff, 0xac080000, 0x00a152ff, + 0xb4080000, 0x00c252ff, 0xbd080000, 0x00e252ff, + 0xc5080000, 0x00005aff, 0xcd080000, 0x00205aff, + 0xd5080000, 0x00405aff, 0xde080000, 0x00615aff, + 0xe6080000, 0x00815aff, 0xee080000, 0x00a15aff, + 0xf6080000, 0x00c25aff, 0xff080000, 0x00e25aff, + 0x000c0000, 0x000062ff, 0x080c0000, 0x002062ff, + 0x100c0000, 0x004062ff, 0x180c0000, 0x006162ff, + 0x200c0000, 0x008162ff, 0x290c0000, 0x00a162ff, + 0x310c0000, 0x00c262ff, 0x390c0000, 0x00e262ff, + 0x410c0000, 0x00006aff, 0x4a0c0000, 0x00206aff, + 0x520c0000, 0x00406aff, 0x5a0c0000, 0x00616aff, + 0x620c0000, 0x00816aff, 0x6a0c0000, 0x00a16aff, + 0x730c0000, 0x00c26aff, 0x7b0c0000, 0x00e26aff, + 0x830c0000, 0x000073ff, 0x8b0c0000, 0x002073ff, + 0x940c0000, 0x004073ff, 0x9c0c0000, 0x006173ff, + 0xa40c0000, 0x008173ff, 0xac0c0000, 0x00a173ff, + 0xb40c0000, 0x00c273ff, 0xbd0c0000, 0x00e273ff, + 0xc50c0000, 0x00007bff, 0xcd0c0000, 0x00207bff, + 0xd50c0000, 0x00407bff, 0xde0c0000, 0x00617bff, + 0xe60c0000, 0x00817bff, 0xee0c0000, 0x00a17bff, + 0xf60c0000, 0x00c27bff, 0xff0c0000, 0x00e27bff, + 0x00100000, 0x000083ff, 0x08100000, 0x002083ff, + 0x10100000, 0x004083ff, 0x18100000, 0x006183ff, + 0x20100000, 0x008183ff, 0x29100000, 0x00a183ff, + 0x31100000, 0x00c283ff, 0x39100000, 0x00e283ff, + 0x41100000, 0x00008bff, 0x4a100000, 0x00208bff, + 0x52100000, 0x00408bff, 0x5a100000, 0x00618bff, + 0x62100000, 0x00818bff, 0x6a100000, 0x00a18bff, + 0x73100000, 0x00c28bff, 0x7b100000, 0x00e28bff, + 0x83100000, 0x000094ff, 0x8b100000, 0x002094ff, + 0x94100000, 0x004094ff, 0x9c100000, 0x006194ff, + 0xa4100000, 0x008194ff, 0xac100000, 0x00a194ff, + 0xb4100000, 0x00c294ff, 0xbd100000, 0x00e294ff, + 0xc5100000, 0x00009cff, 0xcd100000, 0x00209cff, + 0xd5100000, 0x00409cff, 0xde100000, 0x00619cff, + 0xe6100000, 0x00819cff, 0xee100000, 0x00a19cff, + 0xf6100000, 0x00c29cff, 0xff100000, 0x00e29cff, + 0x00140000, 0x0000a4ff, 0x08140000, 0x0020a4ff, + 0x10140000, 0x0040a4ff, 0x18140000, 0x0061a4ff, + 0x20140000, 0x0081a4ff, 0x29140000, 0x00a1a4ff, + 0x31140000, 0x00c2a4ff, 0x39140000, 0x00e2a4ff, + 0x41140000, 0x0000acff, 0x4a140000, 0x0020acff, + 0x52140000, 0x0040acff, 0x5a140000, 0x0061acff, + 0x62140000, 0x0081acff, 0x6a140000, 0x00a1acff, + 0x73140000, 0x00c2acff, 0x7b140000, 0x00e2acff, + 0x83140000, 0x0000b4ff, 0x8b140000, 0x0020b4ff, + 0x94140000, 0x0040b4ff, 0x9c140000, 0x0061b4ff, + 0xa4140000, 0x0081b4ff, 0xac140000, 0x00a1b4ff, + 0xb4140000, 0x00c2b4ff, 0xbd140000, 0x00e2b4ff, + 0xc5140000, 0x0000bdff, 0xcd140000, 0x0020bdff, + 0xd5140000, 0x0040bdff, 0xde140000, 0x0061bdff, + 0xe6140000, 0x0081bdff, 0xee140000, 0x00a1bdff, + 0xf6140000, 0x00c2bdff, 0xff140000, 0x00e2bdff, + 0x00180000, 0x0000c5ff, 0x08180000, 0x0020c5ff, + 0x10180000, 0x0040c5ff, 0x18180000, 0x0061c5ff, + 0x20180000, 0x0081c5ff, 0x29180000, 0x00a1c5ff, + 0x31180000, 0x00c2c5ff, 0x39180000, 0x00e2c5ff, + 0x41180000, 0x0000cdff, 0x4a180000, 0x0020cdff, + 0x52180000, 0x0040cdff, 0x5a180000, 0x0061cdff, + 0x62180000, 0x0081cdff, 0x6a180000, 0x00a1cdff, + 0x73180000, 0x00c2cdff, 0x7b180000, 0x00e2cdff, + 0x83180000, 0x0000d5ff, 0x8b180000, 0x0020d5ff, + 0x94180000, 0x0040d5ff, 0x9c180000, 0x0061d5ff, + 0xa4180000, 0x0081d5ff, 0xac180000, 0x00a1d5ff, + 0xb4180000, 0x00c2d5ff, 0xbd180000, 0x00e2d5ff, + 0xc5180000, 0x0000deff, 0xcd180000, 0x0020deff, + 0xd5180000, 0x0040deff, 0xde180000, 0x0061deff, + 0xe6180000, 0x0081deff, 0xee180000, 0x00a1deff, + 0xf6180000, 0x00c2deff, 0xff180000, 0x00e2deff, + 0x001c0000, 0x0000e6ff, 0x081c0000, 0x0020e6ff, + 0x101c0000, 0x0040e6ff, 0x181c0000, 0x0061e6ff, + 0x201c0000, 0x0081e6ff, 0x291c0000, 0x00a1e6ff, + 0x311c0000, 0x00c2e6ff, 0x391c0000, 0x00e2e6ff, + 0x411c0000, 0x0000eeff, 0x4a1c0000, 0x0020eeff, + 0x521c0000, 0x0040eeff, 0x5a1c0000, 0x0061eeff, + 0x621c0000, 0x0081eeff, 0x6a1c0000, 0x00a1eeff, + 0x731c0000, 0x00c2eeff, 0x7b1c0000, 0x00e2eeff, + 0x831c0000, 0x0000f6ff, 0x8b1c0000, 0x0020f6ff, + 0x941c0000, 0x0040f6ff, 0x9c1c0000, 0x0061f6ff, + 0xa41c0000, 0x0081f6ff, 0xac1c0000, 0x00a1f6ff, + 0xb41c0000, 0x00c2f6ff, 0xbd1c0000, 0x00e2f6ff, + 0xc51c0000, 0x0000ffff, 0xcd1c0000, 0x0020ffff, + 0xd51c0000, 0x0040ffff, 0xde1c0000, 0x0061ffff, + 0xe61c0000, 0x0081ffff, 0xee1c0000, 0x00a1ffff, + 0xf61c0000, 0x00c2ffff, 0xff1c0000, 0x00e2ffff +}; +static void Blit_RGB565_BGRA8888(SDL_BlitInfo *info) +{ + Blit_RGB565_32(info, RGB565_BGRA8888_LUT); +} + +/* Special optimized blit for RGB 8-8-8 --> RGB 3-3-2 */ +#ifndef RGB888_RGB332 +#define RGB888_RGB332(dst, src) { \ + dst = (((src)&0x00E00000)>>16)| \ + (((src)&0x0000E000)>>11)| \ + (((src)&0x000000C0)>>6); \ +} +#endif +static void Blit_RGB888_index8_map(SDL_BlitInfo *info) +{ +#ifndef USE_DUFFS_LOOP + int c; +#endif + int Pixel; + int width, height; + Uint32 *src; + const Uint8 *map; + Uint8 *dst; + int srcskip, dstskip; + + /* Set up some basic variables */ + width = info->d_width; + height = info->d_height; + src = (Uint32 *)info->s_pixels; + srcskip = info->s_skip/4; + dst = info->d_pixels; + dstskip = info->d_skip; + map = info->table; + +#ifdef USE_DUFFS_LOOP + while ( height-- ) { + DUFFS_LOOP( + RGB888_RGB332(Pixel, *src); + *dst++ = map[Pixel]; + ++src; + , width); + src += srcskip; + dst += dstskip; + } +#else + while ( height-- ) { + for ( c=width/4; c; --c ) { + /* Pack RGB into 8bit pixel */ + RGB888_RGB332(Pixel, *src); + *dst++ = map[Pixel]; + ++src; + RGB888_RGB332(Pixel, *src); + *dst++ = map[Pixel]; + ++src; + RGB888_RGB332(Pixel, *src); + *dst++ = map[Pixel]; + ++src; + RGB888_RGB332(Pixel, *src); + *dst++ = map[Pixel]; + ++src; + } + switch ( width & 3 ) { + case 3: + RGB888_RGB332(Pixel, *src); + *dst++ = map[Pixel]; + ++src; + case 2: + RGB888_RGB332(Pixel, *src); + *dst++ = map[Pixel]; + ++src; + case 1: + RGB888_RGB332(Pixel, *src); + *dst++ = map[Pixel]; + ++src; + } + src += srcskip; + dst += dstskip; + } +#endif /* USE_DUFFS_LOOP */ +} +static void BlitNto1(SDL_BlitInfo *info) +{ +#ifndef USE_DUFFS_LOOP + int c; +#endif + int width, height; + Uint8 *src; + const Uint8 *map; + Uint8 *dst; + int srcskip, dstskip; + int srcbpp; + Uint32 Pixel; + int sR, sG, sB; + SDL_PixelFormat *srcfmt; + + /* Set up some basic variables */ + width = info->d_width; + height = info->d_height; + src = info->s_pixels; + srcskip = info->s_skip; + dst = info->d_pixels; + dstskip = info->d_skip; + map = info->table; + srcfmt = info->src; + srcbpp = srcfmt->BytesPerPixel; + + if ( map == NULL ) { + while ( height-- ) { +#ifdef USE_DUFFS_LOOP + DUFFS_LOOP( + DISEMBLE_RGB(src, srcbpp, srcfmt, Pixel, + sR, sG, sB); + if ( 1 ) { + /* Pack RGB into 8bit pixel */ + *dst = ((sR>>5)<<(3+2))| + ((sG>>5)<<(2)) | + ((sB>>6)<<(0)) ; + } + dst++; + src += srcbpp; + , width); +#else + for ( c=width; c; --c ) { + DISEMBLE_RGB(src, srcbpp, srcfmt, Pixel, + sR, sG, sB); + if ( 1 ) { + /* Pack RGB into 8bit pixel */ + *dst = ((sR>>5)<<(3+2))| + ((sG>>5)<<(2)) | + ((sB>>6)<<(0)) ; + } + dst++; + src += srcbpp; + } +#endif + src += srcskip; + dst += dstskip; + } + } else { + while ( height-- ) { +#ifdef USE_DUFFS_LOOP + DUFFS_LOOP( + DISEMBLE_RGB(src, srcbpp, srcfmt, Pixel, + sR, sG, sB); + if ( 1 ) { + /* Pack RGB into 8bit pixel */ + *dst = map[((sR>>5)<<(3+2))| + ((sG>>5)<<(2)) | + ((sB>>6)<<(0)) ]; + } + dst++; + src += srcbpp; + , width); +#else + for ( c=width; c; --c ) { + DISEMBLE_RGB(src, srcbpp, srcfmt, Pixel, + sR, sG, sB); + if ( 1 ) { + /* Pack RGB into 8bit pixel */ + *dst = map[((sR>>5)<<(3+2))| + ((sG>>5)<<(2)) | + ((sB>>6)<<(0)) ]; + } + dst++; + src += srcbpp; + } +#endif /* USE_DUFFS_LOOP */ + src += srcskip; + dst += dstskip; + } + } +} + +/* blits 32 bit RGB<->RGBA with both surfaces having the same R,G,B fields */ +static void Blit4to4MaskAlpha(SDL_BlitInfo *info) +{ + int width = info->d_width; + int height = info->d_height; + Uint32 *src = (Uint32 *)info->s_pixels; + int srcskip = info->s_skip; + Uint32 *dst = (Uint32 *)info->d_pixels; + int dstskip = info->d_skip; + SDL_PixelFormat *srcfmt = info->src; + SDL_PixelFormat *dstfmt = info->dst; + + if (dstfmt->Amask) { + /* RGB->RGBA, SET_ALPHA */ + Uint32 mask = (srcfmt->alpha >> dstfmt->Aloss) << dstfmt->Ashift; + + while ( height-- ) { + DUFFS_LOOP( + { + *dst = *src | mask; + ++dst; + ++src; + }, + width); + src = (Uint32*)((Uint8*)src + srcskip); + dst = (Uint32*)((Uint8*)dst + dstskip); + } + } else { + /* RGBA->RGB, NO_ALPHA */ + Uint32 mask = srcfmt->Rmask | srcfmt->Gmask | srcfmt->Bmask; + + while ( height-- ) { + DUFFS_LOOP( + { + *dst = *src & mask; + ++dst; + ++src; + }, + width); + src = (Uint32*)((Uint8*)src + srcskip); + dst = (Uint32*)((Uint8*)dst + dstskip); + } + } +} + +static void BlitNtoN(SDL_BlitInfo *info) +{ + int width = info->d_width; + int height = info->d_height; + Uint8 *src = info->s_pixels; + int srcskip = info->s_skip; + Uint8 *dst = info->d_pixels; + int dstskip = info->d_skip; + SDL_PixelFormat *srcfmt = info->src; + int srcbpp = srcfmt->BytesPerPixel; + SDL_PixelFormat *dstfmt = info->dst; + int dstbpp = dstfmt->BytesPerPixel; + unsigned alpha = dstfmt->Amask ? srcfmt->alpha : 0; + + while ( height-- ) { + DUFFS_LOOP( + { + Uint32 Pixel; + unsigned sR; + unsigned sG; + unsigned sB; + DISEMBLE_RGB(src, srcbpp, srcfmt, Pixel, sR, sG, sB); + ASSEMBLE_RGBA(dst, dstbpp, dstfmt, sR, sG, sB, alpha); + dst += dstbpp; + src += srcbpp; + }, + width); + src += srcskip; + dst += dstskip; + } +} + +static void BlitNtoNCopyAlpha(SDL_BlitInfo *info) +{ + int width = info->d_width; + int height = info->d_height; + Uint8 *src = info->s_pixels; + int srcskip = info->s_skip; + Uint8 *dst = info->d_pixels; + int dstskip = info->d_skip; + SDL_PixelFormat *srcfmt = info->src; + int srcbpp = srcfmt->BytesPerPixel; + SDL_PixelFormat *dstfmt = info->dst; + int dstbpp = dstfmt->BytesPerPixel; + int c; + + /* FIXME: should map alpha to [0..255] correctly! */ + while ( height-- ) { + for ( c=width; c; --c ) { + Uint32 Pixel; + unsigned sR, sG, sB, sA; + DISEMBLE_RGBA(src, srcbpp, srcfmt, Pixel, + sR, sG, sB, sA); + ASSEMBLE_RGBA(dst, dstbpp, dstfmt, + sR, sG, sB, sA); + dst += dstbpp; + src += srcbpp; + } + src += srcskip; + dst += dstskip; + } +} + +static void BlitNto1Key(SDL_BlitInfo *info) +{ + int width = info->d_width; + int height = info->d_height; + Uint8 *src = info->s_pixels; + int srcskip = info->s_skip; + Uint8 *dst = info->d_pixels; + int dstskip = info->d_skip; + SDL_PixelFormat *srcfmt = info->src; + const Uint8 *palmap = info->table; + Uint32 ckey = srcfmt->colorkey; + Uint32 rgbmask = ~srcfmt->Amask; + int srcbpp; + Uint32 Pixel; + unsigned sR, sG, sB; + + /* Set up some basic variables */ + srcbpp = srcfmt->BytesPerPixel; + ckey &= rgbmask; + + if ( palmap == NULL ) { + while ( height-- ) { + DUFFS_LOOP( + { + DISEMBLE_RGB(src, srcbpp, srcfmt, Pixel, + sR, sG, sB); + if ( (Pixel & rgbmask) != ckey ) { + /* Pack RGB into 8bit pixel */ + *dst = (Uint8)(((sR>>5)<<(3+2))| + ((sG>>5)<<(2)) | + ((sB>>6)<<(0))); + } + dst++; + src += srcbpp; + }, + width); + src += srcskip; + dst += dstskip; + } + } else { + while ( height-- ) { + DUFFS_LOOP( + { + DISEMBLE_RGB(src, srcbpp, srcfmt, Pixel, + sR, sG, sB); + if ( (Pixel & rgbmask) != ckey ) { + /* Pack RGB into 8bit pixel */ + *dst = (Uint8)palmap[((sR>>5)<<(3+2))| + ((sG>>5)<<(2)) | + ((sB>>6)<<(0)) ]; + } + dst++; + src += srcbpp; + }, + width); + src += srcskip; + dst += dstskip; + } + } +} + +static void Blit2to2Key(SDL_BlitInfo *info) +{ + int width = info->d_width; + int height = info->d_height; + Uint16 *srcp = (Uint16 *)info->s_pixels; + int srcskip = info->s_skip; + Uint16 *dstp = (Uint16 *)info->d_pixels; + int dstskip = info->d_skip; + Uint32 ckey = info->src->colorkey; + Uint32 rgbmask = ~info->src->Amask; + + /* Set up some basic variables */ + srcskip /= 2; + dstskip /= 2; + ckey &= rgbmask; + + while ( height-- ) { + DUFFS_LOOP( + { + if ( (*srcp & rgbmask) != ckey ) { + *dstp = *srcp; + } + dstp++; + srcp++; + }, + width); + srcp += srcskip; + dstp += dstskip; + } +} + +static void BlitNtoNKey(SDL_BlitInfo *info) +{ + int width = info->d_width; + int height = info->d_height; + Uint8 *src = info->s_pixels; + int srcskip = info->s_skip; + Uint8 *dst = info->d_pixels; + int dstskip = info->d_skip; + Uint32 ckey = info->src->colorkey; + SDL_PixelFormat *srcfmt = info->src; + SDL_PixelFormat *dstfmt = info->dst; + int srcbpp = srcfmt->BytesPerPixel; + int dstbpp = dstfmt->BytesPerPixel; + unsigned alpha = dstfmt->Amask ? srcfmt->alpha : 0; + Uint32 rgbmask = ~srcfmt->Amask; + + /* Set up some basic variables */ + ckey &= rgbmask; + + while ( height-- ) { + DUFFS_LOOP( + { + Uint32 Pixel; + unsigned sR; + unsigned sG; + unsigned sB; + RETRIEVE_RGB_PIXEL(src, srcbpp, Pixel); + if ( (Pixel & rgbmask) != ckey ) { + RGB_FROM_PIXEL(Pixel, srcfmt, sR, sG, sB); + ASSEMBLE_RGBA(dst, dstbpp, dstfmt, + sR, sG, sB, alpha); + } + dst += dstbpp; + src += srcbpp; + }, + width); + src += srcskip; + dst += dstskip; + } +} + +static void BlitNtoNKeyCopyAlpha(SDL_BlitInfo *info) +{ + int width = info->d_width; + int height = info->d_height; + Uint8 *src = info->s_pixels; + int srcskip = info->s_skip; + Uint8 *dst = info->d_pixels; + int dstskip = info->d_skip; + Uint32 ckey = info->src->colorkey; + SDL_PixelFormat *srcfmt = info->src; + SDL_PixelFormat *dstfmt = info->dst; + Uint32 rgbmask = ~srcfmt->Amask; + + Uint8 srcbpp; + Uint8 dstbpp; + Uint32 Pixel; + unsigned sR, sG, sB, sA; + + /* Set up some basic variables */ + srcbpp = srcfmt->BytesPerPixel; + dstbpp = dstfmt->BytesPerPixel; + ckey &= rgbmask; + + /* FIXME: should map alpha to [0..255] correctly! */ + while ( height-- ) { + DUFFS_LOOP( + { + DISEMBLE_RGBA(src, srcbpp, srcfmt, Pixel, + sR, sG, sB, sA); + if ( (Pixel & rgbmask) != ckey ) { + ASSEMBLE_RGBA(dst, dstbpp, dstfmt, + sR, sG, sB, sA); + } + dst += dstbpp; + src += srcbpp; + }, + width); + src += srcskip; + dst += dstskip; + } +} + +/* Normal N to N optimized blitters */ +struct blit_table { + Uint32 srcR, srcG, srcB; + int dstbpp; + Uint32 dstR, dstG, dstB; + Uint32 blit_features; + void *aux_data; + SDL_loblit blitfunc; + enum { NO_ALPHA=1, SET_ALPHA=2, COPY_ALPHA=4 } alpha; +}; +static const struct blit_table normal_blit_1[] = { + /* Default for 8-bit RGB source, an invalid combination */ + { 0,0,0, 0, 0,0,0, 0, NULL, NULL }, +}; +static const struct blit_table normal_blit_2[] = { +#if SDL_HERMES_BLITTERS + { 0x0000F800,0x000007E0,0x0000001F, 2, 0x0000001F,0x000007E0,0x0000F800, + 0, ConvertX86p16_16BGR565, ConvertX86, NO_ALPHA }, + { 0x0000F800,0x000007E0,0x0000001F, 2, 0x00007C00,0x000003E0,0x0000001F, + 0, ConvertX86p16_16RGB555, ConvertX86, NO_ALPHA }, + { 0x0000F800,0x000007E0,0x0000001F, 2, 0x0000001F,0x000003E0,0x00007C00, + 0, ConvertX86p16_16BGR555, ConvertX86, NO_ALPHA }, +#elif SDL_ALTIVEC_BLITTERS + /* has-altivec */ + { 0x0000F800,0x000007E0,0x0000001F, 4, 0x00000000,0x00000000,0x00000000, + 2, NULL, Blit_RGB565_32Altivec, NO_ALPHA | COPY_ALPHA | SET_ALPHA }, + { 0x00007C00,0x000003E0,0x0000001F, 4, 0x00000000,0x00000000,0x00000000, + 2, NULL, Blit_RGB555_32Altivec, NO_ALPHA | COPY_ALPHA | SET_ALPHA }, +#endif + { 0x0000F800,0x000007E0,0x0000001F, 4, 0x00FF0000,0x0000FF00,0x000000FF, + 0, NULL, Blit_RGB565_ARGB8888, SET_ALPHA }, + { 0x0000F800,0x000007E0,0x0000001F, 4, 0x000000FF,0x0000FF00,0x00FF0000, + 0, NULL, Blit_RGB565_ABGR8888, SET_ALPHA }, + { 0x0000F800,0x000007E0,0x0000001F, 4, 0xFF000000,0x00FF0000,0x0000FF00, + 0, NULL, Blit_RGB565_RGBA8888, SET_ALPHA }, + { 0x0000F800,0x000007E0,0x0000001F, 4, 0x0000FF00,0x00FF0000,0xFF000000, + 0, NULL, Blit_RGB565_BGRA8888, SET_ALPHA }, + + /* Default for 16-bit RGB source, used if no other blitter matches */ + { 0,0,0, 0, 0,0,0, 0, NULL, BlitNtoN, 0 } +}; +static const struct blit_table normal_blit_3[] = { + /* Default for 24-bit RGB source, never optimized */ + { 0,0,0, 0, 0,0,0, 0, NULL, BlitNtoN, 0 } +}; +static const struct blit_table normal_blit_4[] = { +#if SDL_HERMES_BLITTERS + { 0x00FF0000,0x0000FF00,0x000000FF, 2, 0x0000F800,0x000007E0,0x0000001F, + 1, ConvertMMXpII32_16RGB565, ConvertMMX, NO_ALPHA }, + { 0x00FF0000,0x0000FF00,0x000000FF, 2, 0x0000F800,0x000007E0,0x0000001F, + 0, ConvertX86p32_16RGB565, ConvertX86, NO_ALPHA }, + { 0x00FF0000,0x0000FF00,0x000000FF, 2, 0x0000001F,0x000007E0,0x0000F800, + 1, ConvertMMXpII32_16BGR565, ConvertMMX, NO_ALPHA }, + { 0x00FF0000,0x0000FF00,0x000000FF, 2, 0x0000001F,0x000007E0,0x0000F800, + 0, ConvertX86p32_16BGR565, ConvertX86, NO_ALPHA }, + { 0x00FF0000,0x0000FF00,0x000000FF, 2, 0x00007C00,0x000003E0,0x0000001F, + 1, ConvertMMXpII32_16RGB555, ConvertMMX, NO_ALPHA }, + { 0x00FF0000,0x0000FF00,0x000000FF, 2, 0x00007C00,0x000003E0,0x0000001F, + 0, ConvertX86p32_16RGB555, ConvertX86, NO_ALPHA }, + { 0x00FF0000,0x0000FF00,0x000000FF, 2, 0x0000001F,0x000003E0,0x00007C00, + 1, ConvertMMXpII32_16BGR555, ConvertMMX, NO_ALPHA }, + { 0x00FF0000,0x0000FF00,0x000000FF, 2, 0x0000001F,0x000003E0,0x00007C00, + 0, ConvertX86p32_16BGR555, ConvertX86, NO_ALPHA }, + { 0x00FF0000,0x0000FF00,0x000000FF, 3, 0x00FF0000,0x0000FF00,0x000000FF, + 1, ConvertMMXpII32_24RGB888, ConvertMMX, NO_ALPHA }, + { 0x00FF0000,0x0000FF00,0x000000FF, 3, 0x00FF0000,0x0000FF00,0x000000FF, + 0, ConvertX86p32_24RGB888, ConvertX86, NO_ALPHA }, + { 0x00FF0000,0x0000FF00,0x000000FF, 3, 0x000000FF,0x0000FF00,0x00FF0000, + 0, ConvertX86p32_24BGR888, ConvertX86, NO_ALPHA }, + { 0x00FF0000,0x0000FF00,0x000000FF, 4, 0x000000FF,0x0000FF00,0x00FF0000, + 0, ConvertX86p32_32BGR888, ConvertX86, NO_ALPHA }, + { 0x00FF0000,0x0000FF00,0x000000FF, 4, 0xFF000000,0x00FF0000,0x0000FF00, + 0, ConvertX86p32_32RGBA888, ConvertX86, NO_ALPHA }, + { 0x00FF0000,0x0000FF00,0x000000FF, 4, 0x0000FF00,0x00FF0000,0xFF000000, + 0, ConvertX86p32_32BGRA888, ConvertX86, NO_ALPHA }, +#else +#if SDL_ALTIVEC_BLITTERS + /* has-altivec | dont-use-prefetch */ + { 0x00000000,0x00000000,0x00000000, 4, 0x00000000,0x00000000,0x00000000, + 6, NULL, ConvertAltivec32to32_noprefetch, NO_ALPHA | COPY_ALPHA | SET_ALPHA }, + /* has-altivec */ + { 0x00000000,0x00000000,0x00000000, 4, 0x00000000,0x00000000,0x00000000, + 2, NULL, ConvertAltivec32to32_prefetch, NO_ALPHA | COPY_ALPHA | SET_ALPHA }, + /* has-altivec */ + { 0x00000000,0x00000000,0x00000000, 2, 0x0000F800,0x000007E0,0x0000001F, + 2, NULL, Blit_RGB888_RGB565Altivec, NO_ALPHA }, +#endif + { 0x00FF0000,0x0000FF00,0x000000FF, 2, 0x0000F800,0x000007E0,0x0000001F, + 0, NULL, Blit_RGB888_RGB565, NO_ALPHA }, + { 0x00FF0000,0x0000FF00,0x000000FF, 2, 0x00007C00,0x000003E0,0x0000001F, + 0, NULL, Blit_RGB888_RGB555, NO_ALPHA }, +#endif + /* Default for 32-bit RGB source, used if no other blitter matches */ + { 0,0,0, 0, 0,0,0, 0, NULL, BlitNtoN, 0 } +}; +static const struct blit_table *normal_blit[] = { + normal_blit_1, normal_blit_2, normal_blit_3, normal_blit_4 +}; + +/* Mask matches table, or table entry is zero */ +#define MASKOK(x, y) (((x) == (y)) || ((y) == 0x00000000)) + +SDL_loblit SDL_CalculateBlitN(SDL_Surface *surface, int blit_index) +{ + struct private_swaccel *sdata; + SDL_PixelFormat *srcfmt; + SDL_PixelFormat *dstfmt; + const struct blit_table *table; + int which; + SDL_loblit blitfun; + + /* Set up data for choosing the blit */ + sdata = surface->map->sw_data; + srcfmt = surface->format; + dstfmt = surface->map->dst->format; + + if ( blit_index & 2 ) { + /* alpha or alpha+colorkey */ + return SDL_CalculateAlphaBlit(surface, blit_index); + } + + /* We don't support destinations less than 8-bits */ + if ( dstfmt->BitsPerPixel < 8 ) { + return(NULL); + } + + if(blit_index == 1) { + /* colorkey blit: Here we don't have too many options, mostly + because RLE is the preferred fast way to deal with this. + If a particular case turns out to be useful we'll add it. */ + + if(srcfmt->BytesPerPixel == 2 + && surface->map->identity) + return Blit2to2Key; + else if(dstfmt->BytesPerPixel == 1) + return BlitNto1Key; + else { +#if SDL_ALTIVEC_BLITTERS + if((srcfmt->BytesPerPixel == 4) && (dstfmt->BytesPerPixel == 4) && SDL_HasAltiVec()) { + return Blit32to32KeyAltivec; + } else +#endif + + if(srcfmt->Amask && dstfmt->Amask) + return BlitNtoNKeyCopyAlpha; + else + return BlitNtoNKey; + } + } + + blitfun = NULL; + if ( dstfmt->BitsPerPixel == 8 ) { + /* We assume 8-bit destinations are palettized */ + if ( (srcfmt->BytesPerPixel == 4) && + (srcfmt->Rmask == 0x00FF0000) && + (srcfmt->Gmask == 0x0000FF00) && + (srcfmt->Bmask == 0x000000FF) ) { + if ( surface->map->table ) { + blitfun = Blit_RGB888_index8_map; + } else { +#if SDL_HERMES_BLITTERS + sdata->aux_data = ConvertX86p32_8RGB332; + blitfun = ConvertX86; +#else + blitfun = Blit_RGB888_index8; +#endif + } + } else { + blitfun = BlitNto1; + } + } else { + /* Now the meat, choose the blitter we want */ + int a_need = NO_ALPHA; + if(dstfmt->Amask) + a_need = srcfmt->Amask ? COPY_ALPHA : SET_ALPHA; + table = normal_blit[srcfmt->BytesPerPixel-1]; + for ( which=0; table[which].dstbpp; ++which ) { + if ( MASKOK(srcfmt->Rmask, table[which].srcR) && + MASKOK(srcfmt->Gmask, table[which].srcG) && + MASKOK(srcfmt->Bmask, table[which].srcB) && + MASKOK(dstfmt->Rmask, table[which].dstR) && + MASKOK(dstfmt->Gmask, table[which].dstG) && + MASKOK(dstfmt->Bmask, table[which].dstB) && + dstfmt->BytesPerPixel == table[which].dstbpp && + (a_need & table[which].alpha) == a_need && + ((table[which].blit_features & GetBlitFeatures()) == table[which].blit_features) ) + break; + } + sdata->aux_data = table[which].aux_data; + blitfun = table[which].blitfunc; + + if(blitfun == BlitNtoN) { /* default C fallback catch-all. Slow! */ + /* Fastpath C fallback: 32bit RGB<->RGBA blit with matching RGB */ + if ( srcfmt->BytesPerPixel == 4 && dstfmt->BytesPerPixel == 4 && + srcfmt->Rmask == dstfmt->Rmask && + srcfmt->Gmask == dstfmt->Gmask && + srcfmt->Bmask == dstfmt->Bmask ) { + blitfun = Blit4to4MaskAlpha; + } else if ( a_need == COPY_ALPHA ) { + blitfun = BlitNtoNCopyAlpha; + } + } + } + +#ifdef DEBUG_ASM +#if SDL_HERMES_BLITTERS + if ( blitfun == ConvertMMX ) + fprintf(stderr, "Using mmx blit\n"); + else + if ( blitfun == ConvertX86 ) + fprintf(stderr, "Using asm blit\n"); + else +#endif + if ( (blitfun == BlitNtoN) || (blitfun == BlitNto1) ) + fprintf(stderr, "Using C blit\n"); + else + fprintf(stderr, "Using optimized C blit\n"); +#endif /* DEBUG_ASM */ + + return(blitfun); +} diff --git a/3rdparty/SDL/src/video/SDL_bmp.c b/3rdparty/SDL/src/video/SDL_bmp.c new file mode 100644 index 0000000..d56cfd8 --- /dev/null +++ b/3rdparty/SDL/src/video/SDL_bmp.c @@ -0,0 +1,549 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* + Code to load and save surfaces in Windows BMP format. + + Why support BMP format? Well, it's a native format for Windows, and + most image processing programs can read and write it. It would be nice + to be able to have at least one image format that we can natively load + and save, and since PNG is so complex that it would bloat the library, + BMP is a good alternative. + + This code currently supports Win32 DIBs in uncompressed 8 and 24 bpp. +*/ + +#include "SDL_video.h" +#include "SDL_endian.h" + +/* Compression encodings for BMP files */ +#ifndef BI_RGB +#define BI_RGB 0 +#define BI_RLE8 1 +#define BI_RLE4 2 +#define BI_BITFIELDS 3 +#endif + + +SDL_Surface * SDL_LoadBMP_RW (SDL_RWops *src, int freesrc) +{ + SDL_bool was_error; + long fp_offset = 0; + int bmpPitch; + int i, pad; + SDL_Surface *surface; + Uint32 Rmask; + Uint32 Gmask; + Uint32 Bmask; + SDL_Palette *palette; + Uint8 *bits; + Uint8 *top, *end; + SDL_bool topDown; + int ExpandBMP; + + /* The Win32 BMP file header (14 bytes) */ + char magic[2]; + Uint32 bfSize; + Uint16 bfReserved1; + Uint16 bfReserved2; + Uint32 bfOffBits; + + /* The Win32 BITMAPINFOHEADER struct (40 bytes) */ + Uint32 biSize; + Sint32 biWidth; + Sint32 biHeight; + Uint16 biPlanes; + Uint16 biBitCount; + Uint32 biCompression; + Uint32 biSizeImage; + Sint32 biXPelsPerMeter; + Sint32 biYPelsPerMeter; + Uint32 biClrUsed; + Uint32 biClrImportant; + + /* Make sure we are passed a valid data source */ + surface = NULL; + was_error = SDL_FALSE; + if ( src == NULL ) { + was_error = SDL_TRUE; + goto done; + } + + /* Read in the BMP file header */ + fp_offset = SDL_RWtell(src); + SDL_ClearError(); + if ( SDL_RWread(src, magic, 1, 2) != 2 ) { + SDL_Error(SDL_EFREAD); + was_error = SDL_TRUE; + goto done; + } + if ( SDL_strncmp(magic, "BM", 2) != 0 ) { + SDL_SetError("File is not a Windows BMP file"); + was_error = SDL_TRUE; + goto done; + } + bfSize = SDL_ReadLE32(src); + bfReserved1 = SDL_ReadLE16(src); + bfReserved2 = SDL_ReadLE16(src); + bfOffBits = SDL_ReadLE32(src); + + /* Read the Win32 BITMAPINFOHEADER */ + biSize = SDL_ReadLE32(src); + if ( biSize == 12 ) { + biWidth = (Uint32)SDL_ReadLE16(src); + biHeight = (Uint32)SDL_ReadLE16(src); + biPlanes = SDL_ReadLE16(src); + biBitCount = SDL_ReadLE16(src); + biCompression = BI_RGB; + biSizeImage = 0; + biXPelsPerMeter = 0; + biYPelsPerMeter = 0; + biClrUsed = 0; + biClrImportant = 0; + } else { + biWidth = SDL_ReadLE32(src); + biHeight = SDL_ReadLE32(src); + biPlanes = SDL_ReadLE16(src); + biBitCount = SDL_ReadLE16(src); + biCompression = SDL_ReadLE32(src); + biSizeImage = SDL_ReadLE32(src); + biXPelsPerMeter = SDL_ReadLE32(src); + biYPelsPerMeter = SDL_ReadLE32(src); + biClrUsed = SDL_ReadLE32(src); + biClrImportant = SDL_ReadLE32(src); + } + + /* stop some compiler warnings. */ + (void) bfSize; + (void) bfReserved1; + (void) bfReserved2; + (void) biPlanes; + (void) biSizeImage; + (void) biXPelsPerMeter; + (void) biYPelsPerMeter; + (void) biClrImportant; + + if (biHeight < 0) { + topDown = SDL_TRUE; + biHeight = -biHeight; + } else { + topDown = SDL_FALSE; + } + + /* Check for read error */ + if ( SDL_strcmp(SDL_GetError(), "") != 0 ) { + was_error = SDL_TRUE; + goto done; + } + + /* Expand 1 and 4 bit bitmaps to 8 bits per pixel */ + switch (biBitCount) { + case 1: + case 4: + ExpandBMP = biBitCount; + biBitCount = 8; + break; + default: + ExpandBMP = 0; + break; + } + + /* We don't support any BMP compression right now */ + Rmask = Gmask = Bmask = 0; + switch (biCompression) { + case BI_RGB: + /* If there are no masks, use the defaults */ + if ( bfOffBits == (14+biSize) ) { + /* Default values for the BMP format */ + switch (biBitCount) { + case 15: + case 16: + Rmask = 0x7C00; + Gmask = 0x03E0; + Bmask = 0x001F; + break; + case 24: +#if SDL_BYTEORDER == SDL_BIG_ENDIAN + Rmask = 0x000000FF; + Gmask = 0x0000FF00; + Bmask = 0x00FF0000; + break; +#endif + case 32: + Rmask = 0x00FF0000; + Gmask = 0x0000FF00; + Bmask = 0x000000FF; + break; + default: + break; + } + break; + } + /* Fall through -- read the RGB masks */ + + case BI_BITFIELDS: + switch (biBitCount) { + case 15: + case 16: + case 32: + Rmask = SDL_ReadLE32(src); + Gmask = SDL_ReadLE32(src); + Bmask = SDL_ReadLE32(src); + break; + default: + break; + } + break; + default: + SDL_SetError("Compressed BMP files not supported"); + was_error = SDL_TRUE; + goto done; + } + + /* Create a compatible surface, note that the colors are RGB ordered */ + surface = SDL_CreateRGBSurface(SDL_SWSURFACE, + biWidth, biHeight, biBitCount, Rmask, Gmask, Bmask, 0); + if ( surface == NULL ) { + was_error = SDL_TRUE; + goto done; + } + + /* Load the palette, if any */ + palette = (surface->format)->palette; + if ( palette ) { + if ( biClrUsed == 0 ) { + biClrUsed = 1 << biBitCount; + } + if ( biSize == 12 ) { + for ( i = 0; i < (int)biClrUsed; ++i ) { + SDL_RWread(src, &palette->colors[i].b, 1, 1); + SDL_RWread(src, &palette->colors[i].g, 1, 1); + SDL_RWread(src, &palette->colors[i].r, 1, 1); + palette->colors[i].unused = 0; + } + } else { + for ( i = 0; i < (int)biClrUsed; ++i ) { + SDL_RWread(src, &palette->colors[i].b, 1, 1); + SDL_RWread(src, &palette->colors[i].g, 1, 1); + SDL_RWread(src, &palette->colors[i].r, 1, 1); + SDL_RWread(src, &palette->colors[i].unused, 1, 1); + } + } + palette->ncolors = biClrUsed; + } + + /* Read the surface pixels. Note that the bmp image is upside down */ + if ( SDL_RWseek(src, fp_offset+bfOffBits, RW_SEEK_SET) < 0 ) { + SDL_Error(SDL_EFSEEK); + was_error = SDL_TRUE; + goto done; + } + top = (Uint8 *)surface->pixels; + end = (Uint8 *)surface->pixels+(surface->h*surface->pitch); + switch (ExpandBMP) { + case 1: + bmpPitch = (biWidth + 7) >> 3; + pad = (((bmpPitch)%4) ? (4-((bmpPitch)%4)) : 0); + break; + case 4: + bmpPitch = (biWidth + 1) >> 1; + pad = (((bmpPitch)%4) ? (4-((bmpPitch)%4)) : 0); + break; + default: + pad = ((surface->pitch%4) ? + (4-(surface->pitch%4)) : 0); + break; + } + if ( topDown ) { + bits = top; + } else { + bits = end - surface->pitch; + } + while ( bits >= top && bits < end ) { + switch (ExpandBMP) { + case 1: + case 4: { + Uint8 pixel = 0; + int shift = (8-ExpandBMP); + for ( i=0; i<surface->w; ++i ) { + if ( i%(8/ExpandBMP) == 0 ) { + if ( !SDL_RWread(src, &pixel, 1, 1) ) { + SDL_SetError( + "Error reading from BMP"); + was_error = SDL_TRUE; + goto done; + } + } + *(bits+i) = (pixel>>shift); + pixel <<= ExpandBMP; + } } + break; + + default: + if ( SDL_RWread(src, bits, 1, surface->pitch) + != surface->pitch ) { + SDL_Error(SDL_EFREAD); + was_error = SDL_TRUE; + goto done; + } +#if SDL_BYTEORDER == SDL_BIG_ENDIAN + /* Byte-swap the pixels if needed. Note that the 24bpp + case has already been taken care of above. */ + switch(biBitCount) { + case 15: + case 16: { + Uint16 *pix = (Uint16 *)bits; + for(i = 0; i < surface->w; i++) + pix[i] = SDL_Swap16(pix[i]); + break; + } + + case 32: { + Uint32 *pix = (Uint32 *)bits; + for(i = 0; i < surface->w; i++) + pix[i] = SDL_Swap32(pix[i]); + break; + } + } +#endif + break; + } + /* Skip padding bytes, ugh */ + if ( pad ) { + Uint8 padbyte; + for ( i=0; i<pad; ++i ) { + SDL_RWread(src, &padbyte, 1, 1); + } + } + if ( topDown ) { + bits += surface->pitch; + } else { + bits -= surface->pitch; + } + } +done: + if ( was_error ) { + if ( src ) { + SDL_RWseek(src, fp_offset, RW_SEEK_SET); + } + if ( surface ) { + SDL_FreeSurface(surface); + } + surface = NULL; + } + if ( freesrc && src ) { + SDL_RWclose(src); + } + return(surface); +} + +int SDL_SaveBMP_RW (SDL_Surface *saveme, SDL_RWops *dst, int freedst) +{ + long fp_offset; + int i, pad; + SDL_Surface *surface; + Uint8 *bits; + + /* The Win32 BMP file header (14 bytes) */ + char magic[2] = { 'B', 'M' }; + Uint32 bfSize; + Uint16 bfReserved1; + Uint16 bfReserved2; + Uint32 bfOffBits; + + /* The Win32 BITMAPINFOHEADER struct (40 bytes) */ + Uint32 biSize; + Sint32 biWidth; + Sint32 biHeight; + Uint16 biPlanes; + Uint16 biBitCount; + Uint32 biCompression; + Uint32 biSizeImage; + Sint32 biXPelsPerMeter; + Sint32 biYPelsPerMeter; + Uint32 biClrUsed; + Uint32 biClrImportant; + + /* Make sure we have somewhere to save */ + surface = NULL; + if ( dst ) { + if ( saveme->format->palette ) { + if ( saveme->format->BitsPerPixel == 8 ) { + surface = saveme; + } else { + SDL_SetError("%d bpp BMP files not supported", + saveme->format->BitsPerPixel); + } + } + else if ( (saveme->format->BitsPerPixel == 24) && +#if SDL_BYTEORDER == SDL_LIL_ENDIAN + (saveme->format->Rmask == 0x00FF0000) && + (saveme->format->Gmask == 0x0000FF00) && + (saveme->format->Bmask == 0x000000FF) +#else + (saveme->format->Rmask == 0x000000FF) && + (saveme->format->Gmask == 0x0000FF00) && + (saveme->format->Bmask == 0x00FF0000) +#endif + ) { + surface = saveme; + } else { + SDL_Rect bounds; + + /* Convert to 24 bits per pixel */ + surface = SDL_CreateRGBSurface(SDL_SWSURFACE, + saveme->w, saveme->h, 24, +#if SDL_BYTEORDER == SDL_LIL_ENDIAN + 0x00FF0000, 0x0000FF00, 0x000000FF, +#else + 0x000000FF, 0x0000FF00, 0x00FF0000, +#endif + 0); + if ( surface != NULL ) { + bounds.x = 0; + bounds.y = 0; + bounds.w = saveme->w; + bounds.h = saveme->h; + if ( SDL_LowerBlit(saveme, &bounds, surface, + &bounds) < 0 ) { + SDL_FreeSurface(surface); + SDL_SetError( + "Couldn't convert image to 24 bpp"); + surface = NULL; + } + } + } + } + + if ( surface && (SDL_LockSurface(surface) == 0) ) { + const int bw = surface->w*surface->format->BytesPerPixel; + + /* Set the BMP file header values */ + bfSize = 0; /* We'll write this when we're done */ + bfReserved1 = 0; + bfReserved2 = 0; + bfOffBits = 0; /* We'll write this when we're done */ + + /* Write the BMP file header values */ + fp_offset = SDL_RWtell(dst); + SDL_ClearError(); + SDL_RWwrite(dst, magic, 2, 1); + SDL_WriteLE32(dst, bfSize); + SDL_WriteLE16(dst, bfReserved1); + SDL_WriteLE16(dst, bfReserved2); + SDL_WriteLE32(dst, bfOffBits); + + /* Set the BMP info values */ + biSize = 40; + biWidth = surface->w; + biHeight = surface->h; + biPlanes = 1; + biBitCount = surface->format->BitsPerPixel; + biCompression = BI_RGB; + biSizeImage = surface->h*surface->pitch; + biXPelsPerMeter = 0; + biYPelsPerMeter = 0; + if ( surface->format->palette ) { + biClrUsed = surface->format->palette->ncolors; + } else { + biClrUsed = 0; + } + biClrImportant = 0; + + /* Write the BMP info values */ + SDL_WriteLE32(dst, biSize); + SDL_WriteLE32(dst, biWidth); + SDL_WriteLE32(dst, biHeight); + SDL_WriteLE16(dst, biPlanes); + SDL_WriteLE16(dst, biBitCount); + SDL_WriteLE32(dst, biCompression); + SDL_WriteLE32(dst, biSizeImage); + SDL_WriteLE32(dst, biXPelsPerMeter); + SDL_WriteLE32(dst, biYPelsPerMeter); + SDL_WriteLE32(dst, biClrUsed); + SDL_WriteLE32(dst, biClrImportant); + + /* Write the palette (in BGR color order) */ + if ( surface->format->palette ) { + SDL_Color *colors; + int ncolors; + + colors = surface->format->palette->colors; + ncolors = surface->format->palette->ncolors; + for ( i=0; i<ncolors; ++i ) { + SDL_RWwrite(dst, &colors[i].b, 1, 1); + SDL_RWwrite(dst, &colors[i].g, 1, 1); + SDL_RWwrite(dst, &colors[i].r, 1, 1); + SDL_RWwrite(dst, &colors[i].unused, 1, 1); + } + } + + /* Write the bitmap offset */ + bfOffBits = SDL_RWtell(dst)-fp_offset; + if ( SDL_RWseek(dst, fp_offset+10, RW_SEEK_SET) < 0 ) { + SDL_Error(SDL_EFSEEK); + } + SDL_WriteLE32(dst, bfOffBits); + if ( SDL_RWseek(dst, fp_offset+bfOffBits, RW_SEEK_SET) < 0 ) { + SDL_Error(SDL_EFSEEK); + } + + /* Write the bitmap image upside down */ + bits = (Uint8 *)surface->pixels+(surface->h*surface->pitch); + pad = ((bw%4) ? (4-(bw%4)) : 0); + while ( bits > (Uint8 *)surface->pixels ) { + bits -= surface->pitch; + if ( SDL_RWwrite(dst, bits, 1, bw) != bw) { + SDL_Error(SDL_EFWRITE); + break; + } + if ( pad ) { + const Uint8 padbyte = 0; + for ( i=0; i<pad; ++i ) { + SDL_RWwrite(dst, &padbyte, 1, 1); + } + } + } + + /* Write the BMP file size */ + bfSize = SDL_RWtell(dst)-fp_offset; + if ( SDL_RWseek(dst, fp_offset+2, RW_SEEK_SET) < 0 ) { + SDL_Error(SDL_EFSEEK); + } + SDL_WriteLE32(dst, bfSize); + if ( SDL_RWseek(dst, fp_offset+bfSize, RW_SEEK_SET) < 0 ) { + SDL_Error(SDL_EFSEEK); + } + + /* Close it up.. */ + SDL_UnlockSurface(surface); + if ( surface != saveme ) { + SDL_FreeSurface(surface); + } + } + + if ( freedst && dst ) { + SDL_RWclose(dst); + } + return((SDL_strcmp(SDL_GetError(), "") == 0) ? 0 : -1); +} diff --git a/3rdparty/SDL/src/video/SDL_cursor.c b/3rdparty/SDL/src/video/SDL_cursor.c new file mode 100644 index 0000000..5d747d3 --- /dev/null +++ b/3rdparty/SDL/src/video/SDL_cursor.c @@ -0,0 +1,758 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* General cursor handling code for SDL */ + +#include "SDL_mutex.h" +#include "SDL_video.h" +#include "SDL_mouse.h" +#include "SDL_blit.h" +#include "SDL_sysvideo.h" +#include "SDL_cursor_c.h" +#include "SDL_pixels_c.h" +#include "default_cursor.h" +#include "../events/SDL_sysevents.h" +#include "../events/SDL_events_c.h" + +/* These are static for our cursor handling code */ +volatile int SDL_cursorstate = CURSOR_VISIBLE; +SDL_Cursor *SDL_cursor = NULL; +static SDL_Cursor *SDL_defcursor = NULL; +SDL_mutex *SDL_cursorlock = NULL; + +/* Public functions */ +void SDL_CursorQuit(void) +{ + if ( SDL_cursor != NULL ) { + SDL_Cursor *cursor; + + SDL_cursorstate &= ~CURSOR_VISIBLE; + if ( SDL_cursor != SDL_defcursor ) { + SDL_FreeCursor(SDL_cursor); + } + SDL_cursor = NULL; + if ( SDL_defcursor != NULL ) { + cursor = SDL_defcursor; + SDL_defcursor = NULL; + SDL_FreeCursor(cursor); + } + } + if ( SDL_cursorlock != NULL ) { + SDL_DestroyMutex(SDL_cursorlock); + SDL_cursorlock = NULL; + } +} +int SDL_CursorInit(Uint32 multithreaded) +{ + /* We don't have mouse focus, and the cursor isn't drawn yet */ +#ifndef IPOD + SDL_cursorstate = CURSOR_VISIBLE; +#endif + + /* Create the default cursor */ + if ( SDL_defcursor == NULL ) { + SDL_defcursor = SDL_CreateCursor(default_cdata, default_cmask, + DEFAULT_CWIDTH, DEFAULT_CHEIGHT, + DEFAULT_CHOTX, DEFAULT_CHOTY); + SDL_SetCursor(SDL_defcursor); + } + + /* Create a lock if necessary */ + if ( multithreaded ) { + SDL_cursorlock = SDL_CreateMutex(); + } + + /* That's it! */ + return(0); +} + +/* Multi-thread support for cursors */ +#ifndef SDL_LockCursor +void SDL_LockCursor(void) +{ + if ( SDL_cursorlock ) { + SDL_mutexP(SDL_cursorlock); + } +} +#endif +#ifndef SDL_UnlockCursor +void SDL_UnlockCursor(void) +{ + if ( SDL_cursorlock ) { + SDL_mutexV(SDL_cursorlock); + } +} +#endif + +/* Software cursor drawing support */ +SDL_Cursor * SDL_CreateCursor (Uint8 *data, Uint8 *mask, + int w, int h, int hot_x, int hot_y) +{ + SDL_VideoDevice *video = current_video; + int savelen; + int i; + SDL_Cursor *cursor; + + /* Make sure the width is a multiple of 8 */ + w = ((w+7)&~7); + + /* Sanity check the hot spot */ + if ( (hot_x < 0) || (hot_y < 0) || (hot_x >= w) || (hot_y >= h) ) { + SDL_SetError("Cursor hot spot doesn't lie within cursor"); + return(NULL); + } + + /* Allocate memory for the cursor */ + cursor = (SDL_Cursor *)SDL_malloc(sizeof *cursor); + if ( cursor == NULL ) { + SDL_OutOfMemory(); + return(NULL); + } + savelen = (w*4)*h; + cursor->area.x = 0; + cursor->area.y = 0; + cursor->area.w = w; + cursor->area.h = h; + cursor->hot_x = hot_x; + cursor->hot_y = hot_y; + cursor->data = (Uint8 *)SDL_malloc((w/8)*h*2); + cursor->mask = cursor->data+((w/8)*h); + cursor->save[0] = (Uint8 *)SDL_malloc(savelen*2); + cursor->save[1] = cursor->save[0] + savelen; + cursor->wm_cursor = NULL; + if ( ! cursor->data || ! cursor->save[0] ) { + SDL_FreeCursor(cursor); + SDL_OutOfMemory(); + return(NULL); + } + for ( i=((w/8)*h)-1; i>=0; --i ) { + cursor->data[i] = data[i]; + cursor->mask[i] = mask[i] | data[i]; + } + SDL_memset(cursor->save[0], 0, savelen*2); + + /* If the window manager gives us a good cursor, we're done! */ + if ( video->CreateWMCursor ) { + cursor->wm_cursor = video->CreateWMCursor(video, data, mask, + w, h, hot_x, hot_y); + } else { + cursor->wm_cursor = NULL; + } + return(cursor); +} + +/* SDL_SetCursor(NULL) can be used to force the cursor redraw, + if this is desired for any reason. This is used when setting + the video mode and when the SDL window gains the mouse focus. + */ +void SDL_SetCursor (SDL_Cursor *cursor) +{ + SDL_VideoDevice *video = current_video; + SDL_VideoDevice *this = current_video; + + /* Make sure that the video subsystem has been initialized */ + if ( ! video ) { + return; + } + + /* Prevent the event thread from moving the mouse */ + SDL_LockCursor(); + + /* Set the new cursor */ + if ( cursor && (cursor != SDL_cursor) ) { + /* Erase the current mouse position */ + if ( SHOULD_DRAWCURSOR(SDL_cursorstate) ) { + SDL_EraseCursor(SDL_VideoSurface); + } else if ( video->MoveWMCursor ) { + /* If the video driver is moving the cursor directly, + it needs to hide the old cursor before (possibly) + showing the new one. (But don't erase NULL cursor) + */ + if ( SDL_cursor && video->ShowWMCursor ) { + video->ShowWMCursor(this, NULL); + } + } + SDL_cursor = cursor; + } + + /* Draw the new mouse cursor */ + if ( SDL_cursor && (SDL_cursorstate&CURSOR_VISIBLE) ) { + /* Use window manager cursor if possible */ + int show_wm_cursor = 0; + if ( SDL_cursor->wm_cursor && video->ShowWMCursor ) { + show_wm_cursor = video->ShowWMCursor(this, SDL_cursor->wm_cursor); + } + if ( show_wm_cursor ) { + SDL_cursorstate &= ~CURSOR_USINGSW; + } else { + SDL_cursorstate |= CURSOR_USINGSW; + if ( video->ShowWMCursor ) { + video->ShowWMCursor(this, NULL); + } + { int x, y; + SDL_GetMouseState(&x, &y); + SDL_cursor->area.x = (x - SDL_cursor->hot_x); + SDL_cursor->area.y = (y - SDL_cursor->hot_y); + } + SDL_DrawCursor(SDL_VideoSurface); + } + } else { + /* Erase window manager mouse (cursor not visible) */ + if ( SDL_cursor && (SDL_cursorstate & CURSOR_USINGSW) ) { + SDL_EraseCursor(SDL_VideoSurface); + } else { + if ( video ) { + if ( video->ShowWMCursor ) { + video->ShowWMCursor(this, NULL); + } + } + } + } + SDL_UnlockCursor(); +} + +SDL_Cursor * SDL_GetCursor (void) +{ + return(SDL_cursor); +} + +void SDL_FreeCursor (SDL_Cursor *cursor) +{ + if ( cursor ) { + if ( cursor == SDL_cursor ) { + SDL_SetCursor(SDL_defcursor); + } + if ( cursor != SDL_defcursor ) { + SDL_VideoDevice *video = current_video; + SDL_VideoDevice *this = current_video; + + if ( cursor->data ) { + SDL_free(cursor->data); + } + if ( cursor->save[0] ) { + SDL_free(cursor->save[0]); + } + if ( video && cursor->wm_cursor ) { + if ( video->FreeWMCursor ) { + video->FreeWMCursor(this, cursor->wm_cursor); + } + } + SDL_free(cursor); + } + } +} + +int SDL_ShowCursor (int toggle) +{ + int showing; + + showing = (SDL_cursorstate & CURSOR_VISIBLE); + if ( toggle >= 0 ) { + SDL_LockCursor(); + if ( toggle ) { + SDL_cursorstate |= CURSOR_VISIBLE; + } else { + SDL_cursorstate &= ~CURSOR_VISIBLE; + } + SDL_UnlockCursor(); + if ( (SDL_cursorstate & CURSOR_VISIBLE) != showing ) { + SDL_VideoDevice *video = current_video; + SDL_VideoDevice *this = current_video; + + SDL_SetCursor(NULL); + if ( video && video->CheckMouseMode ) { + video->CheckMouseMode(this); + } + } + } else { + /* Query current state */ ; + } + return(showing ? 1 : 0); +} + +void SDL_WarpMouse (Uint16 x, Uint16 y) +{ + SDL_VideoDevice *video = current_video; + SDL_VideoDevice *this = current_video; + + if ( !video || !SDL_PublicSurface ) { + SDL_SetError("A video mode must be set before warping mouse"); + return; + } + + /* If we have an offset video mode, offset the mouse coordinates */ + if (this->screen->pitch == 0) { + x += this->screen->offset / this->screen->format->BytesPerPixel; + y += this->screen->offset; + } else { + x += (this->screen->offset % this->screen->pitch) / + this->screen->format->BytesPerPixel; + y += (this->screen->offset / this->screen->pitch); + } + + /* This generates a mouse motion event */ + if ( video->WarpWMCursor ) { + video->WarpWMCursor(this, x, y); + } else { + SDL_PrivateMouseMotion(0, 0, x, y); + } +} + +void SDL_MoveCursor(int x, int y) +{ + SDL_VideoDevice *video = current_video; + + /* Erase and update the current mouse position */ + if ( SHOULD_DRAWCURSOR(SDL_cursorstate) ) { + /* Erase and redraw mouse cursor in new position */ + SDL_LockCursor(); + SDL_EraseCursor(SDL_VideoSurface); + SDL_cursor->area.x = (x - SDL_cursor->hot_x); + SDL_cursor->area.y = (y - SDL_cursor->hot_y); + SDL_DrawCursor(SDL_VideoSurface); + SDL_UnlockCursor(); + } else if ( video->MoveWMCursor ) { + video->MoveWMCursor(video, x, y); + } +} + +/* Keep track of the current cursor colors */ +static int palette_changed = 1; +static Uint8 pixels8[2]; + +void SDL_CursorPaletteChanged(void) +{ + palette_changed = 1; +} + +void SDL_MouseRect(SDL_Rect *area) +{ + int clip_diff; + + *area = SDL_cursor->area; + if ( area->x < 0 ) { + area->w += area->x; + area->x = 0; + } + if ( area->y < 0 ) { + area->h += area->y; + area->y = 0; + } + clip_diff = (area->x+area->w)-SDL_VideoSurface->w; + if ( clip_diff > 0 ) { + area->w = area->w < clip_diff ? 0 : area->w-clip_diff; + } + clip_diff = (area->y+area->h)-SDL_VideoSurface->h; + if ( clip_diff > 0 ) { + area->h = area->h < clip_diff ? 0 : area->h-clip_diff; + } +} + +static void SDL_DrawCursorFast(SDL_Surface *screen, SDL_Rect *area) +{ + const Uint32 pixels[2] = { 0xFFFFFFFF, 0x00000000 }; + int i, w, h; + Uint8 *data, datab; + Uint8 *mask, maskb; + + data = SDL_cursor->data + area->y * SDL_cursor->area.w/8; + mask = SDL_cursor->mask + area->y * SDL_cursor->area.w/8; + switch (screen->format->BytesPerPixel) { + + case 1: { + Uint8 *dst; + int dstskip; + + if ( palette_changed ) { + pixels8[0] = (Uint8)SDL_MapRGB(screen->format, 255, 255, 255); + pixels8[1] = (Uint8)SDL_MapRGB(screen->format, 0, 0, 0); + palette_changed = 0; + } + dst = (Uint8 *)screen->pixels + + (SDL_cursor->area.y+area->y)*screen->pitch + + SDL_cursor->area.x; + dstskip = screen->pitch-area->w; + + for ( h=area->h; h; h-- ) { + for ( w=area->w/8; w; w-- ) { + maskb = *mask++; + datab = *data++; + for ( i=0; i<8; ++i ) { + if ( maskb & 0x80 ) { + *dst = pixels8[datab>>7]; + } + maskb <<= 1; + datab <<= 1; + dst++; + } + } + dst += dstskip; + } + } + break; + + case 2: { + Uint16 *dst; + int dstskip; + + dst = (Uint16 *)screen->pixels + + (SDL_cursor->area.y+area->y)*screen->pitch/2 + + SDL_cursor->area.x; + dstskip = (screen->pitch/2)-area->w; + + for ( h=area->h; h; h-- ) { + for ( w=area->w/8; w; w-- ) { + maskb = *mask++; + datab = *data++; + for ( i=0; i<8; ++i ) { + if ( maskb & 0x80 ) { + *dst = (Uint16)pixels[datab>>7]; + } + maskb <<= 1; + datab <<= 1; + dst++; + } + } + dst += dstskip; + } + } + break; + + case 3: { + Uint8 *dst; + int dstskip; + + dst = (Uint8 *)screen->pixels + + (SDL_cursor->area.y+area->y)*screen->pitch + + SDL_cursor->area.x*3; + dstskip = screen->pitch-area->w*3; + + for ( h=area->h; h; h-- ) { + for ( w=area->w/8; w; w-- ) { + maskb = *mask++; + datab = *data++; + for ( i=0; i<8; ++i ) { + if ( maskb & 0x80 ) { + SDL_memset(dst,pixels[datab>>7],3); + } + maskb <<= 1; + datab <<= 1; + dst += 3; + } + } + dst += dstskip; + } + } + break; + + case 4: { + Uint32 *dst; + int dstskip; + + dst = (Uint32 *)screen->pixels + + (SDL_cursor->area.y+area->y)*screen->pitch/4 + + SDL_cursor->area.x; + dstskip = (screen->pitch/4)-area->w; + + for ( h=area->h; h; h-- ) { + for ( w=area->w/8; w; w-- ) { + maskb = *mask++; + datab = *data++; + for ( i=0; i<8; ++i ) { + if ( maskb & 0x80 ) { + *dst = pixels[datab>>7]; + } + maskb <<= 1; + datab <<= 1; + dst++; + } + } + dst += dstskip; + } + } + break; + } +} + +static void SDL_DrawCursorSlow(SDL_Surface *screen, SDL_Rect *area) +{ + const Uint32 pixels[2] = { 0xFFFFFF, 0x000000 }; + int h; + int x, minx, maxx; + Uint8 *data, datab = 0; + Uint8 *mask, maskb = 0; + Uint8 *dst; + int dstbpp, dstskip; + + data = SDL_cursor->data + area->y * SDL_cursor->area.w/8; + mask = SDL_cursor->mask + area->y * SDL_cursor->area.w/8; + dstbpp = screen->format->BytesPerPixel; + dst = (Uint8 *)screen->pixels + + (SDL_cursor->area.y+area->y)*screen->pitch + + SDL_cursor->area.x*dstbpp; + dstskip = screen->pitch-SDL_cursor->area.w*dstbpp; + + minx = area->x; + maxx = area->x+area->w; + if ( screen->format->BytesPerPixel == 1 ) { + if ( palette_changed ) { + pixels8[0] = (Uint8)SDL_MapRGB(screen->format, 255, 255, 255); + pixels8[1] = (Uint8)SDL_MapRGB(screen->format, 0, 0, 0); + palette_changed = 0; + } + for ( h=area->h; h; h-- ) { + for ( x=0; x<SDL_cursor->area.w; ++x ) { + if ( (x%8) == 0 ) { + maskb = *mask++; + datab = *data++; + } + if ( (x >= minx) && (x < maxx) ) { + if ( maskb & 0x80 ) { + SDL_memset(dst, pixels8[datab>>7], dstbpp); + } + } + maskb <<= 1; + datab <<= 1; + dst += dstbpp; + } + dst += dstskip; + } + } else { + for ( h=area->h; h; h-- ) { + for ( x=0; x<SDL_cursor->area.w; ++x ) { + if ( (x%8) == 0 ) { + maskb = *mask++; + datab = *data++; + } + if ( (x >= minx) && (x < maxx) ) { + if ( maskb & 0x80 ) { + SDL_memset(dst, pixels[datab>>7], dstbpp); + } + } + maskb <<= 1; + datab <<= 1; + dst += dstbpp; + } + dst += dstskip; + } + } +} + +/* This handles the ugly work of converting the saved cursor background from + the pixel format of the shadow surface to that of the video surface. + This is only necessary when blitting from a shadow surface of a different + pixel format than the video surface, and using a software rendered cursor. +*/ +static void SDL_ConvertCursorSave(SDL_Surface *screen, int w, int h) +{ + SDL_BlitInfo info; + SDL_loblit RunBlit; + + /* Make sure we can steal the blit mapping */ + if ( screen->map->dst != SDL_VideoSurface ) { + return; + } + + /* Set up the blit information */ + info.s_pixels = SDL_cursor->save[1]; + info.s_width = w; + info.s_height = h; + info.s_skip = 0; + info.d_pixels = SDL_cursor->save[0]; + info.d_width = w; + info.d_height = h; + info.d_skip = 0; + info.aux_data = screen->map->sw_data->aux_data; + info.src = screen->format; + info.table = screen->map->table; + info.dst = SDL_VideoSurface->format; + RunBlit = screen->map->sw_data->blit; + + /* Run the actual software blit */ + RunBlit(&info); +} + +void SDL_DrawCursorNoLock(SDL_Surface *screen) +{ + SDL_Rect area; + + /* Get the mouse rectangle, clipped to the screen */ + SDL_MouseRect(&area); + if ( (area.w == 0) || (area.h == 0) ) { + return; + } + + /* Copy mouse background */ + { int w, h, screenbpp; + Uint8 *src, *dst; + + /* Set up the copy pointers */ + screenbpp = screen->format->BytesPerPixel; + if ( (screen == SDL_VideoSurface) || + FORMAT_EQUAL(screen->format, SDL_VideoSurface->format) ) { + dst = SDL_cursor->save[0]; + } else { + dst = SDL_cursor->save[1]; + } + src = (Uint8 *)screen->pixels + area.y * screen->pitch + + area.x * screenbpp; + + /* Perform the copy */ + w = area.w*screenbpp; + h = area.h; + while ( h-- ) { + SDL_memcpy(dst, src, w); + dst += w; + src += screen->pitch; + } + } + + /* Draw the mouse cursor */ + area.x -= SDL_cursor->area.x; + area.y -= SDL_cursor->area.y; + if ( (area.x == 0) && (area.w == SDL_cursor->area.w) ) { + SDL_DrawCursorFast(screen, &area); + } else { + SDL_DrawCursorSlow(screen, &area); + } +} + +void SDL_DrawCursor(SDL_Surface *screen) +{ + /* Lock the screen if necessary */ + if ( screen == NULL ) { + return; + } + if ( SDL_MUSTLOCK(screen) ) { + if ( SDL_LockSurface(screen) < 0 ) { + return; + } + } + + SDL_DrawCursorNoLock(screen); + + /* Unlock the screen and update if necessary */ + if ( SDL_MUSTLOCK(screen) ) { + SDL_UnlockSurface(screen); + } + if ( (screen == SDL_VideoSurface) && + ((screen->flags & SDL_HWSURFACE) != SDL_HWSURFACE) ) { + SDL_VideoDevice *video = current_video; + SDL_VideoDevice *this = current_video; + SDL_Rect area; + + SDL_MouseRect(&area); + + /* This can be called before a video mode is set */ + if ( video->UpdateRects ) { + video->UpdateRects(this, 1, &area); + } + } +} + +void SDL_EraseCursorNoLock(SDL_Surface *screen) +{ + SDL_Rect area; + + /* Get the mouse rectangle, clipped to the screen */ + SDL_MouseRect(&area); + if ( (area.w == 0) || (area.h == 0) ) { + return; + } + + /* Copy mouse background */ + { int w, h, screenbpp; + Uint8 *src, *dst; + + /* Set up the copy pointers */ + screenbpp = screen->format->BytesPerPixel; + if ( (screen == SDL_VideoSurface) || + FORMAT_EQUAL(screen->format, SDL_VideoSurface->format) ) { + src = SDL_cursor->save[0]; + } else { + src = SDL_cursor->save[1]; + } + dst = (Uint8 *)screen->pixels + area.y * screen->pitch + + area.x * screenbpp; + + /* Perform the copy */ + w = area.w*screenbpp; + h = area.h; + while ( h-- ) { + SDL_memcpy(dst, src, w); + src += w; + dst += screen->pitch; + } + + /* Perform pixel conversion on cursor background */ + if ( src > SDL_cursor->save[1] ) { + SDL_ConvertCursorSave(screen, area.w, area.h); + } + } +} + +void SDL_EraseCursor(SDL_Surface *screen) +{ + /* Lock the screen if necessary */ + if ( screen == NULL ) { + return; + } + if ( SDL_MUSTLOCK(screen) ) { + if ( SDL_LockSurface(screen) < 0 ) { + return; + } + } + + SDL_EraseCursorNoLock(screen); + + /* Unlock the screen and update if necessary */ + if ( SDL_MUSTLOCK(screen) ) { + SDL_UnlockSurface(screen); + } + if ( (screen == SDL_VideoSurface) && + ((screen->flags & SDL_HWSURFACE) != SDL_HWSURFACE) ) { + SDL_VideoDevice *video = current_video; + SDL_VideoDevice *this = current_video; + SDL_Rect area; + + SDL_MouseRect(&area); + if ( video->UpdateRects ) { + video->UpdateRects(this, 1, &area); + } + } +} + +/* Reset the cursor on video mode change + FIXME: Keep track of all cursors, and reset them all. + */ +void SDL_ResetCursor(void) +{ + int savelen; + + if ( SDL_cursor ) { + savelen = SDL_cursor->area.w*4*SDL_cursor->area.h; + SDL_cursor->area.x = 0; + SDL_cursor->area.y = 0; + SDL_memset(SDL_cursor->save[0], 0, savelen); + } +} diff --git a/3rdparty/SDL/src/video/SDL_cursor_c.h b/3rdparty/SDL/src/video/SDL_cursor_c.h new file mode 100644 index 0000000..8be8df9 --- /dev/null +++ b/3rdparty/SDL/src/video/SDL_cursor_c.h @@ -0,0 +1,73 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* Useful variables and functions from SDL_cursor.c */ +#include "SDL_mouse.h" + +extern int SDL_CursorInit(Uint32 flags); +extern void SDL_CursorPaletteChanged(void); +extern void SDL_DrawCursor(SDL_Surface *screen); +extern void SDL_DrawCursorNoLock(SDL_Surface *screen); +extern void SDL_EraseCursor(SDL_Surface *screen); +extern void SDL_EraseCursorNoLock(SDL_Surface *screen); +extern void SDL_UpdateCursor(SDL_Surface *screen); +extern void SDL_ResetCursor(void); +extern void SDL_MoveCursor(int x, int y); +extern void SDL_CursorQuit(void); + +#define INLINE_MOUSELOCK +#ifdef INLINE_MOUSELOCK +/* Inline (macro) versions of the mouse lock functions */ +#include "SDL_mutex.h" + +extern SDL_mutex *SDL_cursorlock; + +#define SDL_LockCursor() \ + do { \ + if ( SDL_cursorlock ) { \ + SDL_mutexP(SDL_cursorlock); \ + } \ + } while ( 0 ) +#define SDL_UnlockCursor() \ + do { \ + if ( SDL_cursorlock ) { \ + SDL_mutexV(SDL_cursorlock); \ + } \ + } while ( 0 ) +#else +extern void SDL_LockCursor(void); +extern void SDL_UnlockCursor(void); +#endif /* INLINE_MOUSELOCK */ + +/* Only for low-level mouse cursor drawing */ +extern SDL_Cursor *SDL_cursor; +extern void SDL_MouseRect(SDL_Rect *area); + +/* State definitions for the SDL cursor */ +#define CURSOR_VISIBLE 0x01 +#define CURSOR_USINGSW 0x10 +#define SHOULD_DRAWCURSOR(X) \ + (((X)&(CURSOR_VISIBLE|CURSOR_USINGSW)) == \ + (CURSOR_VISIBLE|CURSOR_USINGSW)) + +extern volatile int SDL_cursorstate; diff --git a/3rdparty/SDL/src/video/SDL_gamma.c b/3rdparty/SDL/src/video/SDL_gamma.c new file mode 100644 index 0000000..4fd0370 --- /dev/null +++ b/3rdparty/SDL/src/video/SDL_gamma.c @@ -0,0 +1,233 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* Gamma correction support */ + +#ifdef HAVE_MATH_H +#include <math.h> /* Used for calculating gamma ramps */ +#else +/* Math routines from uClibc: http://www.uclibc.org */ +#include "math_private.h" +#include "e_sqrt.h" +#include "e_pow.h" +#include "e_log.h" +#define pow(x, y) __ieee754_pow(x, y) +#define log(x) __ieee754_log(x) +#endif + +#include "SDL_sysvideo.h" + + +static void CalculateGammaRamp(float gamma, Uint16 *ramp) +{ + int i; + + /* 0.0 gamma is all black */ + if ( gamma <= 0.0f ) { + for ( i=0; i<256; ++i ) { + ramp[i] = 0; + } + return; + } else + /* 1.0 gamma is identity */ + if ( gamma == 1.0f ) { + for ( i=0; i<256; ++i ) { + ramp[i] = (i << 8) | i; + } + return; + } else + /* Calculate a real gamma ramp */ + { int value; + gamma = 1.0f / gamma; + for ( i=0; i<256; ++i ) { + value = (int)(pow((double)i/256.0, gamma)*65535.0+0.5); + if ( value > 65535 ) { + value = 65535; + } + ramp[i] = (Uint16)value; + } + } +} +static void CalculateGammaFromRamp(float *gamma, Uint16 *ramp) +{ + /* The following is adapted from a post by Garrett Bass on OpenGL + Gamedev list, March 4, 2000. + */ + float sum = 0.0f; + int i, count = 0; + + *gamma = 1.0; + for ( i = 1; i < 256; ++i ) { + if ( (ramp[i] != 0) && (ramp[i] != 65535) ) { + double B = (double)i / 256.0; + double A = ramp[i] / 65535.0; + sum += (float) ( log(A) / log(B) ); + count++; + } + } + if ( count && sum > 0.0f ) { + *gamma = 1.0f / (sum / count); + } +} + +int SDL_SetGamma(float red, float green, float blue) +{ + int succeeded; + SDL_VideoDevice *video = current_video; + SDL_VideoDevice *this = current_video; + + succeeded = -1; + /* Prefer using SetGammaRamp(), as it's more flexible */ + { + Uint16 ramp[3][256]; + + CalculateGammaRamp(red, ramp[0]); + CalculateGammaRamp(green, ramp[1]); + CalculateGammaRamp(blue, ramp[2]); + succeeded = SDL_SetGammaRamp(ramp[0], ramp[1], ramp[2]); + } + if ( (succeeded < 0) && video->SetGamma ) { + SDL_ClearError(); + succeeded = video->SetGamma(this, red, green, blue); + } + return succeeded; +} + +/* Calculating the gamma by integrating the gamma ramps isn't exact, + so this function isn't officially supported. +*/ +int SDL_GetGamma(float *red, float *green, float *blue) +{ + int succeeded; + SDL_VideoDevice *video = current_video; + SDL_VideoDevice *this = current_video; + + succeeded = -1; + /* Prefer using GetGammaRamp(), as it's more flexible */ + { + Uint16 ramp[3][256]; + + succeeded = SDL_GetGammaRamp(ramp[0], ramp[1], ramp[2]); + if ( succeeded >= 0 ) { + CalculateGammaFromRamp(red, ramp[0]); + CalculateGammaFromRamp(green, ramp[1]); + CalculateGammaFromRamp(blue, ramp[2]); + } + } + if ( (succeeded < 0) && video->GetGamma ) { + SDL_ClearError(); + succeeded = video->GetGamma(this, red, green, blue); + } + return succeeded; +} + +int SDL_SetGammaRamp(const Uint16 *red, const Uint16 *green, const Uint16 *blue) +{ + int succeeded; + SDL_VideoDevice *video = current_video; + SDL_VideoDevice *this = current_video; + SDL_Surface *screen = SDL_PublicSurface; + + /* Verify the screen parameter */ + if ( !screen ) { + SDL_SetError("No video mode has been set"); + return -1; + } + + /* Lazily allocate the gamma tables */ + if ( ! video->gamma ) { + SDL_GetGammaRamp(0, 0, 0); + } + + /* Fill the gamma table with the new values */ + if ( red ) { + SDL_memcpy(&video->gamma[0*256], red, 256*sizeof(*video->gamma)); + } + if ( green ) { + SDL_memcpy(&video->gamma[1*256], green, 256*sizeof(*video->gamma)); + } + if ( blue ) { + SDL_memcpy(&video->gamma[2*256], blue, 256*sizeof(*video->gamma)); + } + + /* Gamma correction always possible on split palettes */ + if ( (screen->flags & SDL_HWPALETTE) == SDL_HWPALETTE ) { + SDL_Palette *pal = screen->format->palette; + + /* If physical palette has been set independently, use it */ + if(video->physpal) + pal = video->physpal; + + SDL_SetPalette(screen, SDL_PHYSPAL, + pal->colors, 0, pal->ncolors); + return 0; + } + + /* Try to set the gamma ramp in the driver */ + succeeded = -1; + if ( video->SetGammaRamp ) { + succeeded = video->SetGammaRamp(this, video->gamma); + } else { + SDL_SetError("Gamma ramp manipulation not supported"); + } + return succeeded; +} + +int SDL_GetGammaRamp(Uint16 *red, Uint16 *green, Uint16 *blue) +{ + SDL_VideoDevice *video = current_video; + SDL_VideoDevice *this = current_video; + + /* Lazily allocate the gamma table */ + if ( ! video->gamma ) { + video->gamma = SDL_malloc(3*256*sizeof(*video->gamma)); + if ( ! video->gamma ) { + SDL_OutOfMemory(); + return -1; + } + if ( video->GetGammaRamp ) { + /* Get the real hardware gamma */ + video->GetGammaRamp(this, video->gamma); + } else { + /* Assume an identity gamma */ + int i; + for ( i=0; i<256; ++i ) { + video->gamma[0*256+i] = (i << 8) | i; + video->gamma[1*256+i] = (i << 8) | i; + video->gamma[2*256+i] = (i << 8) | i; + } + } + } + + /* Just copy from our internal table */ + if ( red ) { + SDL_memcpy(red, &video->gamma[0*256], 256*sizeof(*red)); + } + if ( green ) { + SDL_memcpy(green, &video->gamma[1*256], 256*sizeof(*green)); + } + if ( blue ) { + SDL_memcpy(blue, &video->gamma[2*256], 256*sizeof(*blue)); + } + return 0; +} diff --git a/3rdparty/SDL/src/video/SDL_glfuncs.h b/3rdparty/SDL/src/video/SDL_glfuncs.h new file mode 100644 index 0000000..fb2d964 --- /dev/null +++ b/3rdparty/SDL/src/video/SDL_glfuncs.h @@ -0,0 +1,341 @@ +/* list of OpenGL functions sorted alphabetically + If you need to use a GL function from the SDL video subsystem, + change it's entry from SDL_PROC_UNUSED to SDL_PROC and rebuild. +*/ +#define SDL_PROC_UNUSED(ret,func,params) +SDL_PROC_UNUSED(void,glAccum,(GLenum,GLfloat)) +SDL_PROC_UNUSED(void,glAlphaFunc,(GLenum,GLclampf)) +SDL_PROC_UNUSED(GLboolean,glAreTexturesResident,(GLsizei,const GLuint*,GLboolean*)) +SDL_PROC_UNUSED(void,glArrayElement,(GLint)) +SDL_PROC(void,glBegin,(GLenum)) +SDL_PROC(void,glBindTexture,(GLenum,GLuint)) +SDL_PROC_UNUSED(void,glBitmap,(GLsizei,GLsizei,GLfloat,GLfloat,GLfloat,GLfloat,const GLubyte*)) +SDL_PROC(void,glBlendFunc,(GLenum,GLenum)) +SDL_PROC_UNUSED(void,glCallList,(GLuint)) +SDL_PROC_UNUSED(void,glCallLists,(GLsizei,GLenum,const GLvoid*)) +SDL_PROC_UNUSED(void,glClear,(GLbitfield)) +SDL_PROC_UNUSED(void,glClearAccum,(GLfloat,GLfloat,GLfloat,GLfloat)) +SDL_PROC_UNUSED(void,glClearColor,(GLclampf,GLclampf,GLclampf,GLclampf)) +SDL_PROC_UNUSED(void,glClearDepth,(GLclampd)) +SDL_PROC_UNUSED(void,glClearIndex,(GLfloat)) +SDL_PROC_UNUSED(void,glClearStencil,(GLint)) +SDL_PROC_UNUSED(void,glClipPlane,(GLenum,const GLdouble*)) +SDL_PROC_UNUSED(void,glColor3b,(GLbyte,GLbyte,GLbyte)) +SDL_PROC_UNUSED(void,glColor3bv,(const GLbyte*)) +SDL_PROC_UNUSED(void,glColor3d,(GLdouble,GLdouble,GLdouble)) +SDL_PROC_UNUSED(void,glColor3dv,(const GLdouble*)) +SDL_PROC_UNUSED(void,glColor3f,(GLfloat,GLfloat,GLfloat)) +SDL_PROC_UNUSED(void,glColor3fv,(const GLfloat*)) +SDL_PROC_UNUSED(void,glColor3i,(GLint,GLint,GLint)) +SDL_PROC_UNUSED(void,glColor3iv,(const GLint*)) +SDL_PROC_UNUSED(void,glColor3s,(GLshort,GLshort,GLshort)) +SDL_PROC_UNUSED(void,glColor3sv,(const GLshort*)) +SDL_PROC_UNUSED(void,glColor3ub,(GLubyte,GLubyte,GLubyte)) +SDL_PROC_UNUSED(void,glColor3ubv,(const GLubyte*)) +SDL_PROC_UNUSED(void,glColor3ui,(GLuint,GLuint,GLuint)) +SDL_PROC_UNUSED(void,glColor3uiv,(const GLuint*)) +SDL_PROC_UNUSED(void,glColor3us,(GLushort,GLushort,GLushort)) +SDL_PROC_UNUSED(void,glColor3usv,(const GLushort*)) +SDL_PROC_UNUSED(void,glColor4b,(GLbyte,GLbyte,GLbyte,GLbyte)) +SDL_PROC_UNUSED(void,glColor4bv,(const GLbyte*)) +SDL_PROC_UNUSED(void,glColor4d,(GLdouble,GLdouble,GLdouble,GLdouble)) +SDL_PROC_UNUSED(void,glColor4dv,(const GLdouble*)) +SDL_PROC(void,glColor4f,(GLfloat,GLfloat,GLfloat,GLfloat)) +SDL_PROC_UNUSED(void,glColor4fv,(const GLfloat*)) +SDL_PROC_UNUSED(void,glColor4i,(GLint,GLint,GLint,GLint)) +SDL_PROC_UNUSED(void,glColor4iv,(const GLint*)) +SDL_PROC_UNUSED(void,glColor4s,(GLshort,GLshort,GLshort,GLshort)) +SDL_PROC_UNUSED(void,glColor4sv,(const GLshort*)) +SDL_PROC_UNUSED(void,glColor4ub,(GLubyte red, GLubyte green, GLubyte blue, GLubyte alpha)) +SDL_PROC_UNUSED(void,glColor4ubv,(const GLubyte *v)) +SDL_PROC_UNUSED(void,glColor4ui,(GLuint red, GLuint green, GLuint blue, GLuint alpha)) +SDL_PROC_UNUSED(void,glColor4uiv,(const GLuint *v)) +SDL_PROC_UNUSED(void,glColor4us,(GLushort red, GLushort green, GLushort blue, GLushort alpha)) +SDL_PROC_UNUSED(void,glColor4usv,(const GLushort *v)) +SDL_PROC_UNUSED(void,glColorMask,(GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha)) +SDL_PROC_UNUSED(void,glColorMaterial,(GLenum face, GLenum mode)) +SDL_PROC_UNUSED(void,glColorPointer,(GLint size, GLenum type, GLsizei stride, const GLvoid *pointer)) +SDL_PROC_UNUSED(void,glCopyPixels,(GLint x, GLint y, GLsizei width, GLsizei height, GLenum type)) +SDL_PROC_UNUSED(void,glCopyTexImage1D,(GLenum target, GLint level, GLenum internalFormat, GLint x, GLint y, GLsizei width, GLint border)) +SDL_PROC_UNUSED(void,glCopyTexImage2D,(GLenum target, GLint level, GLenum internalFormat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border)) +SDL_PROC_UNUSED(void,glCopyTexSubImage1D,(GLenum target, GLint level, GLint xoffset, GLint x, GLint y, GLsizei width)) +SDL_PROC_UNUSED(void,glCopyTexSubImage2D,(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height)) +SDL_PROC_UNUSED(void,glCullFace,(GLenum mode)) +SDL_PROC_UNUSED(void,glDeleteLists,(GLuint list, GLsizei range)) +SDL_PROC_UNUSED(void,glDeleteTextures,(GLsizei n, const GLuint *textures)) +SDL_PROC_UNUSED(void,glDepthFunc,(GLenum func)) +SDL_PROC_UNUSED(void,glDepthMask,(GLboolean flag)) +SDL_PROC_UNUSED(void,glDepthRange,(GLclampd zNear, GLclampd zFar)) +SDL_PROC(void,glDisable,(GLenum cap)) +SDL_PROC_UNUSED(void,glDisableClientState,(GLenum array)) +SDL_PROC_UNUSED(void,glDrawArrays,(GLenum mode, GLint first, GLsizei count)) +SDL_PROC_UNUSED(void,glDrawBuffer,(GLenum mode)) +SDL_PROC_UNUSED(void,glDrawElements,(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices)) +SDL_PROC_UNUSED(void,glDrawPixels,(GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels)) +SDL_PROC_UNUSED(void,glEdgeFlag,(GLboolean flag)) +SDL_PROC_UNUSED(void,glEdgeFlagPointer,(GLsizei stride, const GLvoid *pointer)) +SDL_PROC_UNUSED(void,glEdgeFlagv,(const GLboolean *flag)) +SDL_PROC(void,glEnable,(GLenum cap)) +SDL_PROC_UNUSED(void,glEnableClientState,(GLenum array)) +SDL_PROC(void,glEnd,(void)) +SDL_PROC_UNUSED(void,glEndList,(void)) +SDL_PROC_UNUSED(void,glEvalCoord1d,(GLdouble u)) +SDL_PROC_UNUSED(void,glEvalCoord1dv,(const GLdouble *u)) +SDL_PROC_UNUSED(void,glEvalCoord1f,(GLfloat u)) +SDL_PROC_UNUSED(void,glEvalCoord1fv,(const GLfloat *u)) +SDL_PROC_UNUSED(void,glEvalCoord2d,(GLdouble u, GLdouble v)) +SDL_PROC_UNUSED(void,glEvalCoord2dv,(const GLdouble *u)) +SDL_PROC_UNUSED(void,glEvalCoord2f,(GLfloat u, GLfloat v)) +SDL_PROC_UNUSED(void,glEvalCoord2fv,(const GLfloat *u)) +SDL_PROC_UNUSED(void,glEvalMesh1,(GLenum mode, GLint i1, GLint i2)) +SDL_PROC_UNUSED(void,glEvalMesh2,(GLenum mode, GLint i1, GLint i2, GLint j1, GLint j2)) +SDL_PROC_UNUSED(void,glEvalPoint1,(GLint i)) +SDL_PROC_UNUSED(void,glEvalPoint2,(GLint i, GLint j)) +SDL_PROC_UNUSED(void,glFeedbackBuffer,(GLsizei size, GLenum type, GLfloat *buffer)) +SDL_PROC_UNUSED(void,glFinish,(void)) +SDL_PROC(void,glFlush,(void)) +SDL_PROC_UNUSED(void,glFogf,(GLenum pname, GLfloat param)) +SDL_PROC_UNUSED(void,glFogfv,(GLenum pname, const GLfloat *params)) +SDL_PROC_UNUSED(void,glFogi,(GLenum pname, GLint param)) +SDL_PROC_UNUSED(void,glFogiv,(GLenum pname, const GLint *params)) +SDL_PROC_UNUSED(void,glFrontFace,(GLenum mode)) +SDL_PROC_UNUSED(void,glFrustum,(GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble zNear, GLdouble zFar)) +SDL_PROC_UNUSED(GLuint,glGenLists,(GLsizei range)) +SDL_PROC(void,glGenTextures,(GLsizei n, GLuint *textures)) +SDL_PROC_UNUSED(void,glGetBooleanv,(GLenum pname, GLboolean *params)) +SDL_PROC_UNUSED(void,glGetClipPlane,(GLenum plane, GLdouble *equation)) +SDL_PROC_UNUSED(void,glGetDoublev,(GLenum pname, GLdouble *params)) +SDL_PROC_UNUSED(GLenum,glGetError,(void)) +SDL_PROC_UNUSED(void,glGetFloatv,(GLenum pname, GLfloat *params)) +SDL_PROC_UNUSED(void,glGetIntegerv,(GLenum pname, GLint *params)) +SDL_PROC_UNUSED(void,glGetLightfv,(GLenum light, GLenum pname, GLfloat *params)) +SDL_PROC_UNUSED(void,glGetLightiv,(GLenum light, GLenum pname, GLint *params)) +SDL_PROC_UNUSED(void,glGetMapdv,(GLenum target, GLenum query, GLdouble *v)) +SDL_PROC_UNUSED(void,glGetMapfv,(GLenum target, GLenum query, GLfloat *v)) +SDL_PROC_UNUSED(void,glGetMapiv,(GLenum target, GLenum query, GLint *v)) +SDL_PROC_UNUSED(void,glGetMaterialfv,(GLenum face, GLenum pname, GLfloat *params)) +SDL_PROC_UNUSED(void,glGetMaterialiv,(GLenum face, GLenum pname, GLint *params)) +SDL_PROC_UNUSED(void,glGetPixelMapfv,(GLenum map, GLfloat *values)) +SDL_PROC_UNUSED(void,glGetPixelMapuiv,(GLenum map, GLuint *values)) +SDL_PROC_UNUSED(void,glGetPixelMapusv,(GLenum map, GLushort *values)) +SDL_PROC_UNUSED(void,glGetPointerv,(GLenum pname, GLvoid* *params)) +SDL_PROC_UNUSED(void,glGetPolygonStipple,(GLubyte *mask)) +SDL_PROC(const GLubyte *,glGetString,(GLenum name)) +SDL_PROC_UNUSED(void,glGetTexEnvfv,(GLenum target, GLenum pname, GLfloat *params)) +SDL_PROC_UNUSED(void,glGetTexEnviv,(GLenum target, GLenum pname, GLint *params)) +SDL_PROC_UNUSED(void,glGetTexGendv,(GLenum coord, GLenum pname, GLdouble *params)) +SDL_PROC_UNUSED(void,glGetTexGenfv,(GLenum coord, GLenum pname, GLfloat *params)) +SDL_PROC_UNUSED(void,glGetTexGeniv,(GLenum coord, GLenum pname, GLint *params)) +SDL_PROC_UNUSED(void,glGetTexImage,(GLenum target, GLint level, GLenum format, GLenum type, GLvoid *pixels)) +SDL_PROC_UNUSED(void,glGetTexLevelParameterfv,(GLenum target, GLint level, GLenum pname, GLfloat *params)) +SDL_PROC_UNUSED(void,glGetTexLevelParameteriv,(GLenum target, GLint level, GLenum pname, GLint *params)) +SDL_PROC_UNUSED(void,glGetTexParameterfv,(GLenum target, GLenum pname, GLfloat *params)) +SDL_PROC_UNUSED(void,glGetTexParameteriv,(GLenum target, GLenum pname, GLint *params)) +SDL_PROC_UNUSED(void,glHint,(GLenum target, GLenum mode)) +SDL_PROC_UNUSED(void,glIndexMask,(GLuint mask)) +SDL_PROC_UNUSED(void,glIndexPointer,(GLenum type, GLsizei stride, const GLvoid *pointer)) +SDL_PROC_UNUSED(void,glIndexd,(GLdouble c)) +SDL_PROC_UNUSED(void,glIndexdv,(const GLdouble *c)) +SDL_PROC_UNUSED(void,glIndexf,(GLfloat c)) +SDL_PROC_UNUSED(void,glIndexfv,(const GLfloat *c)) +SDL_PROC_UNUSED(void,glIndexi,(GLint c)) +SDL_PROC_UNUSED(void,glIndexiv,(const GLint *c)) +SDL_PROC_UNUSED(void,glIndexs,(GLshort c)) +SDL_PROC_UNUSED(void,glIndexsv,(const GLshort *c)) +SDL_PROC_UNUSED(void,glIndexub,(GLubyte c)) +SDL_PROC_UNUSED(void,glIndexubv,(const GLubyte *c)) +SDL_PROC_UNUSED(void,glInitNames,(void)) +SDL_PROC_UNUSED(void,glInterleavedArrays,(GLenum format, GLsizei stride, const GLvoid *pointer)) +SDL_PROC_UNUSED(GLboolean,glIsEnabled,(GLenum cap)) +SDL_PROC_UNUSED(GLboolean,glIsList,(GLuint list)) +SDL_PROC_UNUSED(GLboolean,glIsTexture,(GLuint texture)) +SDL_PROC_UNUSED(void,glLightModelf,(GLenum pname, GLfloat param)) +SDL_PROC_UNUSED(void,glLightModelfv,(GLenum pname, const GLfloat *params)) +SDL_PROC_UNUSED(void,glLightModeli,(GLenum pname, GLint param)) +SDL_PROC_UNUSED(void,glLightModeliv,(GLenum pname, const GLint *params)) +SDL_PROC_UNUSED(void,glLightf,(GLenum light, GLenum pname, GLfloat param)) +SDL_PROC_UNUSED(void,glLightfv,(GLenum light, GLenum pname, const GLfloat *params)) +SDL_PROC_UNUSED(void,glLighti,(GLenum light, GLenum pname, GLint param)) +SDL_PROC_UNUSED(void,glLightiv,(GLenum light, GLenum pname, const GLint *params)) +SDL_PROC_UNUSED(void,glLineStipple,(GLint factor, GLushort pattern)) +SDL_PROC_UNUSED(void,glLineWidth,(GLfloat width)) +SDL_PROC_UNUSED(void,glListBase,(GLuint base)) +SDL_PROC(void,glLoadIdentity,(void)) +SDL_PROC_UNUSED(void,glLoadMatrixd,(const GLdouble *m)) +SDL_PROC_UNUSED(void,glLoadMatrixf,(const GLfloat *m)) +SDL_PROC_UNUSED(void,glLoadName,(GLuint name)) +SDL_PROC_UNUSED(void,glLogicOp,(GLenum opcode)) +SDL_PROC_UNUSED(void,glMap1d,(GLenum target, GLdouble u1, GLdouble u2, GLint stride, GLint order, const GLdouble *points)) +SDL_PROC_UNUSED(void,glMap1f,(GLenum target, GLfloat u1, GLfloat u2, GLint stride, GLint order, const GLfloat *points)) +SDL_PROC_UNUSED(void,glMap2d,(GLenum target, GLdouble u1, GLdouble u2, GLint ustride, GLint uorder, GLdouble v1, GLdouble v2, GLint vstride, GLint vorder, const GLdouble *points)) +SDL_PROC_UNUSED(void,glMap2f,(GLenum target, GLfloat u1, GLfloat u2, GLint ustride, GLint uorder, GLfloat v1, GLfloat v2, GLint vstride, GLint vorder, const GLfloat *points)) +SDL_PROC_UNUSED(void,glMapGrid1d,(GLint un, GLdouble u1, GLdouble u2)) +SDL_PROC_UNUSED(void,glMapGrid1f,(GLint un, GLfloat u1, GLfloat u2)) +SDL_PROC_UNUSED(void,glMapGrid2d,(GLint un, GLdouble u1, GLdouble u2, GLint vn, GLdouble v1, GLdouble v2)) +SDL_PROC_UNUSED(void,glMapGrid2f,(GLint un, GLfloat u1, GLfloat u2, GLint vn, GLfloat v1, GLfloat v2)) +SDL_PROC_UNUSED(void,glMaterialf,(GLenum face, GLenum pname, GLfloat param)) +SDL_PROC_UNUSED(void,glMaterialfv,(GLenum face, GLenum pname, const GLfloat *params)) +SDL_PROC_UNUSED(void,glMateriali,(GLenum face, GLenum pname, GLint param)) +SDL_PROC_UNUSED(void,glMaterialiv,(GLenum face, GLenum pname, const GLint *params)) +SDL_PROC(void,glMatrixMode,(GLenum mode)) +SDL_PROC_UNUSED(void,glMultMatrixd,(const GLdouble *m)) +SDL_PROC_UNUSED(void,glMultMatrixf,(const GLfloat *m)) +SDL_PROC_UNUSED(void,glNewList,(GLuint list, GLenum mode)) +SDL_PROC_UNUSED(void,glNormal3b,(GLbyte nx, GLbyte ny, GLbyte nz)) +SDL_PROC_UNUSED(void,glNormal3bv,(const GLbyte *v)) +SDL_PROC_UNUSED(void,glNormal3d,(GLdouble nx, GLdouble ny, GLdouble nz)) +SDL_PROC_UNUSED(void,glNormal3dv,(const GLdouble *v)) +SDL_PROC_UNUSED(void,glNormal3f,(GLfloat nx, GLfloat ny, GLfloat nz)) +SDL_PROC_UNUSED(void,glNormal3fv,(const GLfloat *v)) +SDL_PROC_UNUSED(void,glNormal3i,(GLint nx, GLint ny, GLint nz)) +SDL_PROC_UNUSED(void,glNormal3iv,(const GLint *v)) +SDL_PROC_UNUSED(void,glNormal3s,(GLshort nx, GLshort ny, GLshort nz)) +SDL_PROC_UNUSED(void,glNormal3sv,(const GLshort *v)) +SDL_PROC_UNUSED(void,glNormalPointer,(GLenum type, GLsizei stride, const GLvoid *pointer)) +SDL_PROC(void,glOrtho,(GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble zNear, GLdouble zFar)) +SDL_PROC_UNUSED(void,glPassThrough,(GLfloat token)) +SDL_PROC_UNUSED(void,glPixelMapfv,(GLenum map, GLsizei mapsize, const GLfloat *values)) +SDL_PROC_UNUSED(void,glPixelMapuiv,(GLenum map, GLsizei mapsize, const GLuint *values)) +SDL_PROC_UNUSED(void,glPixelMapusv,(GLenum map, GLsizei mapsize, const GLushort *values)) +SDL_PROC_UNUSED(void,glPixelStoref,(GLenum pname, GLfloat param)) +SDL_PROC(void,glPixelStorei,(GLenum pname, GLint param)) +SDL_PROC_UNUSED(void,glPixelTransferf,(GLenum pname, GLfloat param)) +SDL_PROC_UNUSED(void,glPixelTransferi,(GLenum pname, GLint param)) +SDL_PROC_UNUSED(void,glPixelZoom,(GLfloat xfactor, GLfloat yfactor)) +SDL_PROC_UNUSED(void,glPointSize,(GLfloat size)) +SDL_PROC_UNUSED(void,glPolygonMode,(GLenum face, GLenum mode)) +SDL_PROC_UNUSED(void,glPolygonOffset,(GLfloat factor, GLfloat units)) +SDL_PROC_UNUSED(void,glPolygonStipple,(const GLubyte *mask)) +SDL_PROC(void,glPopAttrib,(void)) +SDL_PROC(void,glPopClientAttrib,(void)) +SDL_PROC(void,glPopMatrix,(void)) +SDL_PROC_UNUSED(void,glPopName,(void)) +SDL_PROC_UNUSED(void,glPrioritizeTextures,(GLsizei n, const GLuint *textures, const GLclampf *priorities)) +SDL_PROC(void,glPushAttrib,(GLbitfield mask)) +SDL_PROC(void,glPushClientAttrib,(GLbitfield mask)) +SDL_PROC(void,glPushMatrix,(void)) +SDL_PROC_UNUSED(void,glPushName,(GLuint name)) +SDL_PROC_UNUSED(void,glRasterPos2d,(GLdouble x, GLdouble y)) +SDL_PROC_UNUSED(void,glRasterPos2dv,(const GLdouble *v)) +SDL_PROC_UNUSED(void,glRasterPos2f,(GLfloat x, GLfloat y)) +SDL_PROC_UNUSED(void,glRasterPos2fv,(const GLfloat *v)) +SDL_PROC_UNUSED(void,glRasterPos2i,(GLint x, GLint y)) +SDL_PROC_UNUSED(void,glRasterPos2iv,(const GLint *v)) +SDL_PROC_UNUSED(void,glRasterPos2s,(GLshort x, GLshort y)) +SDL_PROC_UNUSED(void,glRasterPos2sv,(const GLshort *v)) +SDL_PROC_UNUSED(void,glRasterPos3d,(GLdouble x, GLdouble y, GLdouble z)) +SDL_PROC_UNUSED(void,glRasterPos3dv,(const GLdouble *v)) +SDL_PROC_UNUSED(void,glRasterPos3f,(GLfloat x, GLfloat y, GLfloat z)) +SDL_PROC_UNUSED(void,glRasterPos3fv,(const GLfloat *v)) +SDL_PROC_UNUSED(void,glRasterPos3i,(GLint x, GLint y, GLint z)) +SDL_PROC_UNUSED(void,glRasterPos3iv,(const GLint *v)) +SDL_PROC_UNUSED(void,glRasterPos3s,(GLshort x, GLshort y, GLshort z)) +SDL_PROC_UNUSED(void,glRasterPos3sv,(const GLshort *v)) +SDL_PROC_UNUSED(void,glRasterPos4d,(GLdouble x, GLdouble y, GLdouble z, GLdouble w)) +SDL_PROC_UNUSED(void,glRasterPos4dv,(const GLdouble *v)) +SDL_PROC_UNUSED(void,glRasterPos4f,(GLfloat x, GLfloat y, GLfloat z, GLfloat w)) +SDL_PROC_UNUSED(void,glRasterPos4fv,(const GLfloat *v)) +SDL_PROC_UNUSED(void,glRasterPos4i,(GLint x, GLint y, GLint z, GLint w)) +SDL_PROC_UNUSED(void,glRasterPos4iv,(const GLint *v)) +SDL_PROC_UNUSED(void,glRasterPos4s,(GLshort x, GLshort y, GLshort z, GLshort w)) +SDL_PROC_UNUSED(void,glRasterPos4sv,(const GLshort *v)) +SDL_PROC_UNUSED(void,glReadBuffer,(GLenum mode)) +SDL_PROC_UNUSED(void,glReadPixels,(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid *pixels)) +SDL_PROC_UNUSED(void,glRectd,(GLdouble x1, GLdouble y1, GLdouble x2, GLdouble y2)) +SDL_PROC_UNUSED(void,glRectdv,(const GLdouble *v1, const GLdouble *v2)) +SDL_PROC_UNUSED(void,glRectf,(GLfloat x1, GLfloat y1, GLfloat x2, GLfloat y2)) +SDL_PROC_UNUSED(void,glRectfv,(const GLfloat *v1, const GLfloat *v2)) +SDL_PROC_UNUSED(void,glRecti,(GLint x1, GLint y1, GLint x2, GLint y2)) +SDL_PROC_UNUSED(void,glRectiv,(const GLint *v1, const GLint *v2)) +SDL_PROC_UNUSED(void,glRects,(GLshort x1, GLshort y1, GLshort x2, GLshort y2)) +SDL_PROC_UNUSED(void,glRectsv,(const GLshort *v1, const GLshort *v2)) +SDL_PROC_UNUSED(GLint,glRenderMode,(GLenum mode)) +SDL_PROC_UNUSED(void,glRotated,(GLdouble angle, GLdouble x, GLdouble y, GLdouble z)) +SDL_PROC_UNUSED(void,glRotatef,(GLfloat angle, GLfloat x, GLfloat y, GLfloat z)) +SDL_PROC_UNUSED(void,glScaled,(GLdouble x, GLdouble y, GLdouble z)) +SDL_PROC_UNUSED(void,glScalef,(GLfloat x, GLfloat y, GLfloat z)) +SDL_PROC_UNUSED(void,glScissor,(GLint x, GLint y, GLsizei width, GLsizei height)) +SDL_PROC_UNUSED(void,glSelectBuffer,(GLsizei size, GLuint *buffer)) +SDL_PROC_UNUSED(void,glShadeModel,(GLenum mode)) +SDL_PROC_UNUSED(void,glStencilFunc,(GLenum func, GLint ref, GLuint mask)) +SDL_PROC_UNUSED(void,glStencilMask,(GLuint mask)) +SDL_PROC_UNUSED(void,glStencilOp,(GLenum fail, GLenum zfail, GLenum zpass)) +SDL_PROC_UNUSED(void,glTexCoord1d,(GLdouble s)) +SDL_PROC_UNUSED(void,glTexCoord1dv,(const GLdouble *v)) +SDL_PROC_UNUSED(void,glTexCoord1f,(GLfloat s)) +SDL_PROC_UNUSED(void,glTexCoord1fv,(const GLfloat *v)) +SDL_PROC_UNUSED(void,glTexCoord1i,(GLint s)) +SDL_PROC_UNUSED(void,glTexCoord1iv,(const GLint *v)) +SDL_PROC_UNUSED(void,glTexCoord1s,(GLshort s)) +SDL_PROC_UNUSED(void,glTexCoord1sv,(const GLshort *v)) +SDL_PROC_UNUSED(void,glTexCoord2d,(GLdouble s, GLdouble t)) +SDL_PROC_UNUSED(void,glTexCoord2dv,(const GLdouble *v)) +SDL_PROC(void,glTexCoord2f,(GLfloat s, GLfloat t)) +SDL_PROC_UNUSED(void,glTexCoord2fv,(const GLfloat *v)) +SDL_PROC_UNUSED(void,glTexCoord2i,(GLint s, GLint t)) +SDL_PROC_UNUSED(void,glTexCoord2iv,(const GLint *v)) +SDL_PROC_UNUSED(void,glTexCoord2s,(GLshort s, GLshort t)) +SDL_PROC_UNUSED(void,glTexCoord2sv,(const GLshort *v)) +SDL_PROC_UNUSED(void,glTexCoord3d,(GLdouble s, GLdouble t, GLdouble r)) +SDL_PROC_UNUSED(void,glTexCoord3dv,(const GLdouble *v)) +SDL_PROC_UNUSED(void,glTexCoord3f,(GLfloat s, GLfloat t, GLfloat r)) +SDL_PROC_UNUSED(void,glTexCoord3fv,(const GLfloat *v)) +SDL_PROC_UNUSED(void,glTexCoord3i,(GLint s, GLint t, GLint r)) +SDL_PROC_UNUSED(void,glTexCoord3iv,(const GLint *v)) +SDL_PROC_UNUSED(void,glTexCoord3s,(GLshort s, GLshort t, GLshort r)) +SDL_PROC_UNUSED(void,glTexCoord3sv,(const GLshort *v)) +SDL_PROC_UNUSED(void,glTexCoord4d,(GLdouble s, GLdouble t, GLdouble r, GLdouble q)) +SDL_PROC_UNUSED(void,glTexCoord4dv,(const GLdouble *v)) +SDL_PROC_UNUSED(void,glTexCoord4f,(GLfloat s, GLfloat t, GLfloat r, GLfloat q)) +SDL_PROC_UNUSED(void,glTexCoord4fv,(const GLfloat *v)) +SDL_PROC_UNUSED(void,glTexCoord4i,(GLint s, GLint t, GLint r, GLint q)) +SDL_PROC_UNUSED(void,glTexCoord4iv,(const GLint *v)) +SDL_PROC_UNUSED(void,glTexCoord4s,(GLshort s, GLshort t, GLshort r, GLshort q)) +SDL_PROC_UNUSED(void,glTexCoord4sv,(const GLshort *v)) +SDL_PROC_UNUSED(void,glTexCoordPointer,(GLint size, GLenum type, GLsizei stride, const GLvoid *pointer)) +SDL_PROC(void,glTexEnvf,(GLenum target, GLenum pname, GLfloat param)) +SDL_PROC_UNUSED(void,glTexEnvfv,(GLenum target, GLenum pname, const GLfloat *params)) +SDL_PROC_UNUSED(void,glTexEnvi,(GLenum target, GLenum pname, GLint param)) +SDL_PROC_UNUSED(void,glTexEnviv,(GLenum target, GLenum pname, const GLint *params)) +SDL_PROC_UNUSED(void,glTexGend,(GLenum coord, GLenum pname, GLdouble param)) +SDL_PROC_UNUSED(void,glTexGendv,(GLenum coord, GLenum pname, const GLdouble *params)) +SDL_PROC_UNUSED(void,glTexGenf,(GLenum coord, GLenum pname, GLfloat param)) +SDL_PROC_UNUSED(void,glTexGenfv,(GLenum coord, GLenum pname, const GLfloat *params)) +SDL_PROC_UNUSED(void,glTexGeni,(GLenum coord, GLenum pname, GLint param)) +SDL_PROC_UNUSED(void,glTexGeniv,(GLenum coord, GLenum pname, const GLint *params)) +SDL_PROC_UNUSED(void,glTexImage1D,(GLenum target, GLint level, GLint internalformat, GLsizei width, GLint border, GLenum format, GLenum type, const GLvoid *pixels)) +SDL_PROC(void,glTexImage2D,(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *pixels)) +SDL_PROC_UNUSED(void,glTexParameterf,(GLenum target, GLenum pname, GLfloat param)) +SDL_PROC_UNUSED(void,glTexParameterfv,(GLenum target, GLenum pname, const GLfloat *params)) +SDL_PROC(void,glTexParameteri,(GLenum target, GLenum pname, GLint param)) +SDL_PROC_UNUSED(void,glTexParameteriv,(GLenum target, GLenum pname, const GLint *params)) +SDL_PROC_UNUSED(void,glTexSubImage1D,(GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const GLvoid *pixels)) +SDL_PROC(void,glTexSubImage2D,(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels)) +SDL_PROC_UNUSED(void,glTranslated,(GLdouble x, GLdouble y, GLdouble z)) +SDL_PROC_UNUSED(void,glTranslatef,(GLfloat x, GLfloat y, GLfloat z)) +SDL_PROC_UNUSED(void,glVertex2d,(GLdouble x, GLdouble y)) +SDL_PROC_UNUSED(void,glVertex2dv,(const GLdouble *v)) +SDL_PROC_UNUSED(void,glVertex2f,(GLfloat x, GLfloat y)) +SDL_PROC_UNUSED(void,glVertex2fv,(const GLfloat *v)) +SDL_PROC(void,glVertex2i,(GLint x, GLint y)) +SDL_PROC_UNUSED(void,glVertex2iv,(const GLint *v)) +SDL_PROC_UNUSED(void,glVertex2s,(GLshort x, GLshort y)) +SDL_PROC_UNUSED(void,glVertex2sv,(const GLshort *v)) +SDL_PROC_UNUSED(void,glVertex3d,(GLdouble x, GLdouble y, GLdouble z)) +SDL_PROC_UNUSED(void,glVertex3dv,(const GLdouble *v)) +SDL_PROC_UNUSED(void,glVertex3f,(GLfloat x, GLfloat y, GLfloat z)) +SDL_PROC_UNUSED(void,glVertex3fv,(const GLfloat *v)) +SDL_PROC_UNUSED(void,glVertex3i,(GLint x, GLint y, GLint z)) +SDL_PROC_UNUSED(void,glVertex3iv,(const GLint *v)) +SDL_PROC_UNUSED(void,glVertex3s,(GLshort x, GLshort y, GLshort z)) +SDL_PROC_UNUSED(void,glVertex3sv,(const GLshort *v)) +SDL_PROC_UNUSED(void,glVertex4d,(GLdouble x, GLdouble y, GLdouble z, GLdouble w)) +SDL_PROC_UNUSED(void,glVertex4dv,(const GLdouble *v)) +SDL_PROC_UNUSED(void,glVertex4f,(GLfloat x, GLfloat y, GLfloat z, GLfloat w)) +SDL_PROC_UNUSED(void,glVertex4fv,(const GLfloat *v)) +SDL_PROC_UNUSED(void,glVertex4i,(GLint x, GLint y, GLint z, GLint w)) +SDL_PROC_UNUSED(void,glVertex4iv,(const GLint *v)) +SDL_PROC_UNUSED(void,glVertex4s,(GLshort x, GLshort y, GLshort z, GLshort w)) +SDL_PROC_UNUSED(void,glVertex4sv,(const GLshort *v)) +SDL_PROC_UNUSED(void,glVertexPointer,(GLint size, GLenum type, GLsizei stride, const GLvoid *pointer)) +SDL_PROC(void,glViewport,(GLint x, GLint y, GLsizei width, GLsizei height)) diff --git a/3rdparty/SDL/src/video/SDL_leaks.h b/3rdparty/SDL/src/video/SDL_leaks.h new file mode 100644 index 0000000..74495c6 --- /dev/null +++ b/3rdparty/SDL/src/video/SDL_leaks.h @@ -0,0 +1,31 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* Define this if you want surface leak detection code enabled */ +/*#define CHECK_LEAKS*/ + +/* Global variables used to check leaks in code using SDL */ + +#ifdef CHECK_LEAKS +extern int surfaces_allocated; +#endif diff --git a/3rdparty/SDL/src/video/SDL_pixels.c b/3rdparty/SDL/src/video/SDL_pixels.c new file mode 100644 index 0000000..1a7fd51 --- /dev/null +++ b/3rdparty/SDL/src/video/SDL_pixels.c @@ -0,0 +1,626 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* General (mostly internal) pixel/color manipulation routines for SDL */ + +#include "SDL_endian.h" +#include "SDL_video.h" +#include "SDL_sysvideo.h" +#include "SDL_blit.h" +#include "SDL_pixels_c.h" +#include "SDL_RLEaccel_c.h" + +/* Helper functions */ +/* + * Allocate a pixel format structure and fill it according to the given info. + */ +SDL_PixelFormat *SDL_AllocFormat(int bpp, + Uint32 Rmask, Uint32 Gmask, Uint32 Bmask, Uint32 Amask) +{ + SDL_PixelFormat *format; + Uint32 mask; + + /* Allocate an empty pixel format structure */ + format = SDL_malloc(sizeof(*format)); + if ( format == NULL ) { + SDL_OutOfMemory(); + return(NULL); + } + SDL_memset(format, 0, sizeof(*format)); + format->alpha = SDL_ALPHA_OPAQUE; + + /* Set up the format */ + format->BitsPerPixel = bpp; + format->BytesPerPixel = (bpp+7)/8; + if ( Rmask || Bmask || Gmask ) { /* Packed pixels with custom mask */ + format->palette = NULL; + format->Rshift = 0; + format->Rloss = 8; + if ( Rmask ) { + for ( mask = Rmask; !(mask&0x01); mask >>= 1 ) + ++format->Rshift; + for ( ; (mask&0x01); mask >>= 1 ) + --format->Rloss; + } + format->Gshift = 0; + format->Gloss = 8; + if ( Gmask ) { + for ( mask = Gmask; !(mask&0x01); mask >>= 1 ) + ++format->Gshift; + for ( ; (mask&0x01); mask >>= 1 ) + --format->Gloss; + } + format->Bshift = 0; + format->Bloss = 8; + if ( Bmask ) { + for ( mask = Bmask; !(mask&0x01); mask >>= 1 ) + ++format->Bshift; + for ( ; (mask&0x01); mask >>= 1 ) + --format->Bloss; + } + format->Ashift = 0; + format->Aloss = 8; + if ( Amask ) { + for ( mask = Amask; !(mask&0x01); mask >>= 1 ) + ++format->Ashift; + for ( ; (mask&0x01); mask >>= 1 ) + --format->Aloss; + } + format->Rmask = Rmask; + format->Gmask = Gmask; + format->Bmask = Bmask; + format->Amask = Amask; + } else if ( bpp > 8 ) { /* Packed pixels with standard mask */ + /* R-G-B */ + if ( bpp > 24 ) + bpp = 24; + format->Rloss = 8-(bpp/3); + format->Gloss = 8-(bpp/3)-(bpp%3); + format->Bloss = 8-(bpp/3); + format->Rshift = ((bpp/3)+(bpp%3))+(bpp/3); + format->Gshift = (bpp/3); + format->Bshift = 0; + format->Rmask = ((0xFF>>format->Rloss)<<format->Rshift); + format->Gmask = ((0xFF>>format->Gloss)<<format->Gshift); + format->Bmask = ((0xFF>>format->Bloss)<<format->Bshift); + } else { + /* Palettized formats have no mask info */ + format->Rloss = 8; + format->Gloss = 8; + format->Bloss = 8; + format->Aloss = 8; + format->Rshift = 0; + format->Gshift = 0; + format->Bshift = 0; + format->Ashift = 0; + format->Rmask = 0; + format->Gmask = 0; + format->Bmask = 0; + format->Amask = 0; + } + if ( bpp <= 8 ) { /* Palettized mode */ + int ncolors = 1<<bpp; +#ifdef DEBUG_PALETTE + fprintf(stderr,"bpp=%d ncolors=%d\n",bpp,ncolors); +#endif + format->palette = (SDL_Palette *)SDL_malloc(sizeof(SDL_Palette)); + if ( format->palette == NULL ) { + SDL_FreeFormat(format); + SDL_OutOfMemory(); + return(NULL); + } + (format->palette)->ncolors = ncolors; + (format->palette)->colors = (SDL_Color *)SDL_malloc( + (format->palette)->ncolors*sizeof(SDL_Color)); + if ( (format->palette)->colors == NULL ) { + SDL_FreeFormat(format); + SDL_OutOfMemory(); + return(NULL); + } + if ( Rmask || Bmask || Gmask ) { + /* create palette according to masks */ + int i; + int Rm=0,Gm=0,Bm=0; + int Rw=0,Gw=0,Bw=0; +#ifdef ENABLE_PALETTE_ALPHA + int Am=0,Aw=0; +#endif + if(Rmask) + { + Rw=8-format->Rloss; + for(i=format->Rloss;i>0;i-=Rw) + Rm|=1<<i; + } +#ifdef DEBUG_PALETTE + fprintf(stderr,"Rw=%d Rm=0x%02X\n",Rw,Rm); +#endif + if(Gmask) + { + Gw=8-format->Gloss; + for(i=format->Gloss;i>0;i-=Gw) + Gm|=1<<i; + } +#ifdef DEBUG_PALETTE + fprintf(stderr,"Gw=%d Gm=0x%02X\n",Gw,Gm); +#endif + if(Bmask) + { + Bw=8-format->Bloss; + for(i=format->Bloss;i>0;i-=Bw) + Bm|=1<<i; + } +#ifdef DEBUG_PALETTE + fprintf(stderr,"Bw=%d Bm=0x%02X\n",Bw,Bm); +#endif +#ifdef ENABLE_PALETTE_ALPHA + if(Amask) + { + Aw=8-format->Aloss; + for(i=format->Aloss;i>0;i-=Aw) + Am|=1<<i; + } +# ifdef DEBUG_PALETTE + fprintf(stderr,"Aw=%d Am=0x%02X\n",Aw,Am); +# endif +#endif + for(i=0; i < ncolors; ++i) { + int r,g,b; + r=(i&Rmask)>>format->Rshift; + r=(r<<format->Rloss)|((r*Rm)>>Rw); + format->palette->colors[i].r=r; + + g=(i&Gmask)>>format->Gshift; + g=(g<<format->Gloss)|((g*Gm)>>Gw); + format->palette->colors[i].g=g; + + b=(i&Bmask)>>format->Bshift; + b=(b<<format->Bloss)|((b*Bm)>>Bw); + format->palette->colors[i].b=b; + +#ifdef ENABLE_PALETTE_ALPHA + a=(i&Amask)>>format->Ashift; + a=(a<<format->Aloss)|((a*Am)>>Aw); + format->palette->colors[i].unused=a; +#else + format->palette->colors[i].unused=0; +#endif + } + } else if ( ncolors == 2 ) { + /* Create a black and white bitmap palette */ + format->palette->colors[0].r = 0xFF; + format->palette->colors[0].g = 0xFF; + format->palette->colors[0].b = 0xFF; + format->palette->colors[1].r = 0x00; + format->palette->colors[1].g = 0x00; + format->palette->colors[1].b = 0x00; + } else { + /* Create an empty palette */ + SDL_memset((format->palette)->colors, 0, + (format->palette)->ncolors*sizeof(SDL_Color)); + } + } + return(format); +} +SDL_PixelFormat *SDL_ReallocFormat(SDL_Surface *surface, int bpp, + Uint32 Rmask, Uint32 Gmask, Uint32 Bmask, Uint32 Amask) +{ + if ( surface->format ) { + SDL_FreeFormat(surface->format); + SDL_FormatChanged(surface); + } + surface->format = SDL_AllocFormat(bpp, Rmask, Gmask, Bmask, Amask); + return surface->format; +} + +/* + * Change any previous mappings from/to the new surface format + */ +void SDL_FormatChanged(SDL_Surface *surface) +{ + static int format_version = 0; + ++format_version; + if ( format_version < 0 ) { /* It wrapped... */ + format_version = 1; + } + surface->format_version = format_version; + SDL_InvalidateMap(surface->map); +} +/* + * Free a previously allocated format structure + */ +void SDL_FreeFormat(SDL_PixelFormat *format) +{ + if ( format ) { + if ( format->palette ) { + if ( format->palette->colors ) { + SDL_free(format->palette->colors); + } + SDL_free(format->palette); + } + SDL_free(format); + } +} +/* + * Calculate an 8-bit (3 red, 3 green, 2 blue) dithered palette of colors + */ +void SDL_DitherColors(SDL_Color *colors, int bpp) +{ + int i; + if(bpp != 8) + return; /* only 8bpp supported right now */ + + for(i = 0; i < 256; i++) { + int r, g, b; + /* map each bit field to the full [0, 255] interval, + so 0 is mapped to (0, 0, 0) and 255 to (255, 255, 255) */ + r = i & 0xe0; + r |= r >> 3 | r >> 6; + colors[i].r = r; + g = (i << 3) & 0xe0; + g |= g >> 3 | g >> 6; + colors[i].g = g; + b = i & 0x3; + b |= b << 2; + b |= b << 4; + colors[i].b = b; + } +} +/* + * Calculate the pad-aligned scanline width of a surface + */ +Uint16 SDL_CalculatePitch(SDL_Surface *surface) +{ + Uint16 pitch; + + /* Surface should be 4-byte aligned for speed */ + pitch = surface->w*surface->format->BytesPerPixel; + switch (surface->format->BitsPerPixel) { + case 1: + pitch = (pitch+7)/8; + break; + case 4: + pitch = (pitch+1)/2; + break; + default: + break; + } + pitch = (pitch + 3) & ~3; /* 4-byte aligning */ + return(pitch); +} +/* + * Match an RGB value to a particular palette index + */ +Uint8 SDL_FindColor(SDL_Palette *pal, Uint8 r, Uint8 g, Uint8 b) +{ + /* Do colorspace distance matching */ + unsigned int smallest; + unsigned int distance; + int rd, gd, bd; + int i; + Uint8 pixel=0; + + smallest = ~0; + for ( i=0; i<pal->ncolors; ++i ) { + rd = pal->colors[i].r - r; + gd = pal->colors[i].g - g; + bd = pal->colors[i].b - b; + distance = (rd*rd)+(gd*gd)+(bd*bd); + if ( distance < smallest ) { + pixel = i; + if ( distance == 0 ) { /* Perfect match! */ + break; + } + smallest = distance; + } + } + return(pixel); +} + +/* Find the opaque pixel value corresponding to an RGB triple */ +Uint32 SDL_MapRGB +(const SDL_PixelFormat * const format, + const Uint8 r, const Uint8 g, const Uint8 b) +{ + if ( format->palette == NULL ) { + return (r >> format->Rloss) << format->Rshift + | (g >> format->Gloss) << format->Gshift + | (b >> format->Bloss) << format->Bshift + | format->Amask; + } else { + return SDL_FindColor(format->palette, r, g, b); + } +} + +/* Find the pixel value corresponding to an RGBA quadruple */ +Uint32 SDL_MapRGBA +(const SDL_PixelFormat * const format, + const Uint8 r, const Uint8 g, const Uint8 b, const Uint8 a) +{ + if ( format->palette == NULL ) { + return (r >> format->Rloss) << format->Rshift + | (g >> format->Gloss) << format->Gshift + | (b >> format->Bloss) << format->Bshift + | ((a >> format->Aloss) << format->Ashift & format->Amask); + } else { + return SDL_FindColor(format->palette, r, g, b); + } +} + +void SDL_GetRGBA(Uint32 pixel, const SDL_PixelFormat * const fmt, + Uint8 *r, Uint8 *g, Uint8 *b, Uint8 *a) +{ + if ( fmt->palette == NULL ) { + /* + * This makes sure that the result is mapped to the + * interval [0..255], and the maximum value for each + * component is 255. This is important to make sure + * that white is indeed reported as (255, 255, 255), + * and that opaque alpha is 255. + * This only works for RGB bit fields at least 4 bit + * wide, which is almost always the case. + */ + unsigned v; + v = (pixel & fmt->Rmask) >> fmt->Rshift; + *r = (v << fmt->Rloss) + (v >> (8 - (fmt->Rloss << 1))); + v = (pixel & fmt->Gmask) >> fmt->Gshift; + *g = (v << fmt->Gloss) + (v >> (8 - (fmt->Gloss << 1))); + v = (pixel & fmt->Bmask) >> fmt->Bshift; + *b = (v << fmt->Bloss) + (v >> (8 - (fmt->Bloss << 1))); + if(fmt->Amask) { + v = (pixel & fmt->Amask) >> fmt->Ashift; + *a = (v << fmt->Aloss) + (v >> (8 - (fmt->Aloss << 1))); + } else { + *a = SDL_ALPHA_OPAQUE; + } + } else { + *r = fmt->palette->colors[pixel].r; + *g = fmt->palette->colors[pixel].g; + *b = fmt->palette->colors[pixel].b; + *a = SDL_ALPHA_OPAQUE; + } +} + +void SDL_GetRGB(Uint32 pixel, const SDL_PixelFormat * const fmt, + Uint8 *r,Uint8 *g,Uint8 *b) +{ + if ( fmt->palette == NULL ) { + /* the note for SDL_GetRGBA above applies here too */ + unsigned v; + v = (pixel & fmt->Rmask) >> fmt->Rshift; + *r = (v << fmt->Rloss) + (v >> (8 - (fmt->Rloss << 1))); + v = (pixel & fmt->Gmask) >> fmt->Gshift; + *g = (v << fmt->Gloss) + (v >> (8 - (fmt->Gloss << 1))); + v = (pixel & fmt->Bmask) >> fmt->Bshift; + *b = (v << fmt->Bloss) + (v >> (8 - (fmt->Bloss << 1))); + } else { + *r = fmt->palette->colors[pixel].r; + *g = fmt->palette->colors[pixel].g; + *b = fmt->palette->colors[pixel].b; + } +} + +/* Apply gamma to a set of colors - this is easy. :) */ +void SDL_ApplyGamma(Uint16 *gamma, SDL_Color *colors, SDL_Color *output, + int ncolors) +{ + int i; + + for ( i=0; i<ncolors; ++i ) { + output[i].r = gamma[0*256 + colors[i].r] >> 8; + output[i].g = gamma[1*256 + colors[i].g] >> 8; + output[i].b = gamma[2*256 + colors[i].b] >> 8; + } +} + +/* Map from Palette to Palette */ +static Uint8 *Map1to1(SDL_Palette *src, SDL_Palette *dst, int *identical) +{ + Uint8 *map; + int i; + + if ( identical ) { + if ( src->ncolors <= dst->ncolors ) { + /* If an identical palette, no need to map */ + if ( SDL_memcmp(src->colors, dst->colors, src->ncolors* + sizeof(SDL_Color)) == 0 ) { + *identical = 1; + return(NULL); + } + } + *identical = 0; + } + map = (Uint8 *)SDL_malloc(src->ncolors); + if ( map == NULL ) { + SDL_OutOfMemory(); + return(NULL); + } + for ( i=0; i<src->ncolors; ++i ) { + map[i] = SDL_FindColor(dst, + src->colors[i].r, src->colors[i].g, src->colors[i].b); + } + return(map); +} +/* Map from Palette to BitField */ +static Uint8 *Map1toN(SDL_PixelFormat *src, SDL_PixelFormat *dst) +{ + Uint8 *map; + int i; + int bpp; + unsigned alpha; + SDL_Palette *pal = src->palette; + + bpp = ((dst->BytesPerPixel == 3) ? 4 : dst->BytesPerPixel); + map = (Uint8 *)SDL_malloc(pal->ncolors*bpp); + if ( map == NULL ) { + SDL_OutOfMemory(); + return(NULL); + } + + alpha = dst->Amask ? src->alpha : 0; + /* We memory copy to the pixel map so the endianness is preserved */ + for ( i=0; i<pal->ncolors; ++i ) { + ASSEMBLE_RGBA(&map[i*bpp], dst->BytesPerPixel, dst, + pal->colors[i].r, pal->colors[i].g, + pal->colors[i].b, alpha); + } + return(map); +} +/* Map from BitField to Dithered-Palette to Palette */ +static Uint8 *MapNto1(SDL_PixelFormat *src, SDL_PixelFormat *dst, int *identical) +{ + /* Generate a 256 color dither palette */ + SDL_Palette dithered; + SDL_Color colors[256]; + SDL_Palette *pal = dst->palette; + + /* SDL_DitherColors does not initialize the 'unused' component of colors, + but Map1to1 compares it against pal, so we should initialize it. */ + SDL_memset(colors, 0, sizeof(colors)); + + dithered.ncolors = 256; + SDL_DitherColors(colors, 8); + dithered.colors = colors; + return(Map1to1(&dithered, pal, identical)); +} + +SDL_BlitMap *SDL_AllocBlitMap(void) +{ + SDL_BlitMap *map; + + /* Allocate the empty map */ + map = (SDL_BlitMap *)SDL_malloc(sizeof(*map)); + if ( map == NULL ) { + SDL_OutOfMemory(); + return(NULL); + } + SDL_memset(map, 0, sizeof(*map)); + + /* Allocate the software blit data */ + map->sw_data = (struct private_swaccel *)SDL_malloc(sizeof(*map->sw_data)); + if ( map->sw_data == NULL ) { + SDL_FreeBlitMap(map); + SDL_OutOfMemory(); + return(NULL); + } + SDL_memset(map->sw_data, 0, sizeof(*map->sw_data)); + + /* It's ready to go */ + return(map); +} +void SDL_InvalidateMap(SDL_BlitMap *map) +{ + if ( ! map ) { + return; + } + map->dst = NULL; + map->format_version = (unsigned int)-1; + if ( map->table ) { + SDL_free(map->table); + map->table = NULL; + } +} +int SDL_MapSurface (SDL_Surface *src, SDL_Surface *dst) +{ + SDL_PixelFormat *srcfmt; + SDL_PixelFormat *dstfmt; + SDL_BlitMap *map; + + /* Clear out any previous mapping */ + map = src->map; + if ( (src->flags & SDL_RLEACCEL) == SDL_RLEACCEL ) { + SDL_UnRLESurface(src, 1); + } + SDL_InvalidateMap(map); + + /* Figure out what kind of mapping we're doing */ + map->identity = 0; + srcfmt = src->format; + dstfmt = dst->format; + switch (srcfmt->BytesPerPixel) { + case 1: + switch (dstfmt->BytesPerPixel) { + case 1: + /* Palette --> Palette */ + /* If both SDL_HWSURFACE, assume have same palette */ + if ( ((src->flags & SDL_HWSURFACE) == SDL_HWSURFACE) && + ((dst->flags & SDL_HWSURFACE) == SDL_HWSURFACE) ) { + map->identity = 1; + } else { + map->table = Map1to1(srcfmt->palette, + dstfmt->palette, &map->identity); + } + if ( ! map->identity ) { + if ( map->table == NULL ) { + return(-1); + } + } + if (srcfmt->BitsPerPixel!=dstfmt->BitsPerPixel) + map->identity = 0; + break; + + default: + /* Palette --> BitField */ + map->table = Map1toN(srcfmt, dstfmt); + if ( map->table == NULL ) { + return(-1); + } + break; + } + break; + default: + switch (dstfmt->BytesPerPixel) { + case 1: + /* BitField --> Palette */ + map->table = MapNto1(srcfmt, dstfmt, &map->identity); + if ( ! map->identity ) { + if ( map->table == NULL ) { + return(-1); + } + } + map->identity = 0; /* Don't optimize to copy */ + break; + default: + /* BitField --> BitField */ + if ( FORMAT_EQUAL(srcfmt, dstfmt) ) + map->identity = 1; + break; + } + break; + } + + map->dst = dst; + map->format_version = dst->format_version; + + /* Choose your blitters wisely */ + return(SDL_CalculateBlit(src)); +} +void SDL_FreeBlitMap(SDL_BlitMap *map) +{ + if ( map ) { + SDL_InvalidateMap(map); + if ( map->sw_data != NULL ) { + SDL_free(map->sw_data); + } + SDL_free(map); + } +} diff --git a/3rdparty/SDL/src/video/SDL_pixels_c.h b/3rdparty/SDL/src/video/SDL_pixels_c.h new file mode 100644 index 0000000..76759e2 --- /dev/null +++ b/3rdparty/SDL/src/video/SDL_pixels_c.h @@ -0,0 +1,46 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* Useful functions and variables from SDL_pixel.c */ + +#include "SDL_blit.h" + +/* Pixel format functions */ +extern SDL_PixelFormat *SDL_AllocFormat(int bpp, + Uint32 Rmask, Uint32 Gmask, Uint32 Bmask, Uint32 Amask); +extern SDL_PixelFormat *SDL_ReallocFormat(SDL_Surface *surface, int bpp, + Uint32 Rmask, Uint32 Gmask, Uint32 Bmask, Uint32 Amask); +extern void SDL_FormatChanged(SDL_Surface *surface); +extern void SDL_FreeFormat(SDL_PixelFormat *format); + +/* Blit mapping functions */ +extern SDL_BlitMap *SDL_AllocBlitMap(void); +extern void SDL_InvalidateMap(SDL_BlitMap *map); +extern int SDL_MapSurface (SDL_Surface *src, SDL_Surface *dst); +extern void SDL_FreeBlitMap(SDL_BlitMap *map); + +/* Miscellaneous functions */ +extern Uint16 SDL_CalculatePitch(SDL_Surface *surface); +extern void SDL_DitherColors(SDL_Color *colors, int bpp); +extern Uint8 SDL_FindColor(SDL_Palette *pal, Uint8 r, Uint8 g, Uint8 b); +extern void SDL_ApplyGamma(Uint16 *gamma, SDL_Color *colors, SDL_Color *output, int ncolors); diff --git a/3rdparty/SDL/src/video/SDL_stretch.c b/3rdparty/SDL/src/video/SDL_stretch.c new file mode 100644 index 0000000..7ce401f --- /dev/null +++ b/3rdparty/SDL/src/video/SDL_stretch.c @@ -0,0 +1,358 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* This a stretch blit implementation based on ideas given to me by + Tomasz Cejner - thanks! :) + + April 27, 2000 - Sam Lantinga +*/ + +#include "SDL_video.h" +#include "SDL_blit.h" + +/* This isn't ready for general consumption yet - it should be folded + into the general blitting mechanism. +*/ + +#if ((defined(_MFC_VER) && defined(_M_IX86)/* && !defined(_WIN32_WCE) still needed? */) || \ + defined(__WATCOMC__) || \ + (defined(__GNUC__) && defined(__i386__))) && SDL_ASSEMBLY_ROUTINES +/* There's a bug with gcc 4.4.1 and -O2 where srcp doesn't get the correct + * value after the first scanline. FIXME? */ +/*#define USE_ASM_STRETCH*/ +#endif + +#ifdef USE_ASM_STRETCH + +#ifdef HAVE_MPROTECT +#include <sys/types.h> +#include <sys/mman.h> +#endif +#ifdef __GNUC__ +#define PAGE_ALIGNED __attribute__((__aligned__(4096))) +#else +#define PAGE_ALIGNED +#endif + +#if defined(_M_IX86) || defined(i386) +#define PREFIX16 0x66 +#define STORE_BYTE 0xAA +#define STORE_WORD 0xAB +#define LOAD_BYTE 0xAC +#define LOAD_WORD 0xAD +#define RETURN 0xC3 +#else +#error Need assembly opcodes for this architecture +#endif + +static unsigned char copy_row[4096] PAGE_ALIGNED; + +static int generate_rowbytes(int src_w, int dst_w, int bpp) +{ + static struct { + int bpp; + int src_w; + int dst_w; + int status; + } last; + + int i; + int pos, inc; + unsigned char *eip, *fence; + unsigned char load, store; + + /* See if we need to regenerate the copy buffer */ + if ( (src_w == last.src_w) && + (dst_w == last.dst_w) && (bpp == last.bpp) ) { + return(last.status); + } + last.bpp = bpp; + last.src_w = src_w; + last.dst_w = dst_w; + last.status = -1; + + switch (bpp) { + case 1: + load = LOAD_BYTE; + store = STORE_BYTE; + break; + case 2: + case 4: + load = LOAD_WORD; + store = STORE_WORD; + break; + default: + SDL_SetError("ASM stretch of %d bytes isn't supported\n", bpp); + return(-1); + } +#ifdef HAVE_MPROTECT + /* Make the code writeable */ + if ( mprotect(copy_row, sizeof(copy_row), PROT_READ|PROT_WRITE) < 0 ) { + SDL_SetError("Couldn't make copy buffer writeable"); + return(-1); + } +#endif + pos = 0x10000; + inc = (src_w << 16) / dst_w; + eip = copy_row; + fence = copy_row+sizeof(copy_row)-2; + for ( i=0; i<dst_w && eip < end; ++i ) { + while ( pos >= 0x10000L ) { + if ( eip == fence ) { + return -1; + } + if ( bpp == 2 ) { + *eip++ = PREFIX16; + } + *eip++ = load; + pos -= 0x10000L; + } + if ( eip == fence ) { + return -1; + } + if ( bpp == 2 ) { + *eip++ = PREFIX16; + } + *eip++ = store; + pos += inc; + } + *eip++ = RETURN; + +#ifdef HAVE_MPROTECT + /* Make the code executable but not writeable */ + if ( mprotect(copy_row, sizeof(copy_row), PROT_READ|PROT_EXEC) < 0 ) { + SDL_SetError("Couldn't make copy buffer executable"); + return(-1); + } +#endif + last.status = 0; + return(0); +} + +#endif /* USE_ASM_STRETCH */ + +#define DEFINE_COPY_ROW(name, type) \ +void name(type *src, int src_w, type *dst, int dst_w) \ +{ \ + int i; \ + int pos, inc; \ + type pixel = 0; \ + \ + pos = 0x10000; \ + inc = (src_w << 16) / dst_w; \ + for ( i=dst_w; i>0; --i ) { \ + while ( pos >= 0x10000L ) { \ + pixel = *src++; \ + pos -= 0x10000L; \ + } \ + *dst++ = pixel; \ + pos += inc; \ + } \ +} +DEFINE_COPY_ROW(copy_row1, Uint8) +DEFINE_COPY_ROW(copy_row2, Uint16) +DEFINE_COPY_ROW(copy_row4, Uint32) + +/* The ASM code doesn't handle 24-bpp stretch blits */ +void copy_row3(Uint8 *src, int src_w, Uint8 *dst, int dst_w) +{ + int i; + int pos, inc; + Uint8 pixel[3] = { 0, 0, 0 }; + + pos = 0x10000; + inc = (src_w << 16) / dst_w; + for ( i=dst_w; i>0; --i ) { + while ( pos >= 0x10000L ) { + pixel[0] = *src++; + pixel[1] = *src++; + pixel[2] = *src++; + pos -= 0x10000L; + } + *dst++ = pixel[0]; + *dst++ = pixel[1]; + *dst++ = pixel[2]; + pos += inc; + } +} + +/* Perform a stretch blit between two surfaces of the same format. + NOTE: This function is not safe to call from multiple threads! +*/ +int SDL_SoftStretch(SDL_Surface *src, SDL_Rect *srcrect, + SDL_Surface *dst, SDL_Rect *dstrect) +{ + int src_locked; + int dst_locked; + int pos, inc; + int dst_maxrow; + int src_row, dst_row; + Uint8 *srcp = NULL; + Uint8 *dstp; + SDL_Rect full_src; + SDL_Rect full_dst; +#ifdef USE_ASM_STRETCH + SDL_bool use_asm = SDL_TRUE; +#ifdef __GNUC__ + int u1, u2; +#endif +#endif /* USE_ASM_STRETCH */ + const int bpp = dst->format->BytesPerPixel; + + if ( src->format->BitsPerPixel != dst->format->BitsPerPixel ) { + SDL_SetError("Only works with same format surfaces"); + return(-1); + } + + /* Verify the blit rectangles */ + if ( srcrect ) { + if ( (srcrect->x < 0) || (srcrect->y < 0) || + ((srcrect->x+srcrect->w) > src->w) || + ((srcrect->y+srcrect->h) > src->h) ) { + SDL_SetError("Invalid source blit rectangle"); + return(-1); + } + } else { + full_src.x = 0; + full_src.y = 0; + full_src.w = src->w; + full_src.h = src->h; + srcrect = &full_src; + } + if ( dstrect ) { + if ( (dstrect->x < 0) || (dstrect->y < 0) || + ((dstrect->x+dstrect->w) > dst->w) || + ((dstrect->y+dstrect->h) > dst->h) ) { + SDL_SetError("Invalid destination blit rectangle"); + return(-1); + } + } else { + full_dst.x = 0; + full_dst.y = 0; + full_dst.w = dst->w; + full_dst.h = dst->h; + dstrect = &full_dst; + } + + /* Lock the destination if it's in hardware */ + dst_locked = 0; + if ( SDL_MUSTLOCK(dst) ) { + if ( SDL_LockSurface(dst) < 0 ) { + SDL_SetError("Unable to lock destination surface"); + return(-1); + } + dst_locked = 1; + } + /* Lock the source if it's in hardware */ + src_locked = 0; + if ( SDL_MUSTLOCK(src) ) { + if ( SDL_LockSurface(src) < 0 ) { + if ( dst_locked ) { + SDL_UnlockSurface(dst); + } + SDL_SetError("Unable to lock source surface"); + return(-1); + } + src_locked = 1; + } + + /* Set up the data... */ + pos = 0x10000; + inc = (srcrect->h << 16) / dstrect->h; + src_row = srcrect->y; + dst_row = dstrect->y; + +#ifdef USE_ASM_STRETCH + /* Write the opcodes for this stretch */ + if ( (bpp == 3) || + (generate_rowbytes(srcrect->w, dstrect->w, bpp) < 0) ) { + use_asm = SDL_FALSE; + } +#endif + + /* Perform the stretch blit */ + for ( dst_maxrow = dst_row+dstrect->h; dst_row<dst_maxrow; ++dst_row ) { + dstp = (Uint8 *)dst->pixels + (dst_row*dst->pitch) + + (dstrect->x*bpp); + while ( pos >= 0x10000L ) { + srcp = (Uint8 *)src->pixels + (src_row*src->pitch) + + (srcrect->x*bpp); + ++src_row; + pos -= 0x10000L; + } +#ifdef USE_ASM_STRETCH + if (use_asm) { +#ifdef __GNUC__ + __asm__ __volatile__ ( + "call *%4" + : "=&D" (u1), "=&S" (u2) + : "0" (dstp), "1" (srcp), "r" (copy_row) + : "memory" ); +#elif defined(_MSC_VER) || defined(__WATCOMC__) + { void *code = copy_row; + __asm { + push edi + push esi + + mov edi, dstp + mov esi, srcp + call dword ptr code + + pop esi + pop edi + } + } +#else +#error Need inline assembly for this compiler +#endif + } else +#endif + switch (bpp) { + case 1: + copy_row1(srcp, srcrect->w, dstp, dstrect->w); + break; + case 2: + copy_row2((Uint16 *)srcp, srcrect->w, + (Uint16 *)dstp, dstrect->w); + break; + case 3: + copy_row3(srcp, srcrect->w, dstp, dstrect->w); + break; + case 4: + copy_row4((Uint32 *)srcp, srcrect->w, + (Uint32 *)dstp, dstrect->w); + break; + } + pos += inc; + } + + /* We need to unlock the surfaces if they're locked */ + if ( dst_locked ) { + SDL_UnlockSurface(dst); + } + if ( src_locked ) { + SDL_UnlockSurface(src); + } + return(0); +} + diff --git a/3rdparty/SDL/src/video/SDL_stretch_c.h b/3rdparty/SDL/src/video/SDL_stretch_c.h new file mode 100644 index 0000000..4cc6acb --- /dev/null +++ b/3rdparty/SDL/src/video/SDL_stretch_c.h @@ -0,0 +1,29 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* Perform a stretch blit between two surfaces of the same format. + NOTE: This function is not safe to call from multiple threads! +*/ +extern int SDL_SoftStretch(SDL_Surface *src, SDL_Rect *srcrect, + SDL_Surface *dst, SDL_Rect *dstrect); + diff --git a/3rdparty/SDL/src/video/SDL_surface.c b/3rdparty/SDL/src/video/SDL_surface.c new file mode 100644 index 0000000..0f3ad12 --- /dev/null +++ b/3rdparty/SDL/src/video/SDL_surface.c @@ -0,0 +1,941 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#include "SDL_video.h" +#include "SDL_sysvideo.h" +#include "SDL_cursor_c.h" +#include "SDL_blit.h" +#include "SDL_RLEaccel_c.h" +#include "SDL_pixels_c.h" +#include "SDL_leaks.h" + + +/* Public routines */ +/* + * Create an empty RGB surface of the appropriate depth + */ +SDL_Surface * SDL_CreateRGBSurface (Uint32 flags, + int width, int height, int depth, + Uint32 Rmask, Uint32 Gmask, Uint32 Bmask, Uint32 Amask) +{ + SDL_VideoDevice *video = current_video; + SDL_VideoDevice *this = current_video; + SDL_Surface *screen; + SDL_Surface *surface; + + /* Make sure the size requested doesn't overflow our datatypes */ + /* Next time I write a library like SDL, I'll use int for size. :) */ + if ( width >= 16384 || height >= 65536 ) { + SDL_SetError("Width or height is too large"); + return(NULL); + } + + /* Check to see if we desire the surface in video memory */ + if ( video ) { + screen = SDL_PublicSurface; + } else { + screen = NULL; + } + if ( screen && ((screen->flags&SDL_HWSURFACE) == SDL_HWSURFACE) ) { + if ( (flags&(SDL_SRCCOLORKEY|SDL_SRCALPHA)) != 0 ) { + flags |= SDL_HWSURFACE; + } + if ( (flags & SDL_SRCCOLORKEY) == SDL_SRCCOLORKEY ) { + if ( ! current_video->info.blit_hw_CC ) { + flags &= ~SDL_HWSURFACE; + } + } + if ( (flags & SDL_SRCALPHA) == SDL_SRCALPHA ) { + if ( ! current_video->info.blit_hw_A ) { + flags &= ~SDL_HWSURFACE; + } + } + } else { + flags &= ~SDL_HWSURFACE; + } + + /* Allocate the surface */ + surface = (SDL_Surface *)SDL_malloc(sizeof(*surface)); + if ( surface == NULL ) { + SDL_OutOfMemory(); + return(NULL); + } + surface->flags = SDL_SWSURFACE; + if ( (flags & SDL_HWSURFACE) == SDL_HWSURFACE ) { + if ((Amask) && (video->displayformatalphapixel)) + { + depth = video->displayformatalphapixel->BitsPerPixel; + Rmask = video->displayformatalphapixel->Rmask; + Gmask = video->displayformatalphapixel->Gmask; + Bmask = video->displayformatalphapixel->Bmask; + Amask = video->displayformatalphapixel->Amask; + } + else + { + depth = screen->format->BitsPerPixel; + Rmask = screen->format->Rmask; + Gmask = screen->format->Gmask; + Bmask = screen->format->Bmask; + Amask = screen->format->Amask; + } + } + surface->format = SDL_AllocFormat(depth, Rmask, Gmask, Bmask, Amask); + if ( surface->format == NULL ) { + SDL_free(surface); + return(NULL); + } + if ( Amask ) { + surface->flags |= SDL_SRCALPHA; + } + surface->w = width; + surface->h = height; + surface->pitch = SDL_CalculatePitch(surface); + surface->pixels = NULL; + surface->offset = 0; + surface->hwdata = NULL; + surface->locked = 0; + surface->map = NULL; + surface->unused1 = 0; + SDL_SetClipRect(surface, NULL); + SDL_FormatChanged(surface); + + /* Get the pixels */ + if ( ((flags&SDL_HWSURFACE) == SDL_SWSURFACE) || + (video->AllocHWSurface(this, surface) < 0) ) { + if ( surface->w && surface->h ) { + surface->pixels = SDL_malloc(surface->h*surface->pitch); + if ( surface->pixels == NULL ) { + SDL_FreeSurface(surface); + SDL_OutOfMemory(); + return(NULL); + } + /* This is important for bitmaps */ + SDL_memset(surface->pixels, 0, surface->h*surface->pitch); + } + } + + /* Allocate an empty mapping */ + surface->map = SDL_AllocBlitMap(); + if ( surface->map == NULL ) { + SDL_FreeSurface(surface); + return(NULL); + } + + /* The surface is ready to go */ + surface->refcount = 1; +#ifdef CHECK_LEAKS + ++surfaces_allocated; +#endif + return(surface); +} +/* + * Create an RGB surface from an existing memory buffer + */ +SDL_Surface * SDL_CreateRGBSurfaceFrom (void *pixels, + int width, int height, int depth, int pitch, + Uint32 Rmask, Uint32 Gmask, Uint32 Bmask, Uint32 Amask) +{ + SDL_Surface *surface; + + surface = SDL_CreateRGBSurface(SDL_SWSURFACE, 0, 0, depth, + Rmask, Gmask, Bmask, Amask); + if ( surface != NULL ) { + surface->flags |= SDL_PREALLOC; + surface->pixels = pixels; + surface->w = width; + surface->h = height; + surface->pitch = pitch; + SDL_SetClipRect(surface, NULL); + } + return(surface); +} +/* + * Set the color key in a blittable surface + */ +int SDL_SetColorKey (SDL_Surface *surface, Uint32 flag, Uint32 key) +{ + /* Sanity check the flag as it gets passed in */ + if ( flag & SDL_SRCCOLORKEY ) { + if ( flag & (SDL_RLEACCEL|SDL_RLEACCELOK) ) { + flag = (SDL_SRCCOLORKEY | SDL_RLEACCELOK); + } else { + flag = SDL_SRCCOLORKEY; + } + } else { + flag = 0; + } + + /* Optimize away operations that don't change anything */ + if ( (flag == (surface->flags & (SDL_SRCCOLORKEY|SDL_RLEACCELOK))) && + (key == surface->format->colorkey) ) { + return(0); + } + + /* UnRLE surfaces before we change the colorkey */ + if ( surface->flags & SDL_RLEACCEL ) { + SDL_UnRLESurface(surface, 1); + } + + if ( flag ) { + SDL_VideoDevice *video = current_video; + SDL_VideoDevice *this = current_video; + + + surface->flags |= SDL_SRCCOLORKEY; + surface->format->colorkey = key; + if ( (surface->flags & SDL_HWACCEL) == SDL_HWACCEL ) { + if ( (video->SetHWColorKey == NULL) || + (video->SetHWColorKey(this, surface, key) < 0) ) { + surface->flags &= ~SDL_HWACCEL; + } + } + if ( flag & SDL_RLEACCELOK ) { + surface->flags |= SDL_RLEACCELOK; + } else { + surface->flags &= ~SDL_RLEACCELOK; + } + } else { + surface->flags &= ~(SDL_SRCCOLORKEY|SDL_RLEACCELOK); + surface->format->colorkey = 0; + } + SDL_InvalidateMap(surface->map); + return(0); +} +/* This function sets the alpha channel of a surface */ +int SDL_SetAlpha (SDL_Surface *surface, Uint32 flag, Uint8 value) +{ + Uint32 oldflags = surface->flags; + Uint32 oldalpha = surface->format->alpha; + + /* Sanity check the flag as it gets passed in */ + if ( flag & SDL_SRCALPHA ) { + if ( flag & (SDL_RLEACCEL|SDL_RLEACCELOK) ) { + flag = (SDL_SRCALPHA | SDL_RLEACCELOK); + } else { + flag = SDL_SRCALPHA; + } + } else { + flag = 0; + } + + /* Optimize away operations that don't change anything */ + if ( (flag == (surface->flags & (SDL_SRCALPHA|SDL_RLEACCELOK))) && + (!flag || value == oldalpha) ) { + return(0); + } + + if(!(flag & SDL_RLEACCELOK) && (surface->flags & SDL_RLEACCEL)) + SDL_UnRLESurface(surface, 1); + + if ( flag ) { + SDL_VideoDevice *video = current_video; + SDL_VideoDevice *this = current_video; + + surface->flags |= SDL_SRCALPHA; + surface->format->alpha = value; + if ( (surface->flags & SDL_HWACCEL) == SDL_HWACCEL ) { + if ( (video->SetHWAlpha == NULL) || + (video->SetHWAlpha(this, surface, value) < 0) ) { + surface->flags &= ~SDL_HWACCEL; + } + } + if ( flag & SDL_RLEACCELOK ) { + surface->flags |= SDL_RLEACCELOK; + } else { + surface->flags &= ~SDL_RLEACCELOK; + } + } else { + surface->flags &= ~SDL_SRCALPHA; + surface->format->alpha = SDL_ALPHA_OPAQUE; + } + /* + * The representation for software surfaces is independent of + * per-surface alpha, so no need to invalidate the blit mapping + * if just the alpha value was changed. (If either is 255, we still + * need to invalidate.) + */ + if((surface->flags & SDL_HWACCEL) == SDL_HWACCEL + || oldflags != surface->flags + || (((oldalpha + 1) ^ (value + 1)) & 0x100)) + SDL_InvalidateMap(surface->map); + return(0); +} +int SDL_SetAlphaChannel(SDL_Surface *surface, Uint8 value) +{ + int row, col; + int offset; + Uint8 *buf; + + if ( (surface->format->Amask != 0xFF000000) && + (surface->format->Amask != 0x000000FF) ) { + SDL_SetError("Unsupported surface alpha mask format"); + return -1; + } + +#if SDL_BYTEORDER == SDL_LIL_ENDIAN + if ( surface->format->Amask == 0xFF000000 ) { + offset = 3; + } else { + offset = 0; + } +#else + if ( surface->format->Amask == 0xFF000000 ) { + offset = 0; + } else { + offset = 3; + } +#endif /* Byte ordering */ + + /* Quickly set the alpha channel of an RGBA or ARGB surface */ + if ( SDL_MUSTLOCK(surface) ) { + if ( SDL_LockSurface(surface) < 0 ) { + return -1; + } + } + row = surface->h; + while (row--) { + col = surface->w; + buf = (Uint8 *)surface->pixels + row * surface->pitch + offset; + while(col--) { + *buf = value; + buf += 4; + } + } + if ( SDL_MUSTLOCK(surface) ) { + SDL_UnlockSurface(surface); + } + return 0; +} + +/* + * A function to calculate the intersection of two rectangles: + * return true if the rectangles intersect, false otherwise + */ +static __inline__ +SDL_bool SDL_IntersectRect(const SDL_Rect *A, const SDL_Rect *B, SDL_Rect *intersection) +{ + int Amin, Amax, Bmin, Bmax; + + /* Horizontal intersection */ + Amin = A->x; + Amax = Amin + A->w; + Bmin = B->x; + Bmax = Bmin + B->w; + if(Bmin > Amin) + Amin = Bmin; + intersection->x = Amin; + if(Bmax < Amax) + Amax = Bmax; + intersection->w = Amax - Amin > 0 ? Amax - Amin : 0; + + /* Vertical intersection */ + Amin = A->y; + Amax = Amin + A->h; + Bmin = B->y; + Bmax = Bmin + B->h; + if(Bmin > Amin) + Amin = Bmin; + intersection->y = Amin; + if(Bmax < Amax) + Amax = Bmax; + intersection->h = Amax - Amin > 0 ? Amax - Amin : 0; + + return (intersection->w && intersection->h); +} +/* + * Set the clipping rectangle for a blittable surface + */ +SDL_bool SDL_SetClipRect(SDL_Surface *surface, const SDL_Rect *rect) +{ + SDL_Rect full_rect; + + /* Don't do anything if there's no surface to act on */ + if ( ! surface ) { + return SDL_FALSE; + } + + /* Set up the full surface rectangle */ + full_rect.x = 0; + full_rect.y = 0; + full_rect.w = surface->w; + full_rect.h = surface->h; + + /* Set the clipping rectangle */ + if ( ! rect ) { + surface->clip_rect = full_rect; + return 1; + } + return SDL_IntersectRect(rect, &full_rect, &surface->clip_rect); +} +void SDL_GetClipRect(SDL_Surface *surface, SDL_Rect *rect) +{ + if ( surface && rect ) { + *rect = surface->clip_rect; + } +} +/* + * Set up a blit between two surfaces -- split into three parts: + * The upper part, SDL_UpperBlit(), performs clipping and rectangle + * verification. The lower part is a pointer to a low level + * accelerated blitting function. + * + * These parts are separated out and each used internally by this + * library in the optimimum places. They are exported so that if + * you know exactly what you are doing, you can optimize your code + * by calling the one(s) you need. + */ +int SDL_LowerBlit (SDL_Surface *src, SDL_Rect *srcrect, + SDL_Surface *dst, SDL_Rect *dstrect) +{ + SDL_blit do_blit; + SDL_Rect hw_srcrect; + SDL_Rect hw_dstrect; + + /* Check to make sure the blit mapping is valid */ + if ( (src->map->dst != dst) || + (src->map->dst->format_version != src->map->format_version) ) { + if ( SDL_MapSurface(src, dst) < 0 ) { + return(-1); + } + } + + /* Figure out which blitter to use */ + if ( (src->flags & SDL_HWACCEL) == SDL_HWACCEL ) { + if ( src == SDL_VideoSurface ) { + hw_srcrect = *srcrect; + hw_srcrect.x += current_video->offset_x; + hw_srcrect.y += current_video->offset_y; + srcrect = &hw_srcrect; + } + if ( dst == SDL_VideoSurface ) { + hw_dstrect = *dstrect; + hw_dstrect.x += current_video->offset_x; + hw_dstrect.y += current_video->offset_y; + dstrect = &hw_dstrect; + } + do_blit = src->map->hw_blit; + } else { + do_blit = src->map->sw_blit; + } + return(do_blit(src, srcrect, dst, dstrect)); +} + + +int SDL_UpperBlit (SDL_Surface *src, SDL_Rect *srcrect, + SDL_Surface *dst, SDL_Rect *dstrect) +{ + SDL_Rect fulldst; + int srcx, srcy, w, h; + + /* Make sure the surfaces aren't locked */ + if ( ! src || ! dst ) { + SDL_SetError("SDL_UpperBlit: passed a NULL surface"); + return(-1); + } + if ( src->locked || dst->locked ) { + SDL_SetError("Surfaces must not be locked during blit"); + return(-1); + } + + /* If the destination rectangle is NULL, use the entire dest surface */ + if ( dstrect == NULL ) { + fulldst.x = fulldst.y = 0; + dstrect = &fulldst; + } + + /* clip the source rectangle to the source surface */ + if(srcrect) { + int maxw, maxh; + + srcx = srcrect->x; + w = srcrect->w; + if(srcx < 0) { + w += srcx; + dstrect->x -= srcx; + srcx = 0; + } + maxw = src->w - srcx; + if(maxw < w) + w = maxw; + + srcy = srcrect->y; + h = srcrect->h; + if(srcy < 0) { + h += srcy; + dstrect->y -= srcy; + srcy = 0; + } + maxh = src->h - srcy; + if(maxh < h) + h = maxh; + + } else { + srcx = srcy = 0; + w = src->w; + h = src->h; + } + + /* clip the destination rectangle against the clip rectangle */ + { + SDL_Rect *clip = &dst->clip_rect; + int dx, dy; + + dx = clip->x - dstrect->x; + if(dx > 0) { + w -= dx; + dstrect->x += dx; + srcx += dx; + } + dx = dstrect->x + w - clip->x - clip->w; + if(dx > 0) + w -= dx; + + dy = clip->y - dstrect->y; + if(dy > 0) { + h -= dy; + dstrect->y += dy; + srcy += dy; + } + dy = dstrect->y + h - clip->y - clip->h; + if(dy > 0) + h -= dy; + } + + if(w > 0 && h > 0) { + SDL_Rect sr; + sr.x = srcx; + sr.y = srcy; + sr.w = dstrect->w = w; + sr.h = dstrect->h = h; + return SDL_LowerBlit(src, &sr, dst, dstrect); + } + dstrect->w = dstrect->h = 0; + return 0; +} + +static int SDL_FillRect1(SDL_Surface *dst, SDL_Rect *dstrect, Uint32 color) +{ + /* FIXME: We have to worry about packing order.. *sigh* */ + SDL_SetError("1-bpp rect fill not yet implemented"); + return -1; +} + +static int SDL_FillRect4(SDL_Surface *dst, SDL_Rect *dstrect, Uint32 color) +{ + /* FIXME: We have to worry about packing order.. *sigh* */ + SDL_SetError("4-bpp rect fill not yet implemented"); + return -1; +} + +/* + * This function performs a fast fill of the given rectangle with 'color' + */ +int SDL_FillRect(SDL_Surface *dst, SDL_Rect *dstrect, Uint32 color) +{ + SDL_VideoDevice *video = current_video; + SDL_VideoDevice *this = current_video; + int x, y; + Uint8 *row; + + /* This function doesn't work on surfaces < 8 bpp */ + if ( dst->format->BitsPerPixel < 8 ) { + switch(dst->format->BitsPerPixel) { + case 1: + return SDL_FillRect1(dst, dstrect, color); + break; + case 4: + return SDL_FillRect4(dst, dstrect, color); + break; + default: + SDL_SetError("Fill rect on unsupported surface format"); + return(-1); + break; + } + } + + /* If 'dstrect' == NULL, then fill the whole surface */ + if ( dstrect ) { + /* Perform clipping */ + if ( !SDL_IntersectRect(dstrect, &dst->clip_rect, dstrect) ) { + return(0); + } + } else { + dstrect = &dst->clip_rect; + } + + /* Check for hardware acceleration */ + if ( ((dst->flags & SDL_HWSURFACE) == SDL_HWSURFACE) && + video->info.blit_fill ) { + SDL_Rect hw_rect; + if ( dst == SDL_VideoSurface ) { + hw_rect = *dstrect; + hw_rect.x += current_video->offset_x; + hw_rect.y += current_video->offset_y; + dstrect = &hw_rect; + } + return(video->FillHWRect(this, dst, dstrect, color)); + } + + /* Perform software fill */ + if ( SDL_LockSurface(dst) != 0 ) { + return(-1); + } + row = (Uint8 *)dst->pixels+dstrect->y*dst->pitch+ + dstrect->x*dst->format->BytesPerPixel; + if ( dst->format->palette || (color == 0) ) { + x = dstrect->w*dst->format->BytesPerPixel; + if ( !color && !((uintptr_t)row&3) && !(x&3) && !(dst->pitch&3) ) { + int n = x >> 2; + for ( y=dstrect->h; y; --y ) { + SDL_memset4(row, 0, n); + row += dst->pitch; + } + } else { +#ifdef __powerpc__ + /* + * SDL_memset() on PPC (both glibc and codewarrior) uses + * the dcbz (Data Cache Block Zero) instruction, which + * causes an alignment exception if the destination is + * uncachable, so only use it on software surfaces + */ + if((dst->flags & SDL_HWSURFACE) == SDL_HWSURFACE) { + if(dstrect->w >= 8) { + /* + * 64-bit stores are probably most + * efficient to uncached video memory + */ + double fill; + SDL_memset(&fill, color, (sizeof fill)); + for(y = dstrect->h; y; y--) { + Uint8 *d = row; + unsigned n = x; + unsigned nn; + Uint8 c = color; + double f = fill; + while((unsigned long)d + & (sizeof(double) - 1)) { + *d++ = c; + n--; + } + nn = n / (sizeof(double) * 4); + while(nn) { + ((double *)d)[0] = f; + ((double *)d)[1] = f; + ((double *)d)[2] = f; + ((double *)d)[3] = f; + d += 4*sizeof(double); + nn--; + } + n &= ~(sizeof(double) * 4 - 1); + nn = n / sizeof(double); + while(nn) { + *(double *)d = f; + d += sizeof(double); + nn--; + } + n &= ~(sizeof(double) - 1); + while(n) { + *d++ = c; + n--; + } + row += dst->pitch; + } + } else { + /* narrow boxes */ + for(y = dstrect->h; y; y--) { + Uint8 *d = row; + Uint8 c = color; + int n = x; + while(n) { + *d++ = c; + n--; + } + row += dst->pitch; + } + } + } else +#endif /* __powerpc__ */ + { + for(y = dstrect->h; y; y--) { + SDL_memset(row, color, x); + row += dst->pitch; + } + } + } + } else { + switch (dst->format->BytesPerPixel) { + case 2: + for ( y=dstrect->h; y; --y ) { + Uint16 *pixels = (Uint16 *)row; + Uint16 c = (Uint16)color; + Uint32 cc = (Uint32)c << 16 | c; + int n = dstrect->w; + if((uintptr_t)pixels & 3) { + *pixels++ = c; + n--; + } + if(n >> 1) + SDL_memset4(pixels, cc, n >> 1); + if(n & 1) + pixels[n - 1] = c; + row += dst->pitch; + } + break; + + case 3: + #if SDL_BYTEORDER == SDL_BIG_ENDIAN + color <<= 8; + #endif + for ( y=dstrect->h; y; --y ) { + Uint8 *pixels = row; + for ( x=dstrect->w; x; --x ) { + SDL_memcpy(pixels, &color, 3); + pixels += 3; + } + row += dst->pitch; + } + break; + + case 4: + for(y = dstrect->h; y; --y) { + SDL_memset4(row, color, dstrect->w); + row += dst->pitch; + } + break; + } + } + SDL_UnlockSurface(dst); + + /* We're done! */ + return(0); +} + +/* + * Lock a surface to directly access the pixels + */ +int SDL_LockSurface (SDL_Surface *surface) +{ + if ( ! surface->locked ) { + /* Perform the lock */ + if ( surface->flags & (SDL_HWSURFACE|SDL_ASYNCBLIT) ) { + SDL_VideoDevice *video = current_video; + SDL_VideoDevice *this = current_video; + if ( video->LockHWSurface(this, surface) < 0 ) { + return(-1); + } + } + if ( surface->flags & SDL_RLEACCEL ) { + SDL_UnRLESurface(surface, 1); + surface->flags |= SDL_RLEACCEL; /* save accel'd state */ + } + /* This needs to be done here in case pixels changes value */ + surface->pixels = (Uint8 *)surface->pixels + surface->offset; + } + + /* Increment the surface lock count, for recursive locks */ + ++surface->locked; + + /* Ready to go.. */ + return(0); +} +/* + * Unlock a previously locked surface + */ +void SDL_UnlockSurface (SDL_Surface *surface) +{ + /* Only perform an unlock if we are locked */ + if ( ! surface->locked || (--surface->locked > 0) ) { + return; + } + + /* Perform the unlock */ + surface->pixels = (Uint8 *)surface->pixels - surface->offset; + + /* Unlock hardware or accelerated surfaces */ + if ( surface->flags & (SDL_HWSURFACE|SDL_ASYNCBLIT) ) { + SDL_VideoDevice *video = current_video; + SDL_VideoDevice *this = current_video; + video->UnlockHWSurface(this, surface); + } else { + /* Update RLE encoded surface with new data */ + if ( (surface->flags & SDL_RLEACCEL) == SDL_RLEACCEL ) { + surface->flags &= ~SDL_RLEACCEL; /* stop lying */ + SDL_RLESurface(surface); + } + } +} + +/* + * Convert a surface into the specified pixel format. + */ +SDL_Surface * SDL_ConvertSurface (SDL_Surface *surface, + SDL_PixelFormat *format, Uint32 flags) +{ + SDL_Surface *convert; + Uint32 colorkey = 0; + Uint8 alpha = 0; + Uint32 surface_flags; + SDL_Rect bounds; + + /* Check for empty destination palette! (results in empty image) */ + if ( format->palette != NULL ) { + int i; + for ( i=0; i<format->palette->ncolors; ++i ) { + if ( (format->palette->colors[i].r != 0) || + (format->palette->colors[i].g != 0) || + (format->palette->colors[i].b != 0) ) + break; + } + if ( i == format->palette->ncolors ) { + SDL_SetError("Empty destination palette"); + return(NULL); + } + } + + /* Only create hw surfaces with alpha channel if hw alpha blits + are supported */ + if(format->Amask != 0 && (flags & SDL_HWSURFACE)) { + const SDL_VideoInfo *vi = SDL_GetVideoInfo(); + if(!vi || !vi->blit_hw_A) + flags &= ~SDL_HWSURFACE; + } + + /* Create a new surface with the desired format */ + convert = SDL_CreateRGBSurface(flags, + surface->w, surface->h, format->BitsPerPixel, + format->Rmask, format->Gmask, format->Bmask, format->Amask); + if ( convert == NULL ) { + return(NULL); + } + + /* Copy the palette if any */ + if ( format->palette && convert->format->palette ) { + SDL_memcpy(convert->format->palette->colors, + format->palette->colors, + format->palette->ncolors*sizeof(SDL_Color)); + convert->format->palette->ncolors = format->palette->ncolors; + } + + /* Save the original surface color key and alpha */ + surface_flags = surface->flags; + if ( (surface_flags & SDL_SRCCOLORKEY) == SDL_SRCCOLORKEY ) { + /* Convert colourkeyed surfaces to RGBA if requested */ + if((flags & SDL_SRCCOLORKEY) != SDL_SRCCOLORKEY + && format->Amask) { + surface_flags &= ~SDL_SRCCOLORKEY; + } else { + colorkey = surface->format->colorkey; + SDL_SetColorKey(surface, 0, 0); + } + } + if ( (surface_flags & SDL_SRCALPHA) == SDL_SRCALPHA ) { + /* Copy over the alpha channel to RGBA if requested */ + if ( format->Amask ) { + surface->flags &= ~SDL_SRCALPHA; + } else { + alpha = surface->format->alpha; + SDL_SetAlpha(surface, 0, 0); + } + } + + /* Copy over the image data */ + bounds.x = 0; + bounds.y = 0; + bounds.w = surface->w; + bounds.h = surface->h; + SDL_LowerBlit(surface, &bounds, convert, &bounds); + + /* Clean up the original surface, and update converted surface */ + if ( convert != NULL ) { + SDL_SetClipRect(convert, &surface->clip_rect); + } + if ( (surface_flags & SDL_SRCCOLORKEY) == SDL_SRCCOLORKEY ) { + Uint32 cflags = surface_flags&(SDL_SRCCOLORKEY|SDL_RLEACCELOK); + if ( convert != NULL ) { + Uint8 keyR, keyG, keyB; + + SDL_GetRGB(colorkey,surface->format,&keyR,&keyG,&keyB); + SDL_SetColorKey(convert, cflags|(flags&SDL_RLEACCELOK), + SDL_MapRGB(convert->format, keyR, keyG, keyB)); + } + SDL_SetColorKey(surface, cflags, colorkey); + } + if ( (surface_flags & SDL_SRCALPHA) == SDL_SRCALPHA ) { + Uint32 aflags = surface_flags&(SDL_SRCALPHA|SDL_RLEACCELOK); + if ( convert != NULL ) { + SDL_SetAlpha(convert, aflags|(flags&SDL_RLEACCELOK), + alpha); + } + if ( format->Amask ) { + surface->flags |= SDL_SRCALPHA; + } else { + SDL_SetAlpha(surface, aflags, alpha); + } + } + + /* We're ready to go! */ + return(convert); +} + +/* + * Free a surface created by the above function. + */ +void SDL_FreeSurface (SDL_Surface *surface) +{ + /* Free anything that's not NULL, and not the screen surface */ + if ((surface == NULL) || + (current_video && + ((surface == SDL_ShadowSurface)||(surface == SDL_VideoSurface)))) { + return; + } + if ( --surface->refcount > 0 ) { + return; + } + while ( surface->locked > 0 ) { + SDL_UnlockSurface(surface); + } + if ( (surface->flags & SDL_RLEACCEL) == SDL_RLEACCEL ) { + SDL_UnRLESurface(surface, 0); + } + if ( surface->format ) { + SDL_FreeFormat(surface->format); + surface->format = NULL; + } + if ( surface->map != NULL ) { + SDL_FreeBlitMap(surface->map); + surface->map = NULL; + } + if ( surface->hwdata ) { + SDL_VideoDevice *video = current_video; + SDL_VideoDevice *this = current_video; + video->FreeHWSurface(this, surface); + } + if ( surface->pixels && + ((surface->flags & SDL_PREALLOC) != SDL_PREALLOC) ) { + SDL_free(surface->pixels); + } + SDL_free(surface); +#ifdef CHECK_LEAKS + --surfaces_allocated; +#endif +} diff --git a/3rdparty/SDL/src/video/SDL_sysvideo.h b/3rdparty/SDL/src/video/SDL_sysvideo.h new file mode 100644 index 0000000..436450e --- /dev/null +++ b/3rdparty/SDL/src/video/SDL_sysvideo.h @@ -0,0 +1,424 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#ifndef _SDL_sysvideo_h +#define _SDL_sysvideo_h + +#include "SDL_mouse.h" +#define SDL_PROTOTYPES_ONLY +#include "SDL_syswm.h" +#undef SDL_PROTOTYPES_ONLY + +/* This file prototypes the video driver implementation. + This is designed to be easily converted to C++ in the future. + */ + +#if SDL_VIDEO_OPENGL +#include "SDL_opengl.h" +#endif /* SDL_VIDEO_OPENGL */ + +/* The SDL video driver */ +typedef struct SDL_VideoDevice SDL_VideoDevice; + +/* Define the SDL video driver structure */ +#define _THIS SDL_VideoDevice *_this +#ifndef _STATUS +#define _STATUS SDL_status *status +#endif +struct SDL_VideoDevice { + /* * * */ + /* The name of this video driver */ + const char *name; + + /* * * */ + /* Initialization/Query functions */ + + /* Initialize the native video subsystem, filling 'vformat' with the + "best" display pixel format, returning 0 or -1 if there's an error. + */ + int (*VideoInit)(_THIS, SDL_PixelFormat *vformat); + + /* List the available video modes for the given pixel format, sorted + from largest to smallest. + */ + SDL_Rect **(*ListModes)(_THIS, SDL_PixelFormat *format, Uint32 flags); + + /* Set the requested video mode, returning a surface which will be + set to the SDL_VideoSurface. The width and height will already + be verified by ListModes(), and the video subsystem is free to + set the mode to a supported bit depth different from the one + specified -- the desired bpp will be emulated with a shadow + surface if necessary. If a new mode is returned, this function + should take care of cleaning up the current mode. + */ + SDL_Surface *(*SetVideoMode)(_THIS, SDL_Surface *current, + int width, int height, int bpp, Uint32 flags); + + /* Toggle the fullscreen mode */ + int (*ToggleFullScreen)(_THIS, int on); + + /* This is called after the video mode has been set, to get the + initial mouse state. It should queue events as necessary to + properly represent the current mouse focus and position. + */ + void (*UpdateMouse)(_THIS); + + /* Create a YUV video surface (possibly overlay) of the given + format. The hardware should be able to perform at least 2x + scaling on display. + */ + SDL_Overlay *(*CreateYUVOverlay)(_THIS, int width, int height, + Uint32 format, SDL_Surface *display); + + /* Sets the color entries { firstcolor .. (firstcolor+ncolors-1) } + of the physical palette to those in 'colors'. If the device is + using a software palette (SDL_HWPALETTE not set), then the + changes are reflected in the logical palette of the screen + as well. + The return value is 1 if all entries could be set properly + or 0 otherwise. + */ + int (*SetColors)(_THIS, int firstcolor, int ncolors, + SDL_Color *colors); + + /* This pointer should exist in the native video subsystem and should + point to an appropriate update function for the current video mode + */ + void (*UpdateRects)(_THIS, int numrects, SDL_Rect *rects); + + /* Reverse the effects VideoInit() -- called if VideoInit() fails + or if the application is shutting down the video subsystem. + */ + void (*VideoQuit)(_THIS); + + /* * * */ + /* Hardware acceleration functions */ + + /* Information about the video hardware */ + SDL_VideoInfo info; + + /* The pixel format used when SDL_CreateRGBSurface creates SDL_HWSURFACEs with alpha */ + SDL_PixelFormat* displayformatalphapixel; + + /* Allocates a surface in video memory */ + int (*AllocHWSurface)(_THIS, SDL_Surface *surface); + + /* Sets the hardware accelerated blit function, if any, based + on the current flags of the surface (colorkey, alpha, etc.) + */ + int (*CheckHWBlit)(_THIS, SDL_Surface *src, SDL_Surface *dst); + + /* Fills a surface rectangle with the given color */ + int (*FillHWRect)(_THIS, SDL_Surface *dst, SDL_Rect *rect, Uint32 color); + + /* Sets video mem colorkey and accelerated blit function */ + int (*SetHWColorKey)(_THIS, SDL_Surface *surface, Uint32 key); + + /* Sets per surface hardware alpha value */ + int (*SetHWAlpha)(_THIS, SDL_Surface *surface, Uint8 value); + + /* Returns a readable/writable surface */ + int (*LockHWSurface)(_THIS, SDL_Surface *surface); + void (*UnlockHWSurface)(_THIS, SDL_Surface *surface); + + /* Performs hardware flipping */ + int (*FlipHWSurface)(_THIS, SDL_Surface *surface); + + /* Frees a previously allocated video surface */ + void (*FreeHWSurface)(_THIS, SDL_Surface *surface); + + /* * * */ + /* Gamma support */ + + Uint16 *gamma; + + /* Set the gamma correction directly (emulated with gamma ramps) */ + int (*SetGamma)(_THIS, float red, float green, float blue); + + /* Get the gamma correction directly (emulated with gamma ramps) */ + int (*GetGamma)(_THIS, float *red, float *green, float *blue); + + /* Set the gamma ramp */ + int (*SetGammaRamp)(_THIS, Uint16 *ramp); + + /* Get the gamma ramp */ + int (*GetGammaRamp)(_THIS, Uint16 *ramp); + + /* * * */ + /* OpenGL support */ + + /* Sets the dll to use for OpenGL and loads it */ + int (*GL_LoadLibrary)(_THIS, const char *path); + + /* Retrieves the address of a function in the gl library */ + void* (*GL_GetProcAddress)(_THIS, const char *proc); + + /* Get attribute information from the windowing system. */ + int (*GL_GetAttribute)(_THIS, SDL_GLattr attrib, int* value); + + /* Make the context associated with this driver current */ + int (*GL_MakeCurrent)(_THIS); + + /* Swap the current buffers in double buffer mode. */ + void (*GL_SwapBuffers)(_THIS); + + /* OpenGL functions for SDL_OPENGLBLIT */ +#if SDL_VIDEO_OPENGL +#if !defined(__WIN32__) +#define WINAPI +#endif +#define SDL_PROC(ret,func,params) ret (WINAPI *func) params; +#include "SDL_glfuncs.h" +#undef SDL_PROC + + /* Texture id */ + GLuint texture; +#endif + int is_32bit; + + /* * * */ + /* Window manager functions */ + + /* Set the title and icon text */ + void (*SetCaption)(_THIS, const char *title, const char *icon); + + /* Set the window icon image */ + void (*SetIcon)(_THIS, SDL_Surface *icon, Uint8 *mask); + + /* Iconify the window. + This function returns 1 if there is a window manager and the + window was actually iconified, it returns 0 otherwise. + */ + int (*IconifyWindow)(_THIS); + + /* Grab or ungrab keyboard and mouse input */ + SDL_GrabMode (*GrabInput)(_THIS, SDL_GrabMode mode); + + /* Get some platform dependent window information */ + int (*GetWMInfo)(_THIS, SDL_SysWMinfo *info); + + /* * * */ + /* Cursor manager functions */ + + /* Free a window manager cursor + This function can be NULL if CreateWMCursor is also NULL. + */ + void (*FreeWMCursor)(_THIS, WMcursor *cursor); + + /* If not NULL, create a black/white window manager cursor */ + WMcursor *(*CreateWMCursor)(_THIS, + Uint8 *data, Uint8 *mask, int w, int h, int hot_x, int hot_y); + + /* Show the specified cursor, or hide if cursor is NULL */ + int (*ShowWMCursor)(_THIS, WMcursor *cursor); + + /* Warp the window manager cursor to (x,y) + If NULL, a mouse motion event is posted internally. + */ + void (*WarpWMCursor)(_THIS, Uint16 x, Uint16 y); + + /* If not NULL, this is called when a mouse motion event occurs */ + void (*MoveWMCursor)(_THIS, int x, int y); + + /* Determine whether the mouse should be in relative mode or not. + This function is called when the input grab state or cursor + visibility state changes. + If the cursor is not visible, and the input is grabbed, the + driver can place the mouse in relative mode, which may result + in higher accuracy sampling of the pointer motion. + */ + void (*CheckMouseMode)(_THIS); + + /* * * */ + /* Event manager functions */ + + /* Initialize keyboard mapping for this driver */ + void (*InitOSKeymap)(_THIS); + + /* Handle any queued OS events */ + void (*PumpEvents)(_THIS); + + /* * * */ + /* Data common to all drivers */ + SDL_Surface *screen; + SDL_Surface *shadow; + SDL_Surface *visible; + SDL_Palette *physpal; /* physical palette, if != logical palette */ + SDL_Color *gammacols; /* gamma-corrected colours, or NULL */ + char *wm_title; + char *wm_icon; + int offset_x; + int offset_y; + SDL_GrabMode input_grab; + + /* Driver information flags */ + int handles_any_size; /* Driver handles any size video mode */ + + /* * * */ + /* Data used by the GL drivers */ + struct { + int red_size; + int green_size; + int blue_size; + int alpha_size; + int depth_size; + int buffer_size; + int stencil_size; + int double_buffer; + int accum_red_size; + int accum_green_size; + int accum_blue_size; + int accum_alpha_size; + int stereo; + int multisamplebuffers; + int multisamplesamples; + int accelerated; + int swap_control; + int driver_loaded; + char driver_path[256]; + void* dll_handle; + } gl_config; + + /* * * */ + /* Data private to this driver */ + struct SDL_PrivateVideoData *hidden; + struct SDL_PrivateGLData *gl_data; + + /* * * */ + /* The function used to dispose of this structure */ + void (*free)(_THIS); +}; +#undef _THIS + +typedef struct VideoBootStrap { + const char *name; + const char *desc; + int (*available)(void); + SDL_VideoDevice *(*create)(int devindex); +} VideoBootStrap; + +#if SDL_VIDEO_DRIVER_QUARTZ +extern VideoBootStrap QZ_bootstrap; +#endif +#if SDL_VIDEO_DRIVER_X11 +extern VideoBootStrap X11_bootstrap; +#endif +#if SDL_VIDEO_DRIVER_DGA +extern VideoBootStrap DGA_bootstrap; +#endif +#if SDL_VIDEO_DRIVER_NANOX +extern VideoBootStrap NX_bootstrap; +#endif +#if SDL_VIDEO_DRIVER_IPOD +extern VideoBootStrap iPod_bootstrap; +#endif +#if SDL_VIDEO_DRIVER_QTOPIA +extern VideoBootStrap Qtopia_bootstrap; +#endif +#if SDL_VIDEO_DRIVER_WSCONS +extern VideoBootStrap WSCONS_bootstrap; +#endif +#if SDL_VIDEO_DRIVER_FBCON +extern VideoBootStrap FBCON_bootstrap; +#endif +#if SDL_VIDEO_DRIVER_DIRECTFB +extern VideoBootStrap DirectFB_bootstrap; +#endif +#if SDL_VIDEO_DRIVER_PS2GS +extern VideoBootStrap PS2GS_bootstrap; +#endif +#if SDL_VIDEO_DRIVER_PS3 +extern VideoBootStrap PS3_bootstrap; +#endif +#if SDL_VIDEO_DRIVER_GGI +extern VideoBootStrap GGI_bootstrap; +#endif +#if SDL_VIDEO_DRIVER_VGL +extern VideoBootStrap VGL_bootstrap; +#endif +#if SDL_VIDEO_DRIVER_SVGALIB +extern VideoBootStrap SVGALIB_bootstrap; +#endif +#if SDL_VIDEO_DRIVER_GAPI +extern VideoBootStrap GAPI_bootstrap; +#endif +#if SDL_VIDEO_DRIVER_WINDIB +extern VideoBootStrap WINDIB_bootstrap; +#endif +#if SDL_VIDEO_DRIVER_DDRAW +extern VideoBootStrap DIRECTX_bootstrap; +#endif +#if SDL_VIDEO_DRIVER_BWINDOW +extern VideoBootStrap BWINDOW_bootstrap; +#endif +#if SDL_VIDEO_DRIVER_TOOLBOX +extern VideoBootStrap TOOLBOX_bootstrap; +#endif +#if SDL_VIDEO_DRIVER_DRAWSPROCKET +extern VideoBootStrap DSp_bootstrap; +#endif +#if SDL_VIDEO_DRIVER_PHOTON +extern VideoBootStrap ph_bootstrap; +#endif +#if SDL_VIDEO_DRIVER_EPOC +extern VideoBootStrap EPOC_bootstrap; +#endif +#if SDL_VIDEO_DRIVER_XBIOS +extern VideoBootStrap XBIOS_bootstrap; +#endif +#if SDL_VIDEO_DRIVER_GEM +extern VideoBootStrap GEM_bootstrap; +#endif +#if SDL_VIDEO_DRIVER_PICOGUI +extern VideoBootStrap PG_bootstrap; +#endif +#if SDL_VIDEO_DRIVER_DC +extern VideoBootStrap DC_bootstrap; +#endif +#if SDL_VIDEO_DRIVER_NDS +extern VideoBootStrap NDS_bootstrap; +#endif +#if SDL_VIDEO_DRIVER_RISCOS +extern VideoBootStrap RISCOS_bootstrap; +#endif +#if SDL_VIDEO_DRIVER_OS2FS +extern VideoBootStrap OS2FSLib_bootstrap; +#endif +#if SDL_VIDEO_DRIVER_AALIB +extern VideoBootStrap AALIB_bootstrap; +#endif +#if SDL_VIDEO_DRIVER_CACA +extern VideoBootStrap CACA_bootstrap; +#endif +#if SDL_VIDEO_DRIVER_DUMMY +extern VideoBootStrap DUMMY_bootstrap; +#endif + +/* This is the current video device */ +extern SDL_VideoDevice *current_video; + +#define SDL_VideoSurface (current_video->screen) +#define SDL_ShadowSurface (current_video->shadow) +#define SDL_PublicSurface (current_video->visible) + +#endif /* _SDL_sysvideo_h */ diff --git a/3rdparty/SDL/src/video/SDL_video.c b/3rdparty/SDL/src/video/SDL_video.c new file mode 100644 index 0000000..46285c9 --- /dev/null +++ b/3rdparty/SDL/src/video/SDL_video.c @@ -0,0 +1,1978 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* The high-level video driver subsystem */ + +#include "SDL.h" +#include "SDL_sysvideo.h" +#include "SDL_blit.h" +#include "SDL_pixels_c.h" +#include "SDL_cursor_c.h" +#include "../events/SDL_sysevents.h" +#include "../events/SDL_events_c.h" + +/* Available video drivers */ +static VideoBootStrap *bootstrap[] = { +#if SDL_VIDEO_DRIVER_QUARTZ + &QZ_bootstrap, +#endif +#if SDL_VIDEO_DRIVER_X11 + &X11_bootstrap, +#endif +#if SDL_VIDEO_DRIVER_DGA + &DGA_bootstrap, +#endif +#if SDL_VIDEO_DRIVER_NANOX + &NX_bootstrap, +#endif +#if SDL_VIDEO_DRIVER_IPOD + &iPod_bootstrap, +#endif +#if SDL_VIDEO_DRIVER_QTOPIA + &Qtopia_bootstrap, +#endif +#if SDL_VIDEO_DRIVER_WSCONS + &WSCONS_bootstrap, +#endif +#if SDL_VIDEO_DRIVER_FBCON + &FBCON_bootstrap, +#endif +#if SDL_VIDEO_DRIVER_DIRECTFB + &DirectFB_bootstrap, +#endif +#if SDL_VIDEO_DRIVER_PS2GS + &PS2GS_bootstrap, +#endif +#if SDL_VIDEO_DRIVER_PS3 + &PS3_bootstrap, +#endif +#if SDL_VIDEO_DRIVER_GGI + &GGI_bootstrap, +#endif +#if SDL_VIDEO_DRIVER_VGL + &VGL_bootstrap, +#endif +#if SDL_VIDEO_DRIVER_SVGALIB + &SVGALIB_bootstrap, +#endif +#if SDL_VIDEO_DRIVER_GAPI + &GAPI_bootstrap, +#endif +#if SDL_VIDEO_DRIVER_WINDIB + &WINDIB_bootstrap, +#endif +#if SDL_VIDEO_DRIVER_DDRAW + &DIRECTX_bootstrap, +#endif +#if SDL_VIDEO_DRIVER_BWINDOW + &BWINDOW_bootstrap, +#endif +#if SDL_VIDEO_DRIVER_TOOLBOX + &TOOLBOX_bootstrap, +#endif +#if SDL_VIDEO_DRIVER_DRAWSPROCKET + &DSp_bootstrap, +#endif +#if SDL_VIDEO_DRIVER_PHOTON + &ph_bootstrap, +#endif +#if SDL_VIDEO_DRIVER_EPOC + &EPOC_bootstrap, +#endif +#if SDL_VIDEO_DRIVER_XBIOS + &XBIOS_bootstrap, +#endif +#if SDL_VIDEO_DRIVER_GEM + &GEM_bootstrap, +#endif +#if SDL_VIDEO_DRIVER_PICOGUI + &PG_bootstrap, +#endif +#if SDL_VIDEO_DRIVER_DC + &DC_bootstrap, +#endif +#if SDL_VIDEO_DRIVER_NDS + &NDS_bootstrap, +#endif +#if SDL_VIDEO_DRIVER_RISCOS + &RISCOS_bootstrap, +#endif +#if SDL_VIDEO_DRIVER_OS2FS + &OS2FSLib_bootstrap, +#endif +#if SDL_VIDEO_DRIVER_AALIB + &AALIB_bootstrap, +#endif +#if SDL_VIDEO_DRIVER_CACA + &CACA_bootstrap, +#endif +#if SDL_VIDEO_DRIVER_DUMMY + &DUMMY_bootstrap, +#endif + NULL +}; + +SDL_VideoDevice *current_video = NULL; + +/* Various local functions */ +int SDL_VideoInit(const char *driver_name, Uint32 flags); +void SDL_VideoQuit(void); +void SDL_GL_UpdateRectsLock(SDL_VideoDevice* this, int numrects, SDL_Rect* rects); + +static SDL_GrabMode SDL_WM_GrabInputOff(void); +#if SDL_VIDEO_OPENGL +static int lock_count = 0; +#endif + + +/* + * Initialize the video and event subsystems -- determine native pixel format + */ +int SDL_VideoInit (const char *driver_name, Uint32 flags) +{ + SDL_VideoDevice *video; + int index; + int i; + SDL_PixelFormat vformat; + Uint32 video_flags; + + /* Toggle the event thread flags, based on OS requirements */ +#if defined(MUST_THREAD_EVENTS) + flags |= SDL_INIT_EVENTTHREAD; +#elif defined(CANT_THREAD_EVENTS) + if ( (flags & SDL_INIT_EVENTTHREAD) == SDL_INIT_EVENTTHREAD ) { + SDL_SetError("OS doesn't support threaded events"); + return(-1); + } +#endif + + /* Check to make sure we don't overwrite 'current_video' */ + if ( current_video != NULL ) { + SDL_VideoQuit(); + } + + /* Select the proper video driver */ + index = 0; + video = NULL; + if ( driver_name != NULL ) { +#if 0 /* This will be replaced with a better driver selection API */ + if ( SDL_strrchr(driver_name, ':') != NULL ) { + index = atoi(SDL_strrchr(driver_name, ':')+1); + } +#endif + for ( i=0; bootstrap[i]; ++i ) { + if ( SDL_strcasecmp(bootstrap[i]->name, driver_name) == 0) { + if ( bootstrap[i]->available() ) { + video = bootstrap[i]->create(index); + break; + } + } + } + } else { + for ( i=0; bootstrap[i]; ++i ) { + if ( bootstrap[i]->available() ) { + video = bootstrap[i]->create(index); + if ( video != NULL ) { + break; + } + } + } + } + if ( video == NULL ) { + SDL_SetError("No available video device"); + return(-1); + } + current_video = video; + current_video->name = bootstrap[i]->name; + + /* Do some basic variable initialization */ + video->screen = NULL; + video->shadow = NULL; + video->visible = NULL; + video->physpal = NULL; + video->gammacols = NULL; + video->gamma = NULL; + video->wm_title = NULL; + video->wm_icon = NULL; + video->offset_x = 0; + video->offset_y = 0; + SDL_memset(&video->info, 0, (sizeof video->info)); + + video->displayformatalphapixel = NULL; + + /* Set some very sane GL defaults */ + video->gl_config.driver_loaded = 0; + video->gl_config.dll_handle = NULL; + video->gl_config.red_size = 3; + video->gl_config.green_size = 3; + video->gl_config.blue_size = 2; + video->gl_config.alpha_size = 0; + video->gl_config.buffer_size = 0; + video->gl_config.depth_size = 16; + video->gl_config.stencil_size = 0; + video->gl_config.double_buffer = 1; + video->gl_config.accum_red_size = 0; + video->gl_config.accum_green_size = 0; + video->gl_config.accum_blue_size = 0; + video->gl_config.accum_alpha_size = 0; + video->gl_config.stereo = 0; + video->gl_config.multisamplebuffers = 0; + video->gl_config.multisamplesamples = 0; + video->gl_config.accelerated = -1; /* not known, don't set */ + video->gl_config.swap_control = -1; /* not known, don't set */ + + /* Initialize the video subsystem */ + SDL_memset(&vformat, 0, sizeof(vformat)); + if ( video->VideoInit(video, &vformat) < 0 ) { + SDL_VideoQuit(); + return(-1); + } + + /* Create a zero sized video surface of the appropriate format */ + video_flags = SDL_SWSURFACE; + SDL_VideoSurface = SDL_CreateRGBSurface(video_flags, 0, 0, + vformat.BitsPerPixel, + vformat.Rmask, vformat.Gmask, vformat.Bmask, 0); + if ( SDL_VideoSurface == NULL ) { + SDL_VideoQuit(); + return(-1); + } + SDL_PublicSurface = NULL; /* Until SDL_SetVideoMode() */ + +#if 0 /* Don't change the current palette - may be used by other programs. + * The application can't do anything with the display surface until + * a video mode has been set anyway. :) + */ + /* If we have a palettized surface, create a default palette */ + if ( SDL_VideoSurface->format->palette ) { + SDL_PixelFormat *vf = SDL_VideoSurface->format; + SDL_DitherColors(vf->palette->colors, vf->BitsPerPixel); + video->SetColors(video, + 0, vf->palette->ncolors, vf->palette->colors); + } +#endif + video->info.vfmt = SDL_VideoSurface->format; + + /* Start the event loop */ + if ( SDL_StartEventLoop(flags) < 0 ) { + SDL_VideoQuit(); + return(-1); + } + SDL_CursorInit(flags & SDL_INIT_EVENTTHREAD); + + /* We're ready to go! */ + return(0); +} + +char *SDL_VideoDriverName(char *namebuf, int maxlen) +{ + if ( current_video != NULL ) { + SDL_strlcpy(namebuf, current_video->name, maxlen); + return(namebuf); + } + return(NULL); +} + +/* + * Get the current display surface + */ +SDL_Surface *SDL_GetVideoSurface(void) +{ + SDL_Surface *visible; + + visible = NULL; + if ( current_video ) { + visible = current_video->visible; + } + return(visible); +} + +/* + * Get the current information about the video hardware + */ +const SDL_VideoInfo *SDL_GetVideoInfo(void) +{ + const SDL_VideoInfo *info; + + info = NULL; + if ( current_video ) { + info = ¤t_video->info; + } + return(info); +} + +/* + * Return a pointer to an array of available screen dimensions for the + * given format, sorted largest to smallest. Returns NULL if there are + * no dimensions available for a particular format, or (SDL_Rect **)-1 + * if any dimension is okay for the given format. If 'format' is NULL, + * the mode list will be for the format given by SDL_GetVideoInfo()->vfmt + */ +SDL_Rect ** SDL_ListModes (SDL_PixelFormat *format, Uint32 flags) +{ + SDL_VideoDevice *video = current_video; + SDL_VideoDevice *this = current_video; + SDL_Rect **modes; + + modes = NULL; + if ( SDL_VideoSurface ) { + if ( format == NULL ) { + format = SDL_VideoSurface->format; + } + modes = video->ListModes(this, format, flags); + } + return(modes); +} + +/* + * Check to see if a particular video mode is supported. + * It returns 0 if the requested mode is not supported under any bit depth, + * or returns the bits-per-pixel of the closest available mode with the + * given width and height. If this bits-per-pixel is different from the + * one used when setting the video mode, SDL_SetVideoMode() will succeed, + * but will emulate the requested bits-per-pixel with a shadow surface. + */ +static Uint8 SDL_closest_depths[4][8] = { + /* 8 bit closest depth ordering */ + { 0, 8, 16, 15, 32, 24, 0, 0 }, + /* 15,16 bit closest depth ordering */ + { 0, 16, 15, 32, 24, 8, 0, 0 }, + /* 24 bit closest depth ordering */ + { 0, 24, 32, 16, 15, 8, 0, 0 }, + /* 32 bit closest depth ordering */ + { 0, 32, 16, 15, 24, 8, 0, 0 } +}; + + +#ifdef __MACOS__ /* MPW optimization bug? */ +#define NEGATIVE_ONE 0xFFFFFFFF +#else +#define NEGATIVE_ONE -1 +#endif + +int SDL_VideoModeOK (int width, int height, int bpp, Uint32 flags) +{ + int table, b, i; + int supported; + SDL_PixelFormat format; + SDL_Rect **sizes; + + /* Currently 1 and 4 bpp are not supported */ + if ( bpp < 8 || bpp > 32 ) { + return(0); + } + if ( (width <= 0) || (height <= 0) ) { + return(0); + } + + /* Search through the list valid of modes */ + SDL_memset(&format, 0, sizeof(format)); + supported = 0; + table = ((bpp+7)/8)-1; + SDL_closest_depths[table][0] = bpp; + SDL_closest_depths[table][7] = 0; + for ( b = 0; !supported && SDL_closest_depths[table][b]; ++b ) { + format.BitsPerPixel = SDL_closest_depths[table][b]; + sizes = SDL_ListModes(&format, flags); + if ( sizes == (SDL_Rect **)0 ) { + /* No sizes supported at this bit-depth */ + continue; + } else + if (sizes == (SDL_Rect **)NEGATIVE_ONE) { + /* Any size supported at this bit-depth */ + supported = 1; + continue; + } else if (current_video->handles_any_size) { + /* Driver can center a smaller surface to simulate fullscreen */ + for ( i=0; sizes[i]; ++i ) { + if ((sizes[i]->w >= width) && (sizes[i]->h >= height)) { + supported = 1; /* this mode can fit the centered window. */ + break; + } + } + } else + for ( i=0; sizes[i]; ++i ) { + if ((sizes[i]->w == width) && (sizes[i]->h == height)) { + supported = 1; + break; + } + } + } + if ( supported ) { + --b; + return(SDL_closest_depths[table][b]); + } else { + return(0); + } +} + +/* + * Get the closest non-emulated video mode to the one requested + */ +static int SDL_GetVideoMode (int *w, int *h, int *BitsPerPixel, Uint32 flags) +{ + int table, b, i; + int supported; + int native_bpp; + SDL_PixelFormat format; + SDL_Rect **sizes; + + /* Check parameters */ + if ( *BitsPerPixel < 8 || *BitsPerPixel > 32 ) { + SDL_SetError("Invalid bits per pixel (range is {8...32})"); + return(0); + } + if ((*w <= 0) || (*h <= 0)) { + SDL_SetError("Invalid width or height"); + return(0); + } + + /* Try the original video mode, get the closest depth */ + native_bpp = SDL_VideoModeOK(*w, *h, *BitsPerPixel, flags); + if ( native_bpp == *BitsPerPixel ) { + return(1); + } + if ( native_bpp > 0 ) { + *BitsPerPixel = native_bpp; + return(1); + } + + /* No exact size match at any depth, look for closest match */ + SDL_memset(&format, 0, sizeof(format)); + supported = 0; + table = ((*BitsPerPixel+7)/8)-1; + SDL_closest_depths[table][0] = *BitsPerPixel; + SDL_closest_depths[table][7] = SDL_VideoSurface->format->BitsPerPixel; + for ( b = 0; !supported && SDL_closest_depths[table][b]; ++b ) { + int best; + + format.BitsPerPixel = SDL_closest_depths[table][b]; + sizes = SDL_ListModes(&format, flags); + if ( sizes == (SDL_Rect **)0 ) { + /* No sizes supported at this bit-depth */ + continue; + } + best=0; + for ( i=0; sizes[i]; ++i ) { + /* Mode with both dimensions bigger or equal than asked ? */ + if ((sizes[i]->w >= *w) && (sizes[i]->h >= *h)) { + /* Mode with any dimension smaller or equal than current best ? */ + if ((sizes[i]->w <= sizes[best]->w) || (sizes[i]->h <= sizes[best]->h)) { + /* Now choose the mode that has less pixels */ + if ((sizes[i]->w * sizes[i]->h) <= (sizes[best]->w * sizes[best]->h)) { + best=i; + supported = 1; + } + } + } + } + if (supported) { + *w=sizes[best]->w; + *h=sizes[best]->h; + *BitsPerPixel = SDL_closest_depths[table][b]; + } + } + if ( ! supported ) { + SDL_SetError("No video mode large enough for %dx%d", *w, *h); + } + return(supported); +} + +/* This should probably go somewhere else -- like SDL_surface.c */ +static void SDL_ClearSurface(SDL_Surface *surface) +{ + Uint32 black; + + black = SDL_MapRGB(surface->format, 0, 0, 0); + SDL_FillRect(surface, NULL, black); + if ((surface->flags&SDL_HWSURFACE) && (surface->flags&SDL_DOUBLEBUF)) { + SDL_Flip(surface); + SDL_FillRect(surface, NULL, black); + } + if (surface->flags&SDL_FULLSCREEN) { + SDL_Flip(surface); + } +} + +/* + * Create a shadow surface suitable for fooling the app. :-) + */ +static void SDL_CreateShadowSurface(int depth) +{ + Uint32 Rmask, Gmask, Bmask; + + /* Allocate the shadow surface */ + if ( depth == (SDL_VideoSurface->format)->BitsPerPixel ) { + Rmask = (SDL_VideoSurface->format)->Rmask; + Gmask = (SDL_VideoSurface->format)->Gmask; + Bmask = (SDL_VideoSurface->format)->Bmask; + } else { + Rmask = Gmask = Bmask = 0; + } + SDL_ShadowSurface = SDL_CreateRGBSurface(SDL_SWSURFACE, + SDL_VideoSurface->w, SDL_VideoSurface->h, + depth, Rmask, Gmask, Bmask, 0); + if ( SDL_ShadowSurface == NULL ) { + return; + } + + /* 8-bit shadow surfaces report that they have exclusive palette */ + if ( SDL_ShadowSurface->format->palette ) { + SDL_ShadowSurface->flags |= SDL_HWPALETTE; + if ( depth == (SDL_VideoSurface->format)->BitsPerPixel ) { + SDL_memcpy(SDL_ShadowSurface->format->palette->colors, + SDL_VideoSurface->format->palette->colors, + SDL_VideoSurface->format->palette->ncolors* + sizeof(SDL_Color)); + } else { + SDL_DitherColors( + SDL_ShadowSurface->format->palette->colors, depth); + } + } + + /* If the video surface is resizable, the shadow should say so */ + if ( (SDL_VideoSurface->flags & SDL_RESIZABLE) == SDL_RESIZABLE ) { + SDL_ShadowSurface->flags |= SDL_RESIZABLE; + } + /* If the video surface has no frame, the shadow should say so */ + if ( (SDL_VideoSurface->flags & SDL_NOFRAME) == SDL_NOFRAME ) { + SDL_ShadowSurface->flags |= SDL_NOFRAME; + } + /* If the video surface is fullscreen, the shadow should say so */ + if ( (SDL_VideoSurface->flags & SDL_FULLSCREEN) == SDL_FULLSCREEN ) { + SDL_ShadowSurface->flags |= SDL_FULLSCREEN; + } + /* If the video surface is flippable, the shadow should say so */ + if ( (SDL_VideoSurface->flags & SDL_DOUBLEBUF) == SDL_DOUBLEBUF ) { + SDL_ShadowSurface->flags |= SDL_DOUBLEBUF; + } + return; +} + +#ifdef __QNXNTO__ + #include <sys/neutrino.h> +#endif /* __QNXNTO__ */ + +#ifdef WIN32 + extern int sysevents_mouse_pressed; +#endif + +/* + * Set the requested video mode, allocating a shadow buffer if necessary. + */ +SDL_Surface * SDL_SetVideoMode (int width, int height, int bpp, Uint32 flags) +{ + SDL_VideoDevice *video, *this; + SDL_Surface *prev_mode, *mode; + int video_w; + int video_h; + int video_bpp; + int is_opengl; + SDL_GrabMode saved_grab; + + #ifdef WIN32 + sysevents_mouse_pressed = 0; + #endif + + /* Start up the video driver, if necessary.. + WARNING: This is the only function protected this way! + */ + if ( ! current_video ) { + if ( SDL_Init(SDL_INIT_VIDEO|SDL_INIT_NOPARACHUTE) < 0 ) { + return(NULL); + } + } + this = video = current_video; + + /* Default to the current width and height */ + if ( width == 0 ) { + width = video->info.current_w; + } + if ( height == 0 ) { + height = video->info.current_h; + } + /* Default to the current video bpp */ + if ( bpp == 0 ) { + flags |= SDL_ANYFORMAT; + bpp = SDL_VideoSurface->format->BitsPerPixel; + } + + /* Get a good video mode, the closest one possible */ + video_w = width; + video_h = height; + video_bpp = bpp; + if ( ! SDL_GetVideoMode(&video_w, &video_h, &video_bpp, flags) ) { + return(NULL); + } + + /* Check the requested flags */ + /* There's no palette in > 8 bits-per-pixel mode */ + if ( video_bpp > 8 ) { + flags &= ~SDL_HWPALETTE; + } +#if 0 + if ( (flags&SDL_FULLSCREEN) != SDL_FULLSCREEN ) { + /* There's no windowed double-buffering */ + flags &= ~SDL_DOUBLEBUF; + } +#endif + if ( (flags&SDL_DOUBLEBUF) == SDL_DOUBLEBUF ) { + /* Use hardware surfaces when double-buffering */ + flags |= SDL_HWSURFACE; + } + + is_opengl = ( ( flags & SDL_OPENGL ) == SDL_OPENGL ); + if ( is_opengl ) { + /* These flags are for 2D video modes only */ + flags &= ~(SDL_HWSURFACE|SDL_DOUBLEBUF); + } + + /* Reset the keyboard here so event callbacks can run */ + SDL_ResetKeyboard(); + SDL_ResetMouse(); + SDL_SetMouseRange(width, height); + SDL_cursorstate &= ~CURSOR_USINGSW; + + /* Clean up any previous video mode */ + if ( SDL_PublicSurface != NULL ) { + SDL_PublicSurface = NULL; + } + if ( SDL_ShadowSurface != NULL ) { + SDL_Surface *ready_to_go; + ready_to_go = SDL_ShadowSurface; + SDL_ShadowSurface = NULL; + SDL_FreeSurface(ready_to_go); + } + if ( video->physpal ) { + SDL_free(video->physpal->colors); + SDL_free(video->physpal); + video->physpal = NULL; + } + if( video->gammacols) { + SDL_free(video->gammacols); + video->gammacols = NULL; + } + + /* Save the previous grab state and turn off grab for mode switch */ + saved_grab = SDL_WM_GrabInputOff(); + + /* Try to set the video mode, along with offset and clipping */ + prev_mode = SDL_VideoSurface; + SDL_LockCursor(); + SDL_VideoSurface = NULL; /* In case it's freed by driver */ + mode = video->SetVideoMode(this, prev_mode,video_w,video_h,video_bpp,flags); + if ( mode ) { /* Prevent resize events from mode change */ + /* But not on OS/2 */ +#ifndef __OS2__ + SDL_PrivateResize(mode->w, mode->h); +#endif + + /* Sam - If we asked for OpenGL mode, and didn't get it, fail */ + if ( is_opengl && !(mode->flags & SDL_OPENGL) ) { + mode = NULL; + SDL_SetError("OpenGL not available"); + } + } + /* + * rcg11292000 + * If you try to set an SDL_OPENGL surface, and fail to find a + * matching visual, then the next call to SDL_SetVideoMode() + * will segfault, since we no longer point to a dummy surface, + * but rather NULL. + * Sam 11/29/00 + * WARNING, we need to make sure that the previous mode hasn't + * already been freed by the video driver. What do we do in + * that case? Should we call SDL_VideoInit() again? + */ + SDL_VideoSurface = (mode != NULL) ? mode : prev_mode; + + if ( (mode != NULL) && (!is_opengl) ) { + /* Sanity check */ + if ( (mode->w < width) || (mode->h < height) ) { + SDL_SetError("Video mode smaller than requested"); + return(NULL); + } + + /* If we have a palettized surface, create a default palette */ + if ( mode->format->palette ) { + SDL_PixelFormat *vf = mode->format; + SDL_DitherColors(vf->palette->colors, vf->BitsPerPixel); + video->SetColors(this, 0, vf->palette->ncolors, + vf->palette->colors); + } + + /* Clear the surface to black */ + video->offset_x = 0; + video->offset_y = 0; + mode->offset = 0; + SDL_SetClipRect(mode, NULL); + SDL_ClearSurface(mode); + + /* Now adjust the offsets to match the desired mode */ + video->offset_x = (mode->w-width)/2; + video->offset_y = (mode->h-height)/2; + mode->offset = video->offset_y*mode->pitch + + video->offset_x*mode->format->BytesPerPixel; +#ifdef DEBUG_VIDEO + fprintf(stderr, + "Requested mode: %dx%dx%d, obtained mode %dx%dx%d (offset %d)\n", + width, height, bpp, + mode->w, mode->h, mode->format->BitsPerPixel, mode->offset); +#endif + mode->w = width; + mode->h = height; + SDL_SetClipRect(mode, NULL); + } + SDL_ResetCursor(); + SDL_UnlockCursor(); + + /* If we failed setting a video mode, return NULL... (Uh Oh!) */ + if ( mode == NULL ) { + return(NULL); + } + + /* If there is no window manager, set the SDL_NOFRAME flag */ + if ( ! video->info.wm_available ) { + mode->flags |= SDL_NOFRAME; + } + + /* Reset the mouse cursor and grab for new video mode */ + SDL_SetCursor(NULL); + if ( video->UpdateMouse ) { + video->UpdateMouse(this); + } + SDL_WM_GrabInput(saved_grab); + SDL_GetRelativeMouseState(NULL, NULL); /* Clear first large delta */ + +#if SDL_VIDEO_OPENGL + /* Load GL symbols (before MakeCurrent, where we need glGetString). */ + if ( flags & (SDL_OPENGL | SDL_OPENGLBLIT) ) { + +#if defined(__QNXNTO__) && (_NTO_VERSION < 630) +#define __SDL_NOGETPROCADDR__ +#elif defined(__MINT__) +#define __SDL_NOGETPROCADDR__ +#endif +#ifdef __SDL_NOGETPROCADDR__ + #define SDL_PROC(ret,func,params) video->func=func; +#else + #define SDL_PROC(ret,func,params) \ + do { \ + video->func = SDL_GL_GetProcAddress(#func); \ + if ( ! video->func ) { \ + SDL_SetError("Couldn't load GL function %s: %s\n", #func, SDL_GetError()); \ + return(NULL); \ + } \ + } while ( 0 ); + +#endif /* __SDL_NOGETPROCADDR__ */ + +#include "SDL_glfuncs.h" +#undef SDL_PROC + } +#endif /* SDL_VIDEO_OPENGL */ + + /* If we're running OpenGL, make the context current */ + if ( (video->screen->flags & SDL_OPENGL) && + video->GL_MakeCurrent ) { + if ( video->GL_MakeCurrent(this) < 0 ) { + return(NULL); + } + } + + /* Set up a fake SDL surface for OpenGL "blitting" */ + if ( (flags & SDL_OPENGLBLIT) == SDL_OPENGLBLIT ) { + /* Load GL functions for performing the texture updates */ +#if SDL_VIDEO_OPENGL + + /* Create a software surface for blitting */ +#ifdef GL_VERSION_1_2 + /* If the implementation either supports the packed pixels + extension, or implements the core OpenGL 1.2 API, it will + support the GL_UNSIGNED_SHORT_5_6_5 texture format. + */ + if ( (bpp == 16) && + (SDL_strstr((const char *)video->glGetString(GL_EXTENSIONS), "GL_EXT_packed_pixels") || + (SDL_atof((const char *)video->glGetString(GL_VERSION)) >= 1.2f)) + ) { + video->is_32bit = 0; + SDL_VideoSurface = SDL_CreateRGBSurface( + flags, + width, + height, + 16, + 31 << 11, + 63 << 5, + 31, + 0 + ); + } + else +#endif /* OpenGL 1.2 */ + { + video->is_32bit = 1; + SDL_VideoSurface = SDL_CreateRGBSurface( + flags, + width, + height, + 32, +#if SDL_BYTEORDER == SDL_LIL_ENDIAN + 0x000000FF, + 0x0000FF00, + 0x00FF0000, + 0xFF000000 +#else + 0xFF000000, + 0x00FF0000, + 0x0000FF00, + 0x000000FF +#endif + ); + } + if ( ! SDL_VideoSurface ) { + return(NULL); + } + SDL_VideoSurface->flags = mode->flags | SDL_OPENGLBLIT; + + /* Free the original video mode surface (is this safe?) */ + SDL_FreeSurface(mode); + + /* Set the surface completely opaque & white by default */ + SDL_memset( SDL_VideoSurface->pixels, 255, SDL_VideoSurface->h * SDL_VideoSurface->pitch ); + video->glGenTextures( 1, &video->texture ); + video->glBindTexture( GL_TEXTURE_2D, video->texture ); + video->glTexImage2D( + GL_TEXTURE_2D, + 0, + video->is_32bit ? GL_RGBA : GL_RGB, + 256, + 256, + 0, + video->is_32bit ? GL_RGBA : GL_RGB, +#ifdef GL_VERSION_1_2 + video->is_32bit ? GL_UNSIGNED_BYTE : GL_UNSIGNED_SHORT_5_6_5, +#else + GL_UNSIGNED_BYTE, +#endif + NULL); + + video->UpdateRects = SDL_GL_UpdateRectsLock; +#else + SDL_SetError("Somebody forgot to #define SDL_VIDEO_OPENGL"); + return(NULL); +#endif + } + + /* Create a shadow surface if necessary */ + /* There are three conditions under which we create a shadow surface: + 1. We need a particular bits-per-pixel that we didn't get. + 2. We need a hardware palette and didn't get one. + 3. We need a software surface and got a hardware surface. + */ + if ( !(SDL_VideoSurface->flags & SDL_OPENGL) && + ( + ( !(flags&SDL_ANYFORMAT) && + (SDL_VideoSurface->format->BitsPerPixel != bpp)) || + ( (flags&SDL_HWPALETTE) && + !(SDL_VideoSurface->flags&SDL_HWPALETTE)) || + /* If the surface is in hardware, video writes are visible + as soon as they are performed, so we need to buffer them + */ + ( ((flags&SDL_HWSURFACE) == SDL_SWSURFACE) && + (SDL_VideoSurface->flags&SDL_HWSURFACE)) || + ( (flags&SDL_DOUBLEBUF) && + (SDL_VideoSurface->flags&SDL_HWSURFACE) && + !(SDL_VideoSurface->flags&SDL_DOUBLEBUF)) + ) ) { + SDL_CreateShadowSurface(bpp); + if ( SDL_ShadowSurface == NULL ) { + SDL_SetError("Couldn't create shadow surface"); + return(NULL); + } + SDL_PublicSurface = SDL_ShadowSurface; + } else { + SDL_PublicSurface = SDL_VideoSurface; + } + video->info.vfmt = SDL_VideoSurface->format; + video->info.current_w = SDL_VideoSurface->w; + video->info.current_h = SDL_VideoSurface->h; + + /* We're done! */ + return(SDL_PublicSurface); +} + +/* + * Convert a surface into the video pixel format. + */ +SDL_Surface * SDL_DisplayFormat (SDL_Surface *surface) +{ + Uint32 flags; + + if ( ! SDL_PublicSurface ) { + SDL_SetError("No video mode has been set"); + return(NULL); + } + /* Set the flags appropriate for copying to display surface */ + if (((SDL_PublicSurface->flags&SDL_HWSURFACE) == SDL_HWSURFACE) && current_video->info.blit_hw) + flags = SDL_HWSURFACE; + else + flags = SDL_SWSURFACE; +#ifdef AUTORLE_DISPLAYFORMAT + flags |= (surface->flags & (SDL_SRCCOLORKEY|SDL_SRCALPHA)); + flags |= SDL_RLEACCELOK; +#else + flags |= surface->flags & (SDL_SRCCOLORKEY|SDL_SRCALPHA|SDL_RLEACCELOK); +#endif + return(SDL_ConvertSurface(surface, SDL_PublicSurface->format, flags)); +} + +/* + * Convert a surface into a format that's suitable for blitting to + * the screen, but including an alpha channel. + */ +SDL_Surface *SDL_DisplayFormatAlpha(SDL_Surface *surface) +{ + SDL_PixelFormat *vf; + SDL_PixelFormat *format; + SDL_Surface *converted; + Uint32 flags; + /* default to ARGB8888 */ + Uint32 amask = 0xff000000; + Uint32 rmask = 0x00ff0000; + Uint32 gmask = 0x0000ff00; + Uint32 bmask = 0x000000ff; + + if ( ! SDL_PublicSurface ) { + SDL_SetError("No video mode has been set"); + return(NULL); + } + vf = SDL_PublicSurface->format; + + switch(vf->BytesPerPixel) { + case 2: + /* For XGY5[56]5, use, AXGY8888, where {X, Y} = {R, B}. + For anything else (like ARGB4444) it doesn't matter + since we have no special code for it anyway */ + if ( (vf->Rmask == 0x1f) && + (vf->Bmask == 0xf800 || vf->Bmask == 0x7c00)) { + rmask = 0xff; + bmask = 0xff0000; + } + break; + + case 3: + case 4: + /* Keep the video format, as long as the high 8 bits are + unused or alpha */ + if ( (vf->Rmask == 0xff) && (vf->Bmask == 0xff0000) ) { + rmask = 0xff; + bmask = 0xff0000; + } else if ( vf->Rmask == 0xFF00 && (vf->Bmask == 0xFF000000) ) { + amask = 0x000000FF; + rmask = 0x0000FF00; + gmask = 0x00FF0000; + bmask = 0xFF000000; + } + break; + + default: + /* We have no other optimised formats right now. When/if a new + optimised alpha format is written, add the converter here */ + break; + } + format = SDL_AllocFormat(32, rmask, gmask, bmask, amask); + flags = SDL_PublicSurface->flags & SDL_HWSURFACE; + flags |= surface->flags & (SDL_SRCALPHA | SDL_RLEACCELOK); + converted = SDL_ConvertSurface(surface, format, flags); + SDL_FreeFormat(format); + return(converted); +} + +/* + * Update a specific portion of the physical screen + */ +void SDL_UpdateRect(SDL_Surface *screen, Sint32 x, Sint32 y, Uint32 w, Uint32 h) +{ + if ( screen ) { + SDL_Rect rect; + + /* Perform some checking */ + if ( w == 0 ) + w = screen->w; + if ( h == 0 ) + h = screen->h; + if ( (int)(x+w) > screen->w ) + return; + if ( (int)(y+h) > screen->h ) + return; + + /* Fill the rectangle */ + rect.x = (Sint16)x; + rect.y = (Sint16)y; + rect.w = (Uint16)w; + rect.h = (Uint16)h; + SDL_UpdateRects(screen, 1, &rect); + } +} +void SDL_UpdateRects (SDL_Surface *screen, int numrects, SDL_Rect *rects) +{ + int i; + SDL_VideoDevice *video = current_video; + SDL_VideoDevice *this = current_video; + + if ( (screen->flags & (SDL_OPENGL | SDL_OPENGLBLIT)) == SDL_OPENGL ) { + SDL_SetError("OpenGL active, use SDL_GL_SwapBuffers()"); + return; + } + if ( screen == SDL_ShadowSurface ) { + /* Blit the shadow surface using saved mapping */ + SDL_Palette *pal = screen->format->palette; + SDL_Color *saved_colors = NULL; + if ( pal && !(SDL_VideoSurface->flags & SDL_HWPALETTE) ) { + /* simulated 8bpp, use correct physical palette */ + saved_colors = pal->colors; + if ( video->gammacols ) { + /* gamma-corrected palette */ + pal->colors = video->gammacols; + } else if ( video->physpal ) { + /* physical palette different from logical */ + pal->colors = video->physpal->colors; + } + } + if ( SHOULD_DRAWCURSOR(SDL_cursorstate) ) { + SDL_LockCursor(); + SDL_DrawCursor(SDL_ShadowSurface); + for ( i=0; i<numrects; ++i ) { + SDL_LowerBlit(SDL_ShadowSurface, &rects[i], + SDL_VideoSurface, &rects[i]); + } + SDL_EraseCursor(SDL_ShadowSurface); + SDL_UnlockCursor(); + } else { + for ( i=0; i<numrects; ++i ) { + SDL_LowerBlit(SDL_ShadowSurface, &rects[i], + SDL_VideoSurface, &rects[i]); + } + } + if ( saved_colors ) { + pal->colors = saved_colors; + } + + /* Fall through to video surface update */ + screen = SDL_VideoSurface; + } + if ( screen == SDL_VideoSurface ) { + /* Update the video surface */ + if ( screen->offset ) { + for ( i=0; i<numrects; ++i ) { + rects[i].x += video->offset_x; + rects[i].y += video->offset_y; + } + video->UpdateRects(this, numrects, rects); + for ( i=0; i<numrects; ++i ) { + rects[i].x -= video->offset_x; + rects[i].y -= video->offset_y; + } + } else { + video->UpdateRects(this, numrects, rects); + } + } +} + +/* + * Performs hardware double buffering, if possible, or a full update if not. + */ +int SDL_Flip(SDL_Surface *screen) +{ + SDL_VideoDevice *video = current_video; + /* Copy the shadow surface to the video surface */ + if ( screen == SDL_ShadowSurface ) { + SDL_Rect rect; + SDL_Palette *pal = screen->format->palette; + SDL_Color *saved_colors = NULL; + if ( pal && !(SDL_VideoSurface->flags & SDL_HWPALETTE) ) { + /* simulated 8bpp, use correct physical palette */ + saved_colors = pal->colors; + if ( video->gammacols ) { + /* gamma-corrected palette */ + pal->colors = video->gammacols; + } else if ( video->physpal ) { + /* physical palette different from logical */ + pal->colors = video->physpal->colors; + } + } + + rect.x = 0; + rect.y = 0; + rect.w = screen->w; + rect.h = screen->h; + if ( SHOULD_DRAWCURSOR(SDL_cursorstate) ) { + SDL_LockCursor(); + SDL_DrawCursor(SDL_ShadowSurface); + SDL_LowerBlit(SDL_ShadowSurface, &rect, + SDL_VideoSurface, &rect); + SDL_EraseCursor(SDL_ShadowSurface); + SDL_UnlockCursor(); + } else { + SDL_LowerBlit(SDL_ShadowSurface, &rect, + SDL_VideoSurface, &rect); + } + if ( saved_colors ) { + pal->colors = saved_colors; + } + + /* Fall through to video surface update */ + screen = SDL_VideoSurface; + } + if ( (screen->flags & SDL_DOUBLEBUF) == SDL_DOUBLEBUF ) { + SDL_VideoDevice *this = current_video; + return(video->FlipHWSurface(this, SDL_VideoSurface)); + } else { + SDL_UpdateRect(screen, 0, 0, 0, 0); + } + return(0); +} + +static void SetPalette_logical(SDL_Surface *screen, SDL_Color *colors, + int firstcolor, int ncolors) +{ + SDL_Palette *pal = screen->format->palette; + SDL_Palette *vidpal; + + if ( colors != (pal->colors + firstcolor) ) { + SDL_memcpy(pal->colors + firstcolor, colors, + ncolors * sizeof(*colors)); + } + + if ( current_video && SDL_VideoSurface ) { + vidpal = SDL_VideoSurface->format->palette; + if ( (screen == SDL_ShadowSurface) && vidpal ) { + /* + * This is a shadow surface, and the physical + * framebuffer is also indexed. Propagate the + * changes to its logical palette so that + * updates are always identity blits + */ + SDL_memcpy(vidpal->colors + firstcolor, colors, + ncolors * sizeof(*colors)); + } + } + SDL_FormatChanged(screen); +} + +static int SetPalette_physical(SDL_Surface *screen, + SDL_Color *colors, int firstcolor, int ncolors) +{ + SDL_VideoDevice *video = current_video; + int gotall = 1; + + if ( video->physpal ) { + /* We need to copy the new colors, since we haven't + * already done the copy in the logical set above. + */ + SDL_memcpy(video->physpal->colors + firstcolor, + colors, ncolors * sizeof(*colors)); + } + if ( screen == SDL_ShadowSurface ) { + if ( SDL_VideoSurface->flags & SDL_HWPALETTE ) { + /* + * The real screen is also indexed - set its physical + * palette. The physical palette does not include the + * gamma modification, we apply it directly instead, + * but this only happens if we have hardware palette. + */ + screen = SDL_VideoSurface; + } else { + /* + * The video surface is not indexed - invalidate any + * active shadow-to-video blit mappings. + */ + if ( screen->map->dst == SDL_VideoSurface ) { + SDL_InvalidateMap(screen->map); + } + if ( video->gamma ) { + if( ! video->gammacols ) { + SDL_Palette *pp = video->physpal; + if(!pp) + pp = screen->format->palette; + video->gammacols = SDL_malloc(pp->ncolors + * sizeof(SDL_Color)); + SDL_ApplyGamma(video->gamma, + pp->colors, + video->gammacols, + pp->ncolors); + } else { + SDL_ApplyGamma(video->gamma, colors, + video->gammacols + + firstcolor, + ncolors); + } + } + SDL_UpdateRect(screen, 0, 0, 0, 0); + } + } + + if ( screen == SDL_VideoSurface ) { + SDL_Color gcolors[256]; + + if ( video->gamma ) { + SDL_ApplyGamma(video->gamma, colors, gcolors, ncolors); + colors = gcolors; + } + gotall = video->SetColors(video, firstcolor, ncolors, colors); + if ( ! gotall ) { + /* The video flags shouldn't have SDL_HWPALETTE, and + the video driver is responsible for copying back the + correct colors into the video surface palette. + */ + ; + } + SDL_CursorPaletteChanged(); + } + return gotall; +} + +/* + * Set the physical and/or logical colormap of a surface: + * Only the screen has a physical colormap. It determines what is actually + * sent to the display. + * The logical colormap is used to map blits to/from the surface. + * 'which' is one or both of SDL_LOGPAL, SDL_PHYSPAL + * + * Return nonzero if all colours were set as requested, or 0 otherwise. + */ +int SDL_SetPalette(SDL_Surface *screen, int which, + SDL_Color *colors, int firstcolor, int ncolors) +{ + SDL_Palette *pal; + int gotall; + int palsize; + + if ( !screen ) { + return 0; + } + if ( !current_video || screen != SDL_PublicSurface ) { + /* only screens have physical palettes */ + which &= ~SDL_PHYSPAL; + } else if ( (screen->flags & SDL_HWPALETTE) != SDL_HWPALETTE ) { + /* hardware palettes required for split colormaps */ + which |= SDL_PHYSPAL | SDL_LOGPAL; + } + + /* Verify the parameters */ + pal = screen->format->palette; + if( !pal ) { + return 0; /* not a palettized surface */ + } + gotall = 1; + palsize = 1 << screen->format->BitsPerPixel; + if ( ncolors > (palsize - firstcolor) ) { + ncolors = (palsize - firstcolor); + gotall = 0; + } + + if ( which & SDL_LOGPAL ) { + /* + * Logical palette change: The actual screen isn't affected, + * but the internal colormap is altered so that the + * interpretation of the pixel values (for blits etc) is + * changed. + */ + SetPalette_logical(screen, colors, firstcolor, ncolors); + } + if ( which & SDL_PHYSPAL ) { + SDL_VideoDevice *video = current_video; + /* + * Physical palette change: This doesn't affect the + * program's idea of what the screen looks like, but changes + * its actual appearance. + */ + if ( !video->physpal && !(which & SDL_LOGPAL) ) { + /* Lazy physical palette allocation */ + int size; + SDL_Palette *pp = SDL_malloc(sizeof(*pp)); + if ( !pp ) { + return 0; + } + video->physpal = pp; + pp->ncolors = pal->ncolors; + size = pp->ncolors * sizeof(SDL_Color); + pp->colors = SDL_malloc(size); + if ( !pp->colors ) { + return 0; + } + SDL_memcpy(pp->colors, pal->colors, size); + } + if ( ! SetPalette_physical(screen, + colors, firstcolor, ncolors) ) { + gotall = 0; + } + } + return gotall; +} + +int SDL_SetColors(SDL_Surface *screen, SDL_Color *colors, int firstcolor, + int ncolors) +{ + return SDL_SetPalette(screen, SDL_LOGPAL | SDL_PHYSPAL, + colors, firstcolor, ncolors); +} + +/* + * Clean up the video subsystem + */ +void SDL_VideoQuit (void) +{ + SDL_Surface *ready_to_go; + + if ( current_video ) { + SDL_VideoDevice *video = current_video; + SDL_VideoDevice *this = current_video; + + /* Halt event processing before doing anything else */ + SDL_StopEventLoop(); + + /* Clean up allocated window manager items */ + if ( SDL_PublicSurface ) { + SDL_PublicSurface = NULL; + } + SDL_CursorQuit(); + + /* Just in case... */ + SDL_WM_GrabInputOff(); + + /* Clean up the system video */ + video->VideoQuit(this); + + /* Free any lingering surfaces */ + ready_to_go = SDL_ShadowSurface; + SDL_ShadowSurface = NULL; + SDL_FreeSurface(ready_to_go); + if ( SDL_VideoSurface != NULL ) { + ready_to_go = SDL_VideoSurface; + SDL_VideoSurface = NULL; + SDL_FreeSurface(ready_to_go); + } + SDL_PublicSurface = NULL; + + /* Clean up miscellaneous memory */ + if ( video->physpal ) { + SDL_free(video->physpal->colors); + SDL_free(video->physpal); + video->physpal = NULL; + } + if ( video->gammacols ) { + SDL_free(video->gammacols); + video->gammacols = NULL; + } + if ( video->gamma ) { + SDL_free(video->gamma); + video->gamma = NULL; + } + if ( video->wm_title != NULL ) { + SDL_free(video->wm_title); + video->wm_title = NULL; + } + if ( video->wm_icon != NULL ) { + SDL_free(video->wm_icon); + video->wm_icon = NULL; + } + + /* Finish cleaning up video subsystem */ + video->free(this); + current_video = NULL; + } + return; +} + +/* Load the GL driver library */ +int SDL_GL_LoadLibrary(const char *path) +{ + SDL_VideoDevice *video = current_video; + SDL_VideoDevice *this = current_video; + int retval; + + retval = -1; + if ( video == NULL ) { + SDL_SetError("Video subsystem has not been initialized"); + } else { + if ( video->GL_LoadLibrary ) { + retval = video->GL_LoadLibrary(this, path); + } else { + SDL_SetError("No dynamic GL support in video driver"); + } + } + return(retval); +} + +void *SDL_GL_GetProcAddress(const char* proc) +{ + SDL_VideoDevice *video = current_video; + SDL_VideoDevice *this = current_video; + void *func; + + func = NULL; + if ( video->GL_GetProcAddress ) { + if ( video->gl_config.driver_loaded ) { + func = video->GL_GetProcAddress(this, proc); + } else { + SDL_SetError("No GL driver has been loaded"); + } + } else { + SDL_SetError("No dynamic GL support in video driver"); + } + return func; +} + +/* Set the specified GL attribute for setting up a GL video mode */ +int SDL_GL_SetAttribute( SDL_GLattr attr, int value ) +{ + int retval; + SDL_VideoDevice *video = current_video; + + retval = 0; + switch (attr) { + case SDL_GL_RED_SIZE: + video->gl_config.red_size = value; + break; + case SDL_GL_GREEN_SIZE: + video->gl_config.green_size = value; + break; + case SDL_GL_BLUE_SIZE: + video->gl_config.blue_size = value; + break; + case SDL_GL_ALPHA_SIZE: + video->gl_config.alpha_size = value; + break; + case SDL_GL_DOUBLEBUFFER: + video->gl_config.double_buffer = value; + break; + case SDL_GL_BUFFER_SIZE: + video->gl_config.buffer_size = value; + break; + case SDL_GL_DEPTH_SIZE: + video->gl_config.depth_size = value; + break; + case SDL_GL_STENCIL_SIZE: + video->gl_config.stencil_size = value; + break; + case SDL_GL_ACCUM_RED_SIZE: + video->gl_config.accum_red_size = value; + break; + case SDL_GL_ACCUM_GREEN_SIZE: + video->gl_config.accum_green_size = value; + break; + case SDL_GL_ACCUM_BLUE_SIZE: + video->gl_config.accum_blue_size = value; + break; + case SDL_GL_ACCUM_ALPHA_SIZE: + video->gl_config.accum_alpha_size = value; + break; + case SDL_GL_STEREO: + video->gl_config.stereo = value; + break; + case SDL_GL_MULTISAMPLEBUFFERS: + video->gl_config.multisamplebuffers = value; + break; + case SDL_GL_MULTISAMPLESAMPLES: + video->gl_config.multisamplesamples = value; + break; + case SDL_GL_ACCELERATED_VISUAL: + video->gl_config.accelerated = value; + break; + case SDL_GL_SWAP_CONTROL: + video->gl_config.swap_control = value; + break; + default: + SDL_SetError("Unknown OpenGL attribute"); + retval = -1; + break; + } + return(retval); +} + +/* Retrieve an attribute value from the windowing system. */ +int SDL_GL_GetAttribute(SDL_GLattr attr, int* value) +{ + int retval = -1; + SDL_VideoDevice* video = current_video; + SDL_VideoDevice* this = current_video; + + if ( video->GL_GetAttribute ) { + retval = this->GL_GetAttribute(this, attr, value); + } else { + *value = 0; + SDL_SetError("GL_GetAttribute not supported"); + } + return retval; +} + +/* Perform a GL buffer swap on the current GL context */ +void SDL_GL_SwapBuffers(void) +{ + SDL_VideoDevice *video = current_video; + SDL_VideoDevice *this = current_video; + + if ( video->screen->flags & SDL_OPENGL ) { + video->GL_SwapBuffers(this); + } else { + SDL_SetError("OpenGL video mode has not been set"); + } +} + +/* Update rects with locking */ +void SDL_GL_UpdateRectsLock(SDL_VideoDevice* this, int numrects, SDL_Rect *rects) +{ + SDL_GL_Lock(); + SDL_GL_UpdateRects(numrects, rects); + SDL_GL_Unlock(); +} + +/* Update rects without state setting and changing (the caller is responsible for it) */ +void SDL_GL_UpdateRects(int numrects, SDL_Rect *rects) +{ +#if SDL_VIDEO_OPENGL + SDL_VideoDevice *this = current_video; + SDL_Rect update, tmp; + int x, y, i; + + for ( i = 0; i < numrects; i++ ) + { + tmp.y = rects[i].y; + tmp.h = rects[i].h; + for ( y = 0; y <= rects[i].h / 256; y++ ) + { + tmp.x = rects[i].x; + tmp.w = rects[i].w; + for ( x = 0; x <= rects[i].w / 256; x++ ) + { + update.x = tmp.x; + update.y = tmp.y; + update.w = tmp.w; + update.h = tmp.h; + + if ( update.w > 256 ) + update.w = 256; + + if ( update.h > 256 ) + update.h = 256; + + this->glFlush(); + this->glTexSubImage2D( + GL_TEXTURE_2D, + 0, + 0, + 0, + update.w, + update.h, + this->is_32bit? GL_RGBA : GL_RGB, +#ifdef GL_VERSION_1_2 + this->is_32bit ? GL_UNSIGNED_BYTE : GL_UNSIGNED_SHORT_5_6_5, +#else + GL_UNSIGNED_BYTE, +#endif + (Uint8 *)this->screen->pixels + + this->screen->format->BytesPerPixel * update.x + + update.y * this->screen->pitch ); + + this->glFlush(); + /* + * Note the parens around the function name: + * This is because some OpenGL implementations define glTexCoord etc + * as macros, and we don't want them expanded here. + */ + this->glBegin(GL_TRIANGLE_STRIP); + (this->glTexCoord2f)( 0.0, 0.0 ); + (this->glVertex2i)( update.x, update.y ); + (this->glTexCoord2f)( (float)(update.w / 256.0), 0.0 ); + (this->glVertex2i)( update.x + update.w, update.y ); + (this->glTexCoord2f)( 0.0, (float)(update.h / 256.0) ); + (this->glVertex2i)( update.x, update.y + update.h ); + (this->glTexCoord2f)( (float)(update.w / 256.0), (float)(update.h / 256.0) ); + (this->glVertex2i)( update.x + update.w , update.y + update.h ); + this->glEnd(); + + tmp.x += 256; + tmp.w -= 256; + } + tmp.y += 256; + tmp.h -= 256; + } + } +#endif +} + +/* Lock == save current state */ +void SDL_GL_Lock() +{ +#if SDL_VIDEO_OPENGL + lock_count--; + if (lock_count==-1) + { + SDL_VideoDevice *this = current_video; + + this->glPushAttrib( GL_ALL_ATTRIB_BITS ); /* TODO: narrow range of what is saved */ +#ifdef GL_CLIENT_PIXEL_STORE_BIT + this->glPushClientAttrib( GL_CLIENT_PIXEL_STORE_BIT ); +#endif + + this->glEnable(GL_TEXTURE_2D); + this->glEnable(GL_BLEND); + this->glDisable(GL_FOG); + this->glDisable(GL_ALPHA_TEST); + this->glDisable(GL_DEPTH_TEST); + this->glDisable(GL_SCISSOR_TEST); + this->glDisable(GL_STENCIL_TEST); + this->glDisable(GL_CULL_FACE); + + this->glBindTexture( GL_TEXTURE_2D, this->texture ); + this->glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE ); + this->glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST ); + this->glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST ); + this->glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT ); + this->glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT ); + + this->glPixelStorei( GL_UNPACK_ROW_LENGTH, this->screen->pitch / this->screen->format->BytesPerPixel ); + this->glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + (this->glColor4f)(1.0, 1.0, 1.0, 1.0); /* Solaris workaround */ + + this->glViewport(0, 0, this->screen->w, this->screen->h); + this->glMatrixMode(GL_PROJECTION); + this->glPushMatrix(); + this->glLoadIdentity(); + + this->glOrtho(0.0, (GLdouble) this->screen->w, (GLdouble) this->screen->h, 0.0, 0.0, 1.0); + + this->glMatrixMode(GL_MODELVIEW); + this->glPushMatrix(); + this->glLoadIdentity(); + } +#endif +} + +/* Unlock == restore saved state */ +void SDL_GL_Unlock() +{ +#if SDL_VIDEO_OPENGL + lock_count++; + if (lock_count==0) + { + SDL_VideoDevice *this = current_video; + + this->glPopMatrix(); + this->glMatrixMode(GL_PROJECTION); + this->glPopMatrix(); + + this->glPopClientAttrib(); + this->glPopAttrib(); + } +#endif +} + + +void SDL_Audio_SetCaption(const char *caption); + +/* + * Sets/Gets the title and icon text of the display window, if any. + */ +void SDL_WM_SetCaption (const char *title, const char *icon) +{ + SDL_VideoDevice *video = current_video; + SDL_VideoDevice *this = current_video; + + if ( video ) { + if ( title ) { + if ( video->wm_title ) { + SDL_free(video->wm_title); + } + video->wm_title = SDL_strdup(title); + } + if ( icon ) { + if ( video->wm_icon ) { + SDL_free(video->wm_icon); + } + video->wm_icon = SDL_strdup(icon); + } + if ( (title || icon) && (video->SetCaption != NULL) ) { + video->SetCaption(this, video->wm_title,video->wm_icon); + } + } + + /* PulseAudio can make use of this information. */ + SDL_Audio_SetCaption(title); +} + +void SDL_WM_GetCaption (char **title, char **icon) +{ + SDL_VideoDevice *video = current_video; + + if ( video ) { + if ( title ) { + *title = video->wm_title; + } + if ( icon ) { + *icon = video->wm_icon; + } + } +} + +/* Utility function used by SDL_WM_SetIcon(); + * flags & 1 for color key, flags & 2 for alpha channel. */ +static void CreateMaskFromColorKeyOrAlpha(SDL_Surface *icon, Uint8 *mask, int flags) +{ + int x, y; + Uint32 colorkey; +#define SET_MASKBIT(icon, x, y, mask) \ + mask[(y*((icon->w+7)/8))+(x/8)] &= ~(0x01<<(7-(x%8))) + + colorkey = icon->format->colorkey; + switch (icon->format->BytesPerPixel) { + case 1: { Uint8 *pixels; + for ( y=0; y<icon->h; ++y ) { + pixels = (Uint8 *)icon->pixels + y*icon->pitch; + for ( x=0; x<icon->w; ++x ) { + if ( *pixels++ == colorkey ) { + SET_MASKBIT(icon, x, y, mask); + } + } + } + } + break; + + case 2: { Uint16 *pixels; + for ( y=0; y<icon->h; ++y ) { + pixels = (Uint16 *)icon->pixels + + y*icon->pitch/2; + for ( x=0; x<icon->w; ++x ) { + if ( (flags & 1) && *pixels == colorkey ) { + SET_MASKBIT(icon, x, y, mask); + } else if((flags & 2) && (*pixels & icon->format->Amask) == 0) { + SET_MASKBIT(icon, x, y, mask); + } + pixels++; + } + } + } + break; + + case 4: { Uint32 *pixels; + for ( y=0; y<icon->h; ++y ) { + pixels = (Uint32 *)icon->pixels + + y*icon->pitch/4; + for ( x=0; x<icon->w; ++x ) { + if ( (flags & 1) && *pixels == colorkey ) { + SET_MASKBIT(icon, x, y, mask); + } else if((flags & 2) && (*pixels & icon->format->Amask) == 0) { + SET_MASKBIT(icon, x, y, mask); + } + pixels++; + } + } + } + break; + } +} + +/* + * Sets the window manager icon for the display window. + */ +void SDL_WM_SetIcon (SDL_Surface *icon, Uint8 *mask) +{ + SDL_VideoDevice *video = current_video; + SDL_VideoDevice *this = current_video; + + if ( icon && video->SetIcon ) { + /* Generate a mask if necessary, and create the icon! */ + if ( mask == NULL ) { + int mask_len = icon->h*(icon->w+7)/8; + int flags = 0; + mask = (Uint8 *)SDL_malloc(mask_len); + if ( mask == NULL ) { + return; + } + SDL_memset(mask, ~0, mask_len); + if ( icon->flags & SDL_SRCCOLORKEY ) flags |= 1; + if ( icon->flags & SDL_SRCALPHA ) flags |= 2; + if( flags ) { + CreateMaskFromColorKeyOrAlpha(icon, mask, flags); + } + video->SetIcon(video, icon, mask); + SDL_free(mask); + } else { + video->SetIcon(this, icon, mask); + } + } +} + +/* + * Grab or ungrab the keyboard and mouse input. + * This function returns the final grab mode after calling the + * driver dependent function. + */ +static SDL_GrabMode SDL_WM_GrabInputRaw(SDL_GrabMode mode) +{ + SDL_VideoDevice *video = current_video; + SDL_VideoDevice *this = current_video; + + /* Only do something if we have support for grabs */ + if ( video->GrabInput == NULL ) { + return(video->input_grab); + } + + /* If the final grab mode if off, only then do we actually grab */ +#ifdef DEBUG_GRAB + printf("SDL_WM_GrabInputRaw(%d) ... ", mode); +#endif + if ( mode == SDL_GRAB_OFF ) { + if ( video->input_grab != SDL_GRAB_OFF ) { + mode = video->GrabInput(this, mode); + } + } else { + if ( video->input_grab == SDL_GRAB_OFF ) { + mode = video->GrabInput(this, mode); + } + } + if ( mode != video->input_grab ) { + video->input_grab = mode; + if ( video->CheckMouseMode ) { + video->CheckMouseMode(this); + } + } +#ifdef DEBUG_GRAB + printf("Final mode %d\n", video->input_grab); +#endif + + /* Return the final grab state */ + if ( mode >= SDL_GRAB_FULLSCREEN ) { + mode -= SDL_GRAB_FULLSCREEN; + } + return(mode); +} +SDL_GrabMode SDL_WM_GrabInput(SDL_GrabMode mode) +{ + SDL_VideoDevice *video = current_video; + + /* If the video isn't initialized yet, we can't do anything */ + if ( ! video ) { + return SDL_GRAB_OFF; + } + + /* Return the current mode on query */ + if ( mode == SDL_GRAB_QUERY ) { + mode = video->input_grab; + if ( mode >= SDL_GRAB_FULLSCREEN ) { + mode -= SDL_GRAB_FULLSCREEN; + } + return(mode); + } + +#ifdef DEBUG_GRAB + printf("SDL_WM_GrabInput(%d) ... ", mode); +#endif + /* If the video surface is fullscreen, we always grab */ + if ( mode >= SDL_GRAB_FULLSCREEN ) { + mode -= SDL_GRAB_FULLSCREEN; + } + if ( SDL_VideoSurface && (SDL_VideoSurface->flags & SDL_FULLSCREEN) ) { + mode += SDL_GRAB_FULLSCREEN; + } + return(SDL_WM_GrabInputRaw(mode)); +} +static SDL_GrabMode SDL_WM_GrabInputOff(void) +{ + SDL_GrabMode mode; + + /* First query the current grab state */ + mode = SDL_WM_GrabInput(SDL_GRAB_QUERY); + + /* Now explicitly turn off input grab */ + SDL_WM_GrabInputRaw(SDL_GRAB_OFF); + + /* Return the old state */ + return(mode); +} + +/* + * Iconify the window in window managed environments. + * A successful iconification will result in an SDL_APPACTIVE loss event. + */ +int SDL_WM_IconifyWindow(void) +{ + SDL_VideoDevice *video = current_video; + SDL_VideoDevice *this = current_video; + int retval; + + retval = 0; + if ( video->IconifyWindow ) { + retval = video->IconifyWindow(this); + } + return(retval); +} + +/* + * Toggle fullscreen mode + */ +int SDL_WM_ToggleFullScreen(SDL_Surface *surface) +{ + SDL_VideoDevice *video = current_video; + SDL_VideoDevice *this = current_video; + int toggled; + + toggled = 0; + if ( SDL_PublicSurface && (surface == SDL_PublicSurface) && + video->ToggleFullScreen ) { + if ( surface->flags & SDL_FULLSCREEN ) { + toggled = video->ToggleFullScreen(this, 0); + if ( toggled ) { + SDL_VideoSurface->flags &= ~SDL_FULLSCREEN; + SDL_PublicSurface->flags &= ~SDL_FULLSCREEN; + } + } else { + toggled = video->ToggleFullScreen(this, 1); + if ( toggled ) { + SDL_VideoSurface->flags |= SDL_FULLSCREEN; + SDL_PublicSurface->flags |= SDL_FULLSCREEN; + } + } + /* Double-check the grab state inside SDL_WM_GrabInput() */ + if ( toggled ) { + SDL_WM_GrabInput(video->input_grab); + } + } + return(toggled); +} + +/* + * Get some platform dependent window manager information + */ +int SDL_GetWMInfo (SDL_SysWMinfo *info) +{ + SDL_VideoDevice *video = current_video; + SDL_VideoDevice *this = current_video; + + if ( video && video->GetWMInfo ) { + return(video->GetWMInfo(this, info)); + } else { + return(0); + } +} diff --git a/3rdparty/SDL/src/video/SDL_yuv.c b/3rdparty/SDL/src/video/SDL_yuv.c new file mode 100644 index 0000000..eea3347 --- /dev/null +++ b/3rdparty/SDL/src/video/SDL_yuv.c @@ -0,0 +1,150 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* This is the implementation of the YUV video surface support */ + +#include "SDL_video.h" +#include "SDL_sysvideo.h" +#include "SDL_yuvfuncs.h" +#include "SDL_yuv_sw_c.h" + + +SDL_Overlay *SDL_CreateYUVOverlay(int w, int h, Uint32 format, + SDL_Surface *display) +{ + SDL_VideoDevice *video = current_video; + SDL_VideoDevice *this = current_video; + const char *yuv_hwaccel; + SDL_Overlay *overlay; + + if ( (display->flags & SDL_OPENGL) == SDL_OPENGL ) { + SDL_SetError("YUV overlays are not supported in OpenGL mode"); + return NULL; + } + + /* Display directly on video surface, if possible */ + if ( SDL_getenv("SDL_VIDEO_YUV_DIRECT") ) { + if ( (display == SDL_PublicSurface) && + ((SDL_VideoSurface->format->BytesPerPixel == 2) || + (SDL_VideoSurface->format->BytesPerPixel == 4)) ) { + display = SDL_VideoSurface; + } + } + overlay = NULL; + yuv_hwaccel = SDL_getenv("SDL_VIDEO_YUV_HWACCEL"); + if ( ((display == SDL_VideoSurface) && video->CreateYUVOverlay) && + (!yuv_hwaccel || (SDL_atoi(yuv_hwaccel) > 0)) ) { + overlay = video->CreateYUVOverlay(this, w, h, format, display); + } + /* If hardware YUV overlay failed ... */ + if ( overlay == NULL ) { + overlay = SDL_CreateYUV_SW(this, w, h, format, display); + } + return overlay; +} + +int SDL_LockYUVOverlay(SDL_Overlay *overlay) +{ + if ( overlay == NULL ) { + SDL_SetError("Passed NULL overlay"); + return -1; + } + return overlay->hwfuncs->Lock(current_video, overlay); +} + +void SDL_UnlockYUVOverlay(SDL_Overlay *overlay) +{ + if ( overlay == NULL ) { + return; + } + overlay->hwfuncs->Unlock(current_video, overlay); +} + +int SDL_DisplayYUVOverlay(SDL_Overlay *overlay, SDL_Rect *dstrect) +{ + SDL_Rect src, dst; + int srcx, srcy, srcw, srch; + int dstx, dsty, dstw, dsth; + + if ( overlay == NULL || dstrect == NULL ) { + SDL_SetError("Passed NULL overlay or dstrect"); + return -1; + } + + /* Clip the rectangle to the screen area */ + srcx = 0; + srcy = 0; + srcw = overlay->w; + srch = overlay->h; + dstx = dstrect->x; + dsty = dstrect->y; + dstw = dstrect->w; + dsth = dstrect->h; + if ( dstx < 0 ) { + srcw += (dstx * overlay->w) / dstrect->w; + dstw += dstx; + srcx -= (dstx * overlay->w) / dstrect->w; + dstx = 0; + } + if ( (dstx+dstw) > current_video->screen->w ) { + int extra = (dstx+dstw - current_video->screen->w); + srcw -= (extra * overlay->w) / dstrect->w; + dstw -= extra; + } + if ( dsty < 0 ) { + srch += (dsty * overlay->h) / dstrect->h; + dsth += dsty; + srcy -= (dsty * overlay->h) / dstrect->h; + dsty = 0; + } + if ( (dsty+dsth) > current_video->screen->h ) { + int extra = (dsty+dsth - current_video->screen->h); + srch -= (extra * overlay->h) / dstrect->h; + dsth -= extra; + } + if ( srcw <= 0 || srch <= 0 || + srch <= 0 || dsth <= 0 ) { + return 0; + } + /* Ugh, I can't wait for SDL_Rect to be int values */ + src.x = srcx; + src.y = srcy; + src.w = srcw; + src.h = srch; + dst.x = dstx; + dst.y = dsty; + dst.w = dstw; + dst.h = dsth; + return overlay->hwfuncs->Display(current_video, overlay, &src, &dst); +} + +void SDL_FreeYUVOverlay(SDL_Overlay *overlay) +{ + if ( overlay == NULL ) { + return; + } + if ( overlay->hwfuncs ) { + overlay->hwfuncs->FreeHW(current_video, overlay); + } + SDL_free(overlay); +} diff --git a/3rdparty/SDL/src/video/SDL_yuv_mmx.c b/3rdparty/SDL/src/video/SDL_yuv_mmx.c new file mode 100644 index 0000000..f11c432 --- /dev/null +++ b/3rdparty/SDL/src/video/SDL_yuv_mmx.c @@ -0,0 +1,428 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#if (__GNUC__ > 2) && defined(__i386__) && __OPTIMIZE__ && SDL_ASSEMBLY_ROUTINES + +#include "SDL_stdinc.h" + +#include "mmx.h" + +/* *INDENT-OFF* */ + +static mmx_t MMX_0080w = { .ud = {0x00800080, 0x00800080} }; +static mmx_t MMX_00FFw = { .ud = {0x00ff00ff, 0x00ff00ff} }; +static mmx_t MMX_FF00w = { .ud = {0xff00ff00, 0xff00ff00} }; + +static mmx_t MMX_Ycoeff = { .uw = {0x004a, 0x004a, 0x004a, 0x004a} }; + +static mmx_t MMX_UbluRGB = { .uw = {0x0072, 0x0072, 0x0072, 0x0072} }; +static mmx_t MMX_VredRGB = { .uw = {0x0059, 0x0059, 0x0059, 0x0059} }; +static mmx_t MMX_UgrnRGB = { .uw = {0xffea, 0xffea, 0xffea, 0xffea} }; +static mmx_t MMX_VgrnRGB = { .uw = {0xffd2, 0xffd2, 0xffd2, 0xffd2} }; + +static mmx_t MMX_Ublu5x5 = { .uw = {0x0081, 0x0081, 0x0081, 0x0081} }; +static mmx_t MMX_Vred5x5 = { .uw = {0x0066, 0x0066, 0x0066, 0x0066} }; +static mmx_t MMX_Ugrn565 = { .uw = {0xffe8, 0xffe8, 0xffe8, 0xffe8} }; +static mmx_t MMX_Vgrn565 = { .uw = {0xffcd, 0xffcd, 0xffcd, 0xffcd} }; + +static mmx_t MMX_red565 = { .uw = {0xf800, 0xf800, 0xf800, 0xf800} }; +static mmx_t MMX_grn565 = { .uw = {0x07e0, 0x07e0, 0x07e0, 0x07e0} }; + +/** + This MMX assembler is my first assembler/MMX program ever. + Thus it maybe buggy. + Send patches to: + mvogt@rhrk.uni-kl.de + + After it worked fine I have "obfuscated" the code a bit to have + more parallism in the MMX units. This means I moved + initilisation around and delayed other instruction. + Performance measurement did not show that this brought any advantage + but in theory it _should_ be faster this way. + + The overall performanve gain to the C based dither was 30%-40%. + The MMX routine calculates 256bit=8RGB values in each cycle + (4 for row1 & 4 for row2) + + The red/green/blue.. coefficents are taken from the mpeg_play + player. They look nice, but I dont know if you can have + better values, to avoid integer rounding errors. + + + IMPORTANT: + ========== + + It is a requirement that the cr/cb/lum are 8 byte aligned and + the out are 16byte aligned or you will/may get segfaults + +*/ + +void ColorRGBDitherYV12MMX1X( int *colortab, Uint32 *rgb_2_pix, + unsigned char *lum, unsigned char *cr, + unsigned char *cb, unsigned char *out, + int rows, int cols, int mod ) +{ + Uint32 *row1; + Uint32 *row2; + + unsigned char* y = lum +cols*rows; // Pointer to the end + int x = 0; + row1 = (Uint32 *)out; // 32 bit target + row2 = (Uint32 *)out+cols+mod; // start of second row + mod = (mod+cols+mod)*4; // increment for row1 in byte + + __asm__ __volatile__ ( + // tap dance to workaround the inability to use %%ebx at will... + // move one thing to the stack... + "pushl $0\n" // save a slot on the stack. + "pushl %%ebx\n" // save %%ebx. + "movl %0, %%ebx\n" // put the thing in ebx. + "movl %%ebx,4(%%esp)\n" // put the thing in the stack slot. + "popl %%ebx\n" // get back %%ebx (the PIC register). + + ".align 8\n" + "1:\n" + + // create Cr (result in mm1) + "pushl %%ebx\n" + "movl 4(%%esp),%%ebx\n" + "movd (%%ebx),%%mm1\n" // 0 0 0 0 v3 v2 v1 v0 + "popl %%ebx\n" + "pxor %%mm7,%%mm7\n" // 00 00 00 00 00 00 00 00 + "movd (%2), %%mm2\n" // 0 0 0 0 l3 l2 l1 l0 + "punpcklbw %%mm7,%%mm1\n" // 0 v3 0 v2 00 v1 00 v0 + "punpckldq %%mm1,%%mm1\n" // 00 v1 00 v0 00 v1 00 v0 + "psubw %9,%%mm1\n" // mm1-128:r1 r1 r0 r0 r1 r1 r0 r0 + + // create Cr_g (result in mm0) + "movq %%mm1,%%mm0\n" // r1 r1 r0 r0 r1 r1 r0 r0 + "pmullw %10,%%mm0\n" // red*-46dec=0.7136*64 + "pmullw %11,%%mm1\n" // red*89dec=1.4013*64 + "psraw $6, %%mm0\n" // red=red/64 + "psraw $6, %%mm1\n" // red=red/64 + + // create L1 L2 (result in mm2,mm4) + // L2=lum+cols + "movq (%2,%4),%%mm3\n" // 0 0 0 0 L3 L2 L1 L0 + "punpckldq %%mm3,%%mm2\n" // L3 L2 L1 L0 l3 l2 l1 l0 + "movq %%mm2,%%mm4\n" // L3 L2 L1 L0 l3 l2 l1 l0 + "pand %12,%%mm2\n" // L3 0 L1 0 l3 0 l1 0 + "pand %13,%%mm4\n" // 0 L2 0 L0 0 l2 0 l0 + "psrlw $8,%%mm2\n" // 0 L3 0 L1 0 l3 0 l1 + + // create R (result in mm6) + "movq %%mm2,%%mm5\n" // 0 L3 0 L1 0 l3 0 l1 + "movq %%mm4,%%mm6\n" // 0 L2 0 L0 0 l2 0 l0 + "paddsw %%mm1, %%mm5\n" // lum1+red:x R3 x R1 x r3 x r1 + "paddsw %%mm1, %%mm6\n" // lum1+red:x R2 x R0 x r2 x r0 + "packuswb %%mm5,%%mm5\n" // R3 R1 r3 r1 R3 R1 r3 r1 + "packuswb %%mm6,%%mm6\n" // R2 R0 r2 r0 R2 R0 r2 r0 + "pxor %%mm7,%%mm7\n" // 00 00 00 00 00 00 00 00 + "punpcklbw %%mm5,%%mm6\n" // R3 R2 R1 R0 r3 r2 r1 r0 + + // create Cb (result in mm1) + "movd (%1), %%mm1\n" // 0 0 0 0 u3 u2 u1 u0 + "punpcklbw %%mm7,%%mm1\n" // 0 u3 0 u2 00 u1 00 u0 + "punpckldq %%mm1,%%mm1\n" // 00 u1 00 u0 00 u1 00 u0 + "psubw %9,%%mm1\n" // mm1-128:u1 u1 u0 u0 u1 u1 u0 u0 + // create Cb_g (result in mm5) + "movq %%mm1,%%mm5\n" // u1 u1 u0 u0 u1 u1 u0 u0 + "pmullw %14,%%mm5\n" // blue*-109dec=1.7129*64 + "pmullw %15,%%mm1\n" // blue*114dec=1.78125*64 + "psraw $6, %%mm5\n" // blue=red/64 + "psraw $6, %%mm1\n" // blue=blue/64 + + // create G (result in mm7) + "movq %%mm2,%%mm3\n" // 0 L3 0 L1 0 l3 0 l1 + "movq %%mm4,%%mm7\n" // 0 L2 0 L0 0 l2 0 l1 + "paddsw %%mm5, %%mm3\n" // lum1+Cb_g:x G3t x G1t x g3t x g1t + "paddsw %%mm5, %%mm7\n" // lum1+Cb_g:x G2t x G0t x g2t x g0t + "paddsw %%mm0, %%mm3\n" // lum1+Cr_g:x G3 x G1 x g3 x g1 + "paddsw %%mm0, %%mm7\n" // lum1+blue:x G2 x G0 x g2 x g0 + "packuswb %%mm3,%%mm3\n" // G3 G1 g3 g1 G3 G1 g3 g1 + "packuswb %%mm7,%%mm7\n" // G2 G0 g2 g0 G2 G0 g2 g0 + "punpcklbw %%mm3,%%mm7\n" // G3 G2 G1 G0 g3 g2 g1 g0 + + // create B (result in mm5) + "movq %%mm2,%%mm3\n" // 0 L3 0 L1 0 l3 0 l1 + "movq %%mm4,%%mm5\n" // 0 L2 0 L0 0 l2 0 l1 + "paddsw %%mm1, %%mm3\n" // lum1+blue:x B3 x B1 x b3 x b1 + "paddsw %%mm1, %%mm5\n" // lum1+blue:x B2 x B0 x b2 x b0 + "packuswb %%mm3,%%mm3\n" // B3 B1 b3 b1 B3 B1 b3 b1 + "packuswb %%mm5,%%mm5\n" // B2 B0 b2 b0 B2 B0 b2 b0 + "punpcklbw %%mm3,%%mm5\n" // B3 B2 B1 B0 b3 b2 b1 b0 + + // fill destination row1 (needed are mm6=Rr,mm7=Gg,mm5=Bb) + + "pxor %%mm2,%%mm2\n" // 0 0 0 0 0 0 0 0 + "pxor %%mm4,%%mm4\n" // 0 0 0 0 0 0 0 0 + "movq %%mm6,%%mm1\n" // R3 R2 R1 R0 r3 r2 r1 r0 + "movq %%mm5,%%mm3\n" // B3 B2 B1 B0 b3 b2 b1 b0 + // process lower lum + "punpcklbw %%mm4,%%mm1\n" // 0 r3 0 r2 0 r1 0 r0 + "punpcklbw %%mm4,%%mm3\n" // 0 b3 0 b2 0 b1 0 b0 + "movq %%mm1,%%mm2\n" // 0 r3 0 r2 0 r1 0 r0 + "movq %%mm3,%%mm0\n" // 0 b3 0 b2 0 b1 0 b0 + "punpcklwd %%mm1,%%mm3\n" // 0 r1 0 b1 0 r0 0 b0 + "punpckhwd %%mm2,%%mm0\n" // 0 r3 0 b3 0 r2 0 b2 + + "pxor %%mm2,%%mm2\n" // 0 0 0 0 0 0 0 0 + "movq %%mm7,%%mm1\n" // G3 G2 G1 G0 g3 g2 g1 g0 + "punpcklbw %%mm1,%%mm2\n" // g3 0 g2 0 g1 0 g0 0 + "punpcklwd %%mm4,%%mm2\n" // 0 0 g1 0 0 0 g0 0 + "por %%mm3, %%mm2\n" // 0 r1 g1 b1 0 r0 g0 b0 + "movq %%mm2,(%3)\n" // wrote out ! row1 + + "pxor %%mm2,%%mm2\n" // 0 0 0 0 0 0 0 0 + "punpcklbw %%mm1,%%mm4\n" // g3 0 g2 0 g1 0 g0 0 + "punpckhwd %%mm2,%%mm4\n" // 0 0 g3 0 0 0 g2 0 + "por %%mm0, %%mm4\n" // 0 r3 g3 b3 0 r2 g2 b2 + "movq %%mm4,8(%3)\n" // wrote out ! row1 + + // fill destination row2 (needed are mm6=Rr,mm7=Gg,mm5=Bb) + // this can be done "destructive" + "pxor %%mm2,%%mm2\n" // 0 0 0 0 0 0 0 0 + "punpckhbw %%mm2,%%mm6\n" // 0 R3 0 R2 0 R1 0 R0 + "punpckhbw %%mm1,%%mm5\n" // G3 B3 G2 B2 G1 B1 G0 B0 + "movq %%mm5,%%mm1\n" // G3 B3 G2 B2 G1 B1 G0 B0 + "punpcklwd %%mm6,%%mm1\n" // 0 R1 G1 B1 0 R0 G0 B0 + "movq %%mm1,(%5)\n" // wrote out ! row2 + "punpckhwd %%mm6,%%mm5\n" // 0 R3 G3 B3 0 R2 G2 B2 + "movq %%mm5,8(%5)\n" // wrote out ! row2 + + "addl $4,%2\n" // lum+4 + "leal 16(%3),%3\n" // row1+16 + "leal 16(%5),%5\n" // row2+16 + "addl $2,(%%esp)\n" // cr+2 + "addl $2,%1\n" // cb+2 + + "addl $4,%6\n" // x+4 + "cmpl %4,%6\n" + + "jl 1b\n" + "addl %4,%2\n" // lum += cols + "addl %8,%3\n" // row1+= mod + "addl %8,%5\n" // row2+= mod + "movl $0,%6\n" // x=0 + "cmpl %7,%2\n" + "jl 1b\n" + + "addl $4,%%esp\n" // get rid of the stack slot we reserved. + "emms\n" // reset MMX registers. + : + : "m" (cr), "r"(cb),"r"(lum), + "r"(row1),"r"(cols),"r"(row2),"m"(x),"m"(y),"m"(mod), + "m"(MMX_0080w),"m"(MMX_VgrnRGB),"m"(MMX_VredRGB), + "m"(MMX_FF00w),"m"(MMX_00FFw),"m"(MMX_UgrnRGB), + "m"(MMX_UbluRGB) + ); +} + +void Color565DitherYV12MMX1X( int *colortab, Uint32 *rgb_2_pix, + unsigned char *lum, unsigned char *cr, + unsigned char *cb, unsigned char *out, + int rows, int cols, int mod ) +{ + Uint16 *row1; + Uint16 *row2; + + unsigned char* y = lum +cols*rows; /* Pointer to the end */ + int x = 0; + row1 = (Uint16 *)out; /* 16 bit target */ + row2 = (Uint16 *)out+cols+mod; /* start of second row */ + mod = (mod+cols+mod)*2; /* increment for row1 in byte */ + + __asm__ __volatile__( + // tap dance to workaround the inability to use %%ebx at will... + // move one thing to the stack... + "pushl $0\n" // save a slot on the stack. + "pushl %%ebx\n" // save %%ebx. + "movl %0, %%ebx\n" // put the thing in ebx. + "movl %%ebx, 4(%%esp)\n" // put the thing in the stack slot. + "popl %%ebx\n" // get back %%ebx (the PIC register). + + ".align 8\n" + "1:\n" + "movd (%1), %%mm0\n" // 4 Cb 0 0 0 0 u3 u2 u1 u0 + "pxor %%mm7, %%mm7\n" + "pushl %%ebx\n" + "movl 4(%%esp), %%ebx\n" + "movd (%%ebx), %%mm1\n" // 4 Cr 0 0 0 0 v3 v2 v1 v0 + "popl %%ebx\n" + + "punpcklbw %%mm7, %%mm0\n" // 4 W cb 0 u3 0 u2 0 u1 0 u0 + "punpcklbw %%mm7, %%mm1\n" // 4 W cr 0 v3 0 v2 0 v1 0 v0 + "psubw %9, %%mm0\n" + "psubw %9, %%mm1\n" + "movq %%mm0, %%mm2\n" // Cb 0 u3 0 u2 0 u1 0 u0 + "movq %%mm1, %%mm3\n" // Cr + "pmullw %10, %%mm2\n" // Cb2green 0 R3 0 R2 0 R1 0 R0 + "movq (%2), %%mm6\n" // L1 l7 L6 L5 L4 L3 L2 L1 L0 + "pmullw %11, %%mm0\n" // Cb2blue + "pand %12, %%mm6\n" // L1 00 L6 00 L4 00 L2 00 L0 + "pmullw %13, %%mm3\n" // Cr2green + "movq (%2), %%mm7\n" // L2 + "pmullw %14, %%mm1\n" // Cr2red + "psrlw $8, %%mm7\n" // L2 00 L7 00 L5 00 L3 00 L1 + "pmullw %15, %%mm6\n" // lum1 + "paddw %%mm3, %%mm2\n" // Cb2green + Cr2green == green + "pmullw %15, %%mm7\n" // lum2 + + "movq %%mm6, %%mm4\n" // lum1 + "paddw %%mm0, %%mm6\n" // lum1 +blue 00 B6 00 B4 00 B2 00 B0 + "movq %%mm4, %%mm5\n" // lum1 + "paddw %%mm1, %%mm4\n" // lum1 +red 00 R6 00 R4 00 R2 00 R0 + "paddw %%mm2, %%mm5\n" // lum1 +green 00 G6 00 G4 00 G2 00 G0 + "psraw $6, %%mm4\n" // R1 0 .. 64 + "movq %%mm7, %%mm3\n" // lum2 00 L7 00 L5 00 L3 00 L1 + "psraw $6, %%mm5\n" // G1 - .. + + "paddw %%mm0, %%mm7\n" // Lum2 +blue 00 B7 00 B5 00 B3 00 B1 + "psraw $6, %%mm6\n" // B1 0 .. 64 + "packuswb %%mm4, %%mm4\n" // R1 R1 + "packuswb %%mm5, %%mm5\n" // G1 G1 + "packuswb %%mm6, %%mm6\n" // B1 B1 + "punpcklbw %%mm4, %%mm4\n" + "punpcklbw %%mm5, %%mm5\n" + + "pand %16, %%mm4\n" + "psllw $3, %%mm5\n" // GREEN 1 + "punpcklbw %%mm6, %%mm6\n" + "pand %17, %%mm5\n" + "pand %16, %%mm6\n" + "por %%mm5, %%mm4\n" // + "psrlw $11, %%mm6\n" // BLUE 1 + "movq %%mm3, %%mm5\n" // lum2 + "paddw %%mm1, %%mm3\n" // lum2 +red 00 R7 00 R5 00 R3 00 R1 + "paddw %%mm2, %%mm5\n" // lum2 +green 00 G7 00 G5 00 G3 00 G1 + "psraw $6, %%mm3\n" // R2 + "por %%mm6, %%mm4\n" // MM4 + "psraw $6, %%mm5\n" // G2 + "movq (%2, %4), %%mm6\n" // L3 load lum2 + "psraw $6, %%mm7\n" + "packuswb %%mm3, %%mm3\n" + "packuswb %%mm5, %%mm5\n" + "packuswb %%mm7, %%mm7\n" + "pand %12, %%mm6\n" // L3 + "punpcklbw %%mm3, %%mm3\n" + "punpcklbw %%mm5, %%mm5\n" + "pmullw %15, %%mm6\n" // lum3 + "punpcklbw %%mm7, %%mm7\n" + "psllw $3, %%mm5\n" // GREEN 2 + "pand %16, %%mm7\n" + "pand %16, %%mm3\n" + "psrlw $11, %%mm7\n" // BLUE 2 + "pand %17, %%mm5\n" + "por %%mm7, %%mm3\n" + "movq (%2,%4), %%mm7\n" // L4 load lum2 + "por %%mm5, %%mm3\n" // + "psrlw $8, %%mm7\n" // L4 + "movq %%mm4, %%mm5\n" + "punpcklwd %%mm3, %%mm4\n" + "pmullw %15, %%mm7\n" // lum4 + "punpckhwd %%mm3, %%mm5\n" + + "movq %%mm4, (%3)\n" // write row1 + "movq %%mm5, 8(%3)\n" // write row1 + + "movq %%mm6, %%mm4\n" // Lum3 + "paddw %%mm0, %%mm6\n" // Lum3 +blue + + "movq %%mm4, %%mm5\n" // Lum3 + "paddw %%mm1, %%mm4\n" // Lum3 +red + "paddw %%mm2, %%mm5\n" // Lum3 +green + "psraw $6, %%mm4\n" + "movq %%mm7, %%mm3\n" // Lum4 + "psraw $6, %%mm5\n" + "paddw %%mm0, %%mm7\n" // Lum4 +blue + "psraw $6, %%mm6\n" // Lum3 +blue + "movq %%mm3, %%mm0\n" // Lum4 + "packuswb %%mm4, %%mm4\n" + "paddw %%mm1, %%mm3\n" // Lum4 +red + "packuswb %%mm5, %%mm5\n" + "paddw %%mm2, %%mm0\n" // Lum4 +green + "packuswb %%mm6, %%mm6\n" + "punpcklbw %%mm4, %%mm4\n" + "punpcklbw %%mm5, %%mm5\n" + "punpcklbw %%mm6, %%mm6\n" + "psllw $3, %%mm5\n" // GREEN 3 + "pand %16, %%mm4\n" + "psraw $6, %%mm3\n" // psr 6 + "psraw $6, %%mm0\n" + "pand %16, %%mm6\n" // BLUE + "pand %17, %%mm5\n" + "psrlw $11, %%mm6\n" // BLUE 3 + "por %%mm5, %%mm4\n" + "psraw $6, %%mm7\n" + "por %%mm6, %%mm4\n" + "packuswb %%mm3, %%mm3\n" + "packuswb %%mm0, %%mm0\n" + "packuswb %%mm7, %%mm7\n" + "punpcklbw %%mm3, %%mm3\n" + "punpcklbw %%mm0, %%mm0\n" + "punpcklbw %%mm7, %%mm7\n" + "pand %16, %%mm3\n" + "pand %16, %%mm7\n" // BLUE + "psllw $3, %%mm0\n" // GREEN 4 + "psrlw $11, %%mm7\n" + "pand %17, %%mm0\n" + "por %%mm7, %%mm3\n" + "por %%mm0, %%mm3\n" + + "movq %%mm4, %%mm5\n" + + "punpcklwd %%mm3, %%mm4\n" + "punpckhwd %%mm3, %%mm5\n" + + "movq %%mm4, (%5)\n" + "movq %%mm5, 8(%5)\n" + + "addl $8, %6\n" + "addl $8, %2\n" + "addl $4, (%%esp)\n" + "addl $4, %1\n" + "cmpl %4, %6\n" + "leal 16(%3), %3\n" + "leal 16(%5),%5\n" // row2+16 + + "jl 1b\n" + "addl %4, %2\n" // lum += cols + "addl %8, %3\n" // row1+= mod + "addl %8, %5\n" // row2+= mod + "movl $0, %6\n" // x=0 + "cmpl %7, %2\n" + "jl 1b\n" + "addl $4, %%esp\n" // get rid of the stack slot we reserved. + "emms\n" + : + : "m" (cr), "r"(cb),"r"(lum), + "r"(row1),"r"(cols),"r"(row2),"m"(x),"m"(y),"m"(mod), + "m"(MMX_0080w),"m"(MMX_Ugrn565),"m"(MMX_Ublu5x5), + "m"(MMX_00FFw),"m"(MMX_Vgrn565),"m"(MMX_Vred5x5), + "m"(MMX_Ycoeff),"m"(MMX_red565),"m"(MMX_grn565) + ); +} + +/* *INDENT-ON* */ + +#endif /* GCC3 i386 inline assembly */ + diff --git a/3rdparty/SDL/src/video/SDL_yuv_sw.c b/3rdparty/SDL/src/video/SDL_yuv_sw.c new file mode 100644 index 0000000..c555ce0 --- /dev/null +++ b/3rdparty/SDL/src/video/SDL_yuv_sw.c @@ -0,0 +1,1299 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* This is the software implementation of the YUV video overlay support */ + +/* This code was derived from code carrying the following copyright notices: + + * Copyright (c) 1995 The Regents of the University of California. + * All rights reserved. + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose, without fee, and without written agreement is + * hereby granted, provided that the above copyright notice and the following + * two paragraphs appear in all copies of this software. + * + * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT + * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF + * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + + * Copyright (c) 1995 Erik Corry + * All rights reserved. + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose, without fee, and without written agreement is + * hereby granted, provided that the above copyright notice and the following + * two paragraphs appear in all copies of this software. + * + * IN NO EVENT SHALL ERIK CORRY BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, + * SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OF + * THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF ERIK CORRY HAS BEEN ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * + * ERIK CORRY SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS" + * BASIS, AND ERIK CORRY HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, + * UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + + * Portions of this software Copyright (c) 1995 Brown University. + * All rights reserved. + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose, without fee, and without written agreement + * is hereby granted, provided that the above copyright notice and the + * following two paragraphs appear in all copies of this software. + * + * IN NO EVENT SHALL BROWN UNIVERSITY BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT + * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF BROWN + * UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * BROWN UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS" + * BASIS, AND BROWN UNIVERSITY HAS NO OBLIGATION TO PROVIDE MAINTENANCE, + * SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + */ + +#include "SDL_video.h" +#include "SDL_cpuinfo.h" +#include "SDL_stretch_c.h" +#include "SDL_yuvfuncs.h" +#include "SDL_yuv_sw_c.h" + +/* The functions used to manipulate software video overlays */ +static struct private_yuvhwfuncs sw_yuvfuncs = { + SDL_LockYUV_SW, + SDL_UnlockYUV_SW, + SDL_DisplayYUV_SW, + SDL_FreeYUV_SW +}; + +/* RGB conversion lookup tables */ +struct private_yuvhwdata { + SDL_Surface *stretch; + SDL_Surface *display; + Uint8 *pixels; + int *colortab; + Uint32 *rgb_2_pix; + void (*Display1X)(int *colortab, Uint32 *rgb_2_pix, + unsigned char *lum, unsigned char *cr, + unsigned char *cb, unsigned char *out, + int rows, int cols, int mod ); + void (*Display2X)(int *colortab, Uint32 *rgb_2_pix, + unsigned char *lum, unsigned char *cr, + unsigned char *cb, unsigned char *out, + int rows, int cols, int mod ); + + /* These are just so we don't have to allocate them separately */ + Uint16 pitches[3]; + Uint8 *planes[3]; +}; + + +/* The colorspace conversion functions */ + +#if (__GNUC__ > 2) && defined(__i386__) && __OPTIMIZE__ && SDL_ASSEMBLY_ROUTINES +extern void Color565DitherYV12MMX1X( int *colortab, Uint32 *rgb_2_pix, + unsigned char *lum, unsigned char *cr, + unsigned char *cb, unsigned char *out, + int rows, int cols, int mod ); +extern void ColorRGBDitherYV12MMX1X( int *colortab, Uint32 *rgb_2_pix, + unsigned char *lum, unsigned char *cr, + unsigned char *cb, unsigned char *out, + int rows, int cols, int mod ); +#endif + +static void Color16DitherYV12Mod1X( int *colortab, Uint32 *rgb_2_pix, + unsigned char *lum, unsigned char *cr, + unsigned char *cb, unsigned char *out, + int rows, int cols, int mod ) +{ + unsigned short* row1; + unsigned short* row2; + unsigned char* lum2; + int x, y; + int cr_r; + int crb_g; + int cb_b; + int cols_2 = cols / 2; + + row1 = (unsigned short*) out; + row2 = row1 + cols + mod; + lum2 = lum + cols; + + mod += cols + mod; + + y = rows / 2; + while( y-- ) + { + x = cols_2; + while( x-- ) + { + register int L; + + cr_r = 0*768+256 + colortab[ *cr + 0*256 ]; + crb_g = 1*768+256 + colortab[ *cr + 1*256 ] + + colortab[ *cb + 2*256 ]; + cb_b = 2*768+256 + colortab[ *cb + 3*256 ]; + ++cr; ++cb; + + L = *lum++; + *row1++ = (unsigned short)(rgb_2_pix[ L + cr_r ] | + rgb_2_pix[ L + crb_g ] | + rgb_2_pix[ L + cb_b ]); + + L = *lum++; + *row1++ = (unsigned short)(rgb_2_pix[ L + cr_r ] | + rgb_2_pix[ L + crb_g ] | + rgb_2_pix[ L + cb_b ]); + + + /* Now, do second row. */ + + L = *lum2++; + *row2++ = (unsigned short)(rgb_2_pix[ L + cr_r ] | + rgb_2_pix[ L + crb_g ] | + rgb_2_pix[ L + cb_b ]); + + L = *lum2++; + *row2++ = (unsigned short)(rgb_2_pix[ L + cr_r ] | + rgb_2_pix[ L + crb_g ] | + rgb_2_pix[ L + cb_b ]); + } + + /* + * These values are at the start of the next line, (due + * to the ++'s above),but they need to be at the start + * of the line after that. + */ + lum += cols; + lum2 += cols; + row1 += mod; + row2 += mod; + } +} + +static void Color24DitherYV12Mod1X( int *colortab, Uint32 *rgb_2_pix, + unsigned char *lum, unsigned char *cr, + unsigned char *cb, unsigned char *out, + int rows, int cols, int mod ) +{ + unsigned int value; + unsigned char* row1; + unsigned char* row2; + unsigned char* lum2; + int x, y; + int cr_r; + int crb_g; + int cb_b; + int cols_2 = cols / 2; + + row1 = out; + row2 = row1 + cols*3 + mod*3; + lum2 = lum + cols; + + mod += cols + mod; + mod *= 3; + + y = rows / 2; + while( y-- ) + { + x = cols_2; + while( x-- ) + { + register int L; + + cr_r = 0*768+256 + colortab[ *cr + 0*256 ]; + crb_g = 1*768+256 + colortab[ *cr + 1*256 ] + + colortab[ *cb + 2*256 ]; + cb_b = 2*768+256 + colortab[ *cb + 3*256 ]; + ++cr; ++cb; + + L = *lum++; + value = (rgb_2_pix[ L + cr_r ] | + rgb_2_pix[ L + crb_g ] | + rgb_2_pix[ L + cb_b ]); + *row1++ = (value ) & 0xFF; + *row1++ = (value >> 8) & 0xFF; + *row1++ = (value >> 16) & 0xFF; + + L = *lum++; + value = (rgb_2_pix[ L + cr_r ] | + rgb_2_pix[ L + crb_g ] | + rgb_2_pix[ L + cb_b ]); + *row1++ = (value ) & 0xFF; + *row1++ = (value >> 8) & 0xFF; + *row1++ = (value >> 16) & 0xFF; + + + /* Now, do second row. */ + + L = *lum2++; + value = (rgb_2_pix[ L + cr_r ] | + rgb_2_pix[ L + crb_g ] | + rgb_2_pix[ L + cb_b ]); + *row2++ = (value ) & 0xFF; + *row2++ = (value >> 8) & 0xFF; + *row2++ = (value >> 16) & 0xFF; + + L = *lum2++; + value = (rgb_2_pix[ L + cr_r ] | + rgb_2_pix[ L + crb_g ] | + rgb_2_pix[ L + cb_b ]); + *row2++ = (value ) & 0xFF; + *row2++ = (value >> 8) & 0xFF; + *row2++ = (value >> 16) & 0xFF; + } + + /* + * These values are at the start of the next line, (due + * to the ++'s above),but they need to be at the start + * of the line after that. + */ + lum += cols; + lum2 += cols; + row1 += mod; + row2 += mod; + } +} + +static void Color32DitherYV12Mod1X( int *colortab, Uint32 *rgb_2_pix, + unsigned char *lum, unsigned char *cr, + unsigned char *cb, unsigned char *out, + int rows, int cols, int mod ) +{ + unsigned int* row1; + unsigned int* row2; + unsigned char* lum2; + int x, y; + int cr_r; + int crb_g; + int cb_b; + int cols_2 = cols / 2; + + row1 = (unsigned int*) out; + row2 = row1 + cols + mod; + lum2 = lum + cols; + + mod += cols + mod; + + y = rows / 2; + while( y-- ) + { + x = cols_2; + while( x-- ) + { + register int L; + + cr_r = 0*768+256 + colortab[ *cr + 0*256 ]; + crb_g = 1*768+256 + colortab[ *cr + 1*256 ] + + colortab[ *cb + 2*256 ]; + cb_b = 2*768+256 + colortab[ *cb + 3*256 ]; + ++cr; ++cb; + + L = *lum++; + *row1++ = (rgb_2_pix[ L + cr_r ] | + rgb_2_pix[ L + crb_g ] | + rgb_2_pix[ L + cb_b ]); + + L = *lum++; + *row1++ = (rgb_2_pix[ L + cr_r ] | + rgb_2_pix[ L + crb_g ] | + rgb_2_pix[ L + cb_b ]); + + + /* Now, do second row. */ + + L = *lum2++; + *row2++ = (rgb_2_pix[ L + cr_r ] | + rgb_2_pix[ L + crb_g ] | + rgb_2_pix[ L + cb_b ]); + + L = *lum2++; + *row2++ = (rgb_2_pix[ L + cr_r ] | + rgb_2_pix[ L + crb_g ] | + rgb_2_pix[ L + cb_b ]); + } + + /* + * These values are at the start of the next line, (due + * to the ++'s above),but they need to be at the start + * of the line after that. + */ + lum += cols; + lum2 += cols; + row1 += mod; + row2 += mod; + } +} + +/* + * In this function I make use of a nasty trick. The tables have the lower + * 16 bits replicated in the upper 16. This means I can write ints and get + * the horisontal doubling for free (almost). + */ +static void Color16DitherYV12Mod2X( int *colortab, Uint32 *rgb_2_pix, + unsigned char *lum, unsigned char *cr, + unsigned char *cb, unsigned char *out, + int rows, int cols, int mod ) +{ + unsigned int* row1 = (unsigned int*) out; + const int next_row = cols+(mod/2); + unsigned int* row2 = row1 + 2*next_row; + unsigned char* lum2; + int x, y; + int cr_r; + int crb_g; + int cb_b; + int cols_2 = cols / 2; + + lum2 = lum + cols; + + mod = (next_row * 3) + (mod/2); + + y = rows / 2; + while( y-- ) + { + x = cols_2; + while( x-- ) + { + register int L; + + cr_r = 0*768+256 + colortab[ *cr + 0*256 ]; + crb_g = 1*768+256 + colortab[ *cr + 1*256 ] + + colortab[ *cb + 2*256 ]; + cb_b = 2*768+256 + colortab[ *cb + 3*256 ]; + ++cr; ++cb; + + L = *lum++; + row1[0] = row1[next_row] = (rgb_2_pix[ L + cr_r ] | + rgb_2_pix[ L + crb_g ] | + rgb_2_pix[ L + cb_b ]); + row1++; + + L = *lum++; + row1[0] = row1[next_row] = (rgb_2_pix[ L + cr_r ] | + rgb_2_pix[ L + crb_g ] | + rgb_2_pix[ L + cb_b ]); + row1++; + + + /* Now, do second row. */ + + L = *lum2++; + row2[0] = row2[next_row] = (rgb_2_pix[ L + cr_r ] | + rgb_2_pix[ L + crb_g ] | + rgb_2_pix[ L + cb_b ]); + row2++; + + L = *lum2++; + row2[0] = row2[next_row] = (rgb_2_pix[ L + cr_r ] | + rgb_2_pix[ L + crb_g ] | + rgb_2_pix[ L + cb_b ]); + row2++; + } + + /* + * These values are at the start of the next line, (due + * to the ++'s above),but they need to be at the start + * of the line after that. + */ + lum += cols; + lum2 += cols; + row1 += mod; + row2 += mod; + } +} + +static void Color24DitherYV12Mod2X( int *colortab, Uint32 *rgb_2_pix, + unsigned char *lum, unsigned char *cr, + unsigned char *cb, unsigned char *out, + int rows, int cols, int mod ) +{ + unsigned int value; + unsigned char* row1 = out; + const int next_row = (cols*2 + mod) * 3; + unsigned char* row2 = row1 + 2*next_row; + unsigned char* lum2; + int x, y; + int cr_r; + int crb_g; + int cb_b; + int cols_2 = cols / 2; + + lum2 = lum + cols; + + mod = next_row*3 + mod*3; + + y = rows / 2; + while( y-- ) + { + x = cols_2; + while( x-- ) + { + register int L; + + cr_r = 0*768+256 + colortab[ *cr + 0*256 ]; + crb_g = 1*768+256 + colortab[ *cr + 1*256 ] + + colortab[ *cb + 2*256 ]; + cb_b = 2*768+256 + colortab[ *cb + 3*256 ]; + ++cr; ++cb; + + L = *lum++; + value = (rgb_2_pix[ L + cr_r ] | + rgb_2_pix[ L + crb_g ] | + rgb_2_pix[ L + cb_b ]); + row1[0+0] = row1[3+0] = row1[next_row+0] = row1[next_row+3+0] = + (value ) & 0xFF; + row1[0+1] = row1[3+1] = row1[next_row+1] = row1[next_row+3+1] = + (value >> 8) & 0xFF; + row1[0+2] = row1[3+2] = row1[next_row+2] = row1[next_row+3+2] = + (value >> 16) & 0xFF; + row1 += 2*3; + + L = *lum++; + value = (rgb_2_pix[ L + cr_r ] | + rgb_2_pix[ L + crb_g ] | + rgb_2_pix[ L + cb_b ]); + row1[0+0] = row1[3+0] = row1[next_row+0] = row1[next_row+3+0] = + (value ) & 0xFF; + row1[0+1] = row1[3+1] = row1[next_row+1] = row1[next_row+3+1] = + (value >> 8) & 0xFF; + row1[0+2] = row1[3+2] = row1[next_row+2] = row1[next_row+3+2] = + (value >> 16) & 0xFF; + row1 += 2*3; + + + /* Now, do second row. */ + + L = *lum2++; + value = (rgb_2_pix[ L + cr_r ] | + rgb_2_pix[ L + crb_g ] | + rgb_2_pix[ L + cb_b ]); + row2[0+0] = row2[3+0] = row2[next_row+0] = row2[next_row+3+0] = + (value ) & 0xFF; + row2[0+1] = row2[3+1] = row2[next_row+1] = row2[next_row+3+1] = + (value >> 8) & 0xFF; + row2[0+2] = row2[3+2] = row2[next_row+2] = row2[next_row+3+2] = + (value >> 16) & 0xFF; + row2 += 2*3; + + L = *lum2++; + value = (rgb_2_pix[ L + cr_r ] | + rgb_2_pix[ L + crb_g ] | + rgb_2_pix[ L + cb_b ]); + row2[0+0] = row2[3+0] = row2[next_row+0] = row2[next_row+3+0] = + (value ) & 0xFF; + row2[0+1] = row2[3+1] = row2[next_row+1] = row2[next_row+3+1] = + (value >> 8) & 0xFF; + row2[0+2] = row2[3+2] = row2[next_row+2] = row2[next_row+3+2] = + (value >> 16) & 0xFF; + row2 += 2*3; + } + + /* + * These values are at the start of the next line, (due + * to the ++'s above),but they need to be at the start + * of the line after that. + */ + lum += cols; + lum2 += cols; + row1 += mod; + row2 += mod; + } +} + +static void Color32DitherYV12Mod2X( int *colortab, Uint32 *rgb_2_pix, + unsigned char *lum, unsigned char *cr, + unsigned char *cb, unsigned char *out, + int rows, int cols, int mod ) +{ + unsigned int* row1 = (unsigned int*) out; + const int next_row = cols*2+mod; + unsigned int* row2 = row1 + 2*next_row; + unsigned char* lum2; + int x, y; + int cr_r; + int crb_g; + int cb_b; + int cols_2 = cols / 2; + + lum2 = lum + cols; + + mod = (next_row * 3) + mod; + + y = rows / 2; + while( y-- ) + { + x = cols_2; + while( x-- ) + { + register int L; + + cr_r = 0*768+256 + colortab[ *cr + 0*256 ]; + crb_g = 1*768+256 + colortab[ *cr + 1*256 ] + + colortab[ *cb + 2*256 ]; + cb_b = 2*768+256 + colortab[ *cb + 3*256 ]; + ++cr; ++cb; + + L = *lum++; + row1[0] = row1[1] = row1[next_row] = row1[next_row+1] = + (rgb_2_pix[ L + cr_r ] | + rgb_2_pix[ L + crb_g ] | + rgb_2_pix[ L + cb_b ]); + row1 += 2; + + L = *lum++; + row1[0] = row1[1] = row1[next_row] = row1[next_row+1] = + (rgb_2_pix[ L + cr_r ] | + rgb_2_pix[ L + crb_g ] | + rgb_2_pix[ L + cb_b ]); + row1 += 2; + + + /* Now, do second row. */ + + L = *lum2++; + row2[0] = row2[1] = row2[next_row] = row2[next_row+1] = + (rgb_2_pix[ L + cr_r ] | + rgb_2_pix[ L + crb_g ] | + rgb_2_pix[ L + cb_b ]); + row2 += 2; + + L = *lum2++; + row2[0] = row2[1] = row2[next_row] = row2[next_row+1] = + (rgb_2_pix[ L + cr_r ] | + rgb_2_pix[ L + crb_g ] | + rgb_2_pix[ L + cb_b ]); + row2 += 2; + } + + /* + * These values are at the start of the next line, (due + * to the ++'s above),but they need to be at the start + * of the line after that. + */ + lum += cols; + lum2 += cols; + row1 += mod; + row2 += mod; + } +} + +static void Color16DitherYUY2Mod1X( int *colortab, Uint32 *rgb_2_pix, + unsigned char *lum, unsigned char *cr, + unsigned char *cb, unsigned char *out, + int rows, int cols, int mod ) +{ + unsigned short* row; + int x, y; + int cr_r; + int crb_g; + int cb_b; + int cols_2 = cols / 2; + + row = (unsigned short*) out; + + y = rows; + while( y-- ) + { + x = cols_2; + while( x-- ) + { + register int L; + + cr_r = 0*768+256 + colortab[ *cr + 0*256 ]; + crb_g = 1*768+256 + colortab[ *cr + 1*256 ] + + colortab[ *cb + 2*256 ]; + cb_b = 2*768+256 + colortab[ *cb + 3*256 ]; + cr += 4; cb += 4; + + L = *lum; lum += 2; + *row++ = (unsigned short)(rgb_2_pix[ L + cr_r ] | + rgb_2_pix[ L + crb_g ] | + rgb_2_pix[ L + cb_b ]); + + L = *lum; lum += 2; + *row++ = (unsigned short)(rgb_2_pix[ L + cr_r ] | + rgb_2_pix[ L + crb_g ] | + rgb_2_pix[ L + cb_b ]); + + } + + row += mod; + } +} + +static void Color24DitherYUY2Mod1X( int *colortab, Uint32 *rgb_2_pix, + unsigned char *lum, unsigned char *cr, + unsigned char *cb, unsigned char *out, + int rows, int cols, int mod ) +{ + unsigned int value; + unsigned char* row; + int x, y; + int cr_r; + int crb_g; + int cb_b; + int cols_2 = cols / 2; + + row = (unsigned char*) out; + mod *= 3; + y = rows; + while( y-- ) + { + x = cols_2; + while( x-- ) + { + register int L; + + cr_r = 0*768+256 + colortab[ *cr + 0*256 ]; + crb_g = 1*768+256 + colortab[ *cr + 1*256 ] + + colortab[ *cb + 2*256 ]; + cb_b = 2*768+256 + colortab[ *cb + 3*256 ]; + cr += 4; cb += 4; + + L = *lum; lum += 2; + value = (rgb_2_pix[ L + cr_r ] | + rgb_2_pix[ L + crb_g ] | + rgb_2_pix[ L + cb_b ]); + *row++ = (value ) & 0xFF; + *row++ = (value >> 8) & 0xFF; + *row++ = (value >> 16) & 0xFF; + + L = *lum; lum += 2; + value = (rgb_2_pix[ L + cr_r ] | + rgb_2_pix[ L + crb_g ] | + rgb_2_pix[ L + cb_b ]); + *row++ = (value ) & 0xFF; + *row++ = (value >> 8) & 0xFF; + *row++ = (value >> 16) & 0xFF; + + } + row += mod; + } +} + +static void Color32DitherYUY2Mod1X( int *colortab, Uint32 *rgb_2_pix, + unsigned char *lum, unsigned char *cr, + unsigned char *cb, unsigned char *out, + int rows, int cols, int mod ) +{ + unsigned int* row; + int x, y; + int cr_r; + int crb_g; + int cb_b; + int cols_2 = cols / 2; + + row = (unsigned int*) out; + y = rows; + while( y-- ) + { + x = cols_2; + while( x-- ) + { + register int L; + + cr_r = 0*768+256 + colortab[ *cr + 0*256 ]; + crb_g = 1*768+256 + colortab[ *cr + 1*256 ] + + colortab[ *cb + 2*256 ]; + cb_b = 2*768+256 + colortab[ *cb + 3*256 ]; + cr += 4; cb += 4; + + L = *lum; lum += 2; + *row++ = (rgb_2_pix[ L + cr_r ] | + rgb_2_pix[ L + crb_g ] | + rgb_2_pix[ L + cb_b ]); + + L = *lum; lum += 2; + *row++ = (rgb_2_pix[ L + cr_r ] | + rgb_2_pix[ L + crb_g ] | + rgb_2_pix[ L + cb_b ]); + + + } + row += mod; + } +} + +/* + * In this function I make use of a nasty trick. The tables have the lower + * 16 bits replicated in the upper 16. This means I can write ints and get + * the horisontal doubling for free (almost). + */ +static void Color16DitherYUY2Mod2X( int *colortab, Uint32 *rgb_2_pix, + unsigned char *lum, unsigned char *cr, + unsigned char *cb, unsigned char *out, + int rows, int cols, int mod ) +{ + unsigned int* row = (unsigned int*) out; + const int next_row = cols+(mod/2); + int x, y; + int cr_r; + int crb_g; + int cb_b; + int cols_2 = cols / 2; + + y = rows; + while( y-- ) + { + x = cols_2; + while( x-- ) + { + register int L; + + cr_r = 0*768+256 + colortab[ *cr + 0*256 ]; + crb_g = 1*768+256 + colortab[ *cr + 1*256 ] + + colortab[ *cb + 2*256 ]; + cb_b = 2*768+256 + colortab[ *cb + 3*256 ]; + cr += 4; cb += 4; + + L = *lum; lum += 2; + row[0] = row[next_row] = (rgb_2_pix[ L + cr_r ] | + rgb_2_pix[ L + crb_g ] | + rgb_2_pix[ L + cb_b ]); + row++; + + L = *lum; lum += 2; + row[0] = row[next_row] = (rgb_2_pix[ L + cr_r ] | + rgb_2_pix[ L + crb_g ] | + rgb_2_pix[ L + cb_b ]); + row++; + + } + row += next_row; + } +} + +static void Color24DitherYUY2Mod2X( int *colortab, Uint32 *rgb_2_pix, + unsigned char *lum, unsigned char *cr, + unsigned char *cb, unsigned char *out, + int rows, int cols, int mod ) +{ + unsigned int value; + unsigned char* row = out; + const int next_row = (cols*2 + mod) * 3; + int x, y; + int cr_r; + int crb_g; + int cb_b; + int cols_2 = cols / 2; + y = rows; + while( y-- ) + { + x = cols_2; + while( x-- ) + { + register int L; + + cr_r = 0*768+256 + colortab[ *cr + 0*256 ]; + crb_g = 1*768+256 + colortab[ *cr + 1*256 ] + + colortab[ *cb + 2*256 ]; + cb_b = 2*768+256 + colortab[ *cb + 3*256 ]; + cr += 4; cb += 4; + + L = *lum; lum += 2; + value = (rgb_2_pix[ L + cr_r ] | + rgb_2_pix[ L + crb_g ] | + rgb_2_pix[ L + cb_b ]); + row[0+0] = row[3+0] = row[next_row+0] = row[next_row+3+0] = + (value ) & 0xFF; + row[0+1] = row[3+1] = row[next_row+1] = row[next_row+3+1] = + (value >> 8) & 0xFF; + row[0+2] = row[3+2] = row[next_row+2] = row[next_row+3+2] = + (value >> 16) & 0xFF; + row += 2*3; + + L = *lum; lum += 2; + value = (rgb_2_pix[ L + cr_r ] | + rgb_2_pix[ L + crb_g ] | + rgb_2_pix[ L + cb_b ]); + row[0+0] = row[3+0] = row[next_row+0] = row[next_row+3+0] = + (value ) & 0xFF; + row[0+1] = row[3+1] = row[next_row+1] = row[next_row+3+1] = + (value >> 8) & 0xFF; + row[0+2] = row[3+2] = row[next_row+2] = row[next_row+3+2] = + (value >> 16) & 0xFF; + row += 2*3; + + } + row += next_row; + } +} + +static void Color32DitherYUY2Mod2X( int *colortab, Uint32 *rgb_2_pix, + unsigned char *lum, unsigned char *cr, + unsigned char *cb, unsigned char *out, + int rows, int cols, int mod ) +{ + unsigned int* row = (unsigned int*) out; + const int next_row = cols*2+mod; + int x, y; + int cr_r; + int crb_g; + int cb_b; + int cols_2 = cols / 2; + mod+=mod; + y = rows; + while( y-- ) + { + x = cols_2; + while( x-- ) + { + register int L; + + cr_r = 0*768+256 + colortab[ *cr + 0*256 ]; + crb_g = 1*768+256 + colortab[ *cr + 1*256 ] + + colortab[ *cb + 2*256 ]; + cb_b = 2*768+256 + colortab[ *cb + 3*256 ]; + cr += 4; cb += 4; + + L = *lum; lum += 2; + row[0] = row[1] = row[next_row] = row[next_row+1] = + (rgb_2_pix[ L + cr_r ] | + rgb_2_pix[ L + crb_g ] | + rgb_2_pix[ L + cb_b ]); + row += 2; + + L = *lum; lum += 2; + row[0] = row[1] = row[next_row] = row[next_row+1] = + (rgb_2_pix[ L + cr_r ] | + rgb_2_pix[ L + crb_g ] | + rgb_2_pix[ L + cb_b ]); + row += 2; + + + } + + row += next_row; + } +} + +/* + * How many 1 bits are there in the Uint32. + * Low performance, do not call often. + */ +static int number_of_bits_set( Uint32 a ) +{ + if(!a) return 0; + if(a & 1) return 1 + number_of_bits_set(a >> 1); + return(number_of_bits_set(a >> 1)); +} + +/* + * How many 0 bits are there at least significant end of Uint32. + * Low performance, do not call often. + */ +static int free_bits_at_bottom( Uint32 a ) +{ + /* assume char is 8 bits */ + if(!a) return sizeof(Uint32) * 8; + if(((Sint32)a) & 1l) return 0; + return 1 + free_bits_at_bottom ( a >> 1); +} + + +SDL_Overlay *SDL_CreateYUV_SW(_THIS, int width, int height, Uint32 format, SDL_Surface *display) +{ + SDL_Overlay *overlay; + struct private_yuvhwdata *swdata; + int *Cr_r_tab; + int *Cr_g_tab; + int *Cb_g_tab; + int *Cb_b_tab; + Uint32 *r_2_pix_alloc; + Uint32 *g_2_pix_alloc; + Uint32 *b_2_pix_alloc; + int i; + int CR, CB; + Uint32 Rmask, Gmask, Bmask; + + /* Only RGB packed pixel conversion supported */ + if ( (display->format->BytesPerPixel != 2) && + (display->format->BytesPerPixel != 3) && + (display->format->BytesPerPixel != 4) ) { + SDL_SetError("Can't use YUV data on non 16/24/32 bit surfaces"); + return(NULL); + } + + /* Verify that we support the format */ + switch (format) { + case SDL_YV12_OVERLAY: + case SDL_IYUV_OVERLAY: + case SDL_YUY2_OVERLAY: + case SDL_UYVY_OVERLAY: + case SDL_YVYU_OVERLAY: + break; + default: + SDL_SetError("Unsupported YUV format"); + return(NULL); + } + + /* Create the overlay structure */ + overlay = (SDL_Overlay *)SDL_malloc(sizeof *overlay); + if ( overlay == NULL ) { + SDL_OutOfMemory(); + return(NULL); + } + SDL_memset(overlay, 0, (sizeof *overlay)); + + /* Fill in the basic members */ + overlay->format = format; + overlay->w = width; + overlay->h = height; + + /* Set up the YUV surface function structure */ + overlay->hwfuncs = &sw_yuvfuncs; + + /* Create the pixel data and lookup tables */ + swdata = (struct private_yuvhwdata *)SDL_malloc(sizeof *swdata); + overlay->hwdata = swdata; + if ( swdata == NULL ) { + SDL_OutOfMemory(); + SDL_FreeYUVOverlay(overlay); + return(NULL); + } + swdata->stretch = NULL; + swdata->display = display; + swdata->pixels = (Uint8 *) SDL_malloc(width*height*2); + swdata->colortab = (int *)SDL_malloc(4*256*sizeof(int)); + Cr_r_tab = &swdata->colortab[0*256]; + Cr_g_tab = &swdata->colortab[1*256]; + Cb_g_tab = &swdata->colortab[2*256]; + Cb_b_tab = &swdata->colortab[3*256]; + swdata->rgb_2_pix = (Uint32 *)SDL_malloc(3*768*sizeof(Uint32)); + r_2_pix_alloc = &swdata->rgb_2_pix[0*768]; + g_2_pix_alloc = &swdata->rgb_2_pix[1*768]; + b_2_pix_alloc = &swdata->rgb_2_pix[2*768]; + if ( ! swdata->pixels || ! swdata->colortab || ! swdata->rgb_2_pix ) { + SDL_OutOfMemory(); + SDL_FreeYUVOverlay(overlay); + return(NULL); + } + + /* Generate the tables for the display surface */ + for (i=0; i<256; i++) { + /* Gamma correction (luminescence table) and chroma correction + would be done here. See the Berkeley mpeg_play sources. + */ + CB = CR = (i-128); + Cr_r_tab[i] = (int) ( (0.419/0.299) * CR); + Cr_g_tab[i] = (int) (-(0.299/0.419) * CR); + Cb_g_tab[i] = (int) (-(0.114/0.331) * CB); + Cb_b_tab[i] = (int) ( (0.587/0.331) * CB); + } + + /* + * Set up entries 0-255 in rgb-to-pixel value tables. + */ + Rmask = display->format->Rmask; + Gmask = display->format->Gmask; + Bmask = display->format->Bmask; + for ( i=0; i<256; ++i ) { + r_2_pix_alloc[i+256] = i >> (8 - number_of_bits_set(Rmask)); + r_2_pix_alloc[i+256] <<= free_bits_at_bottom(Rmask); + g_2_pix_alloc[i+256] = i >> (8 - number_of_bits_set(Gmask)); + g_2_pix_alloc[i+256] <<= free_bits_at_bottom(Gmask); + b_2_pix_alloc[i+256] = i >> (8 - number_of_bits_set(Bmask)); + b_2_pix_alloc[i+256] <<= free_bits_at_bottom(Bmask); + } + + /* + * If we have 16-bit output depth, then we double the value + * in the top word. This means that we can write out both + * pixels in the pixel doubling mode with one op. It is + * harmless in the normal case as storing a 32-bit value + * through a short pointer will lose the top bits anyway. + */ + if( display->format->BytesPerPixel == 2 ) { + for ( i=0; i<256; ++i ) { + r_2_pix_alloc[i+256] |= (r_2_pix_alloc[i+256]) << 16; + g_2_pix_alloc[i+256] |= (g_2_pix_alloc[i+256]) << 16; + b_2_pix_alloc[i+256] |= (b_2_pix_alloc[i+256]) << 16; + } + } + + /* + * Spread out the values we have to the rest of the array so that + * we do not need to check for overflow. + */ + for ( i=0; i<256; ++i ) { + r_2_pix_alloc[i] = r_2_pix_alloc[256]; + r_2_pix_alloc[i+512] = r_2_pix_alloc[511]; + g_2_pix_alloc[i] = g_2_pix_alloc[256]; + g_2_pix_alloc[i+512] = g_2_pix_alloc[511]; + b_2_pix_alloc[i] = b_2_pix_alloc[256]; + b_2_pix_alloc[i+512] = b_2_pix_alloc[511]; + } + + /* You have chosen wisely... */ + switch (format) { + case SDL_YV12_OVERLAY: + case SDL_IYUV_OVERLAY: + if ( display->format->BytesPerPixel == 2 ) { +#if (__GNUC__ > 2) && defined(__i386__) && __OPTIMIZE__ && SDL_ASSEMBLY_ROUTINES + /* inline assembly functions */ + if ( SDL_HasMMX() && (Rmask == 0xF800) && + (Gmask == 0x07E0) && + (Bmask == 0x001F) && + (width & 15) == 0) { +/*printf("Using MMX 16-bit 565 dither\n");*/ + swdata->Display1X = Color565DitherYV12MMX1X; + } else { +/*printf("Using C 16-bit dither\n");*/ + swdata->Display1X = Color16DitherYV12Mod1X; + } +#else + swdata->Display1X = Color16DitherYV12Mod1X; +#endif + swdata->Display2X = Color16DitherYV12Mod2X; + } + if ( display->format->BytesPerPixel == 3 ) { + swdata->Display1X = Color24DitherYV12Mod1X; + swdata->Display2X = Color24DitherYV12Mod2X; + } + if ( display->format->BytesPerPixel == 4 ) { +#if (__GNUC__ > 2) && defined(__i386__) && __OPTIMIZE__ && SDL_ASSEMBLY_ROUTINES + /* inline assembly functions */ + if ( SDL_HasMMX() && (Rmask == 0x00FF0000) && + (Gmask == 0x0000FF00) && + (Bmask == 0x000000FF) && + (width & 15) == 0) { +/*printf("Using MMX 32-bit dither\n");*/ + swdata->Display1X = ColorRGBDitherYV12MMX1X; + } else { +/*printf("Using C 32-bit dither\n");*/ + swdata->Display1X = Color32DitherYV12Mod1X; + } +#else + swdata->Display1X = Color32DitherYV12Mod1X; +#endif + swdata->Display2X = Color32DitherYV12Mod2X; + } + break; + case SDL_YUY2_OVERLAY: + case SDL_UYVY_OVERLAY: + case SDL_YVYU_OVERLAY: + if ( display->format->BytesPerPixel == 2 ) { + swdata->Display1X = Color16DitherYUY2Mod1X; + swdata->Display2X = Color16DitherYUY2Mod2X; + } + if ( display->format->BytesPerPixel == 3 ) { + swdata->Display1X = Color24DitherYUY2Mod1X; + swdata->Display2X = Color24DitherYUY2Mod2X; + } + if ( display->format->BytesPerPixel == 4 ) { + swdata->Display1X = Color32DitherYUY2Mod1X; + swdata->Display2X = Color32DitherYUY2Mod2X; + } + break; + default: + /* We should never get here (caught above) */ + break; + } + + /* Find the pitch and offset values for the overlay */ + overlay->pitches = swdata->pitches; + overlay->pixels = swdata->planes; + switch (format) { + case SDL_YV12_OVERLAY: + case SDL_IYUV_OVERLAY: + overlay->pitches[0] = overlay->w; + overlay->pitches[1] = overlay->pitches[0] / 2; + overlay->pitches[2] = overlay->pitches[0] / 2; + overlay->pixels[0] = swdata->pixels; + overlay->pixels[1] = overlay->pixels[0] + + overlay->pitches[0] * overlay->h; + overlay->pixels[2] = overlay->pixels[1] + + overlay->pitches[1] * overlay->h / 2; + overlay->planes = 3; + break; + case SDL_YUY2_OVERLAY: + case SDL_UYVY_OVERLAY: + case SDL_YVYU_OVERLAY: + overlay->pitches[0] = overlay->w*2; + overlay->pixels[0] = swdata->pixels; + overlay->planes = 1; + break; + default: + /* We should never get here (caught above) */ + break; + } + + /* We're all done.. */ + return(overlay); +} + +int SDL_LockYUV_SW(_THIS, SDL_Overlay *overlay) +{ + return(0); +} + +void SDL_UnlockYUV_SW(_THIS, SDL_Overlay *overlay) +{ + return; +} + +int SDL_DisplayYUV_SW(_THIS, SDL_Overlay *overlay, SDL_Rect *src, SDL_Rect *dst) +{ + struct private_yuvhwdata *swdata; + int stretch; + int scale_2x; + SDL_Surface *display; + Uint8 *lum, *Cr, *Cb; + Uint8 *dstp; + int mod; + + swdata = overlay->hwdata; + stretch = 0; + scale_2x = 0; + if ( src->x || src->y || src->w < overlay->w || src->h < overlay->h ) { + /* The source rectangle has been clipped. + Using a scratch surface is easier than adding clipped + source support to all the blitters, plus that would + slow them down in the general unclipped case. + */ + stretch = 1; + } else if ( (src->w != dst->w) || (src->h != dst->h) ) { + if ( (dst->w == 2*src->w) && + (dst->h == 2*src->h) ) { + scale_2x = 1; + } else { + stretch = 1; + } + } + if ( stretch ) { + if ( ! swdata->stretch ) { + display = swdata->display; + swdata->stretch = SDL_CreateRGBSurface( + SDL_SWSURFACE, + overlay->w, overlay->h, + display->format->BitsPerPixel, + display->format->Rmask, + display->format->Gmask, + display->format->Bmask, 0); + if ( ! swdata->stretch ) { + return(-1); + } + } + display = swdata->stretch; + } else { + display = swdata->display; + } + switch (overlay->format) { + case SDL_YV12_OVERLAY: + lum = overlay->pixels[0]; + Cr = overlay->pixels[1]; + Cb = overlay->pixels[2]; + break; + case SDL_IYUV_OVERLAY: + lum = overlay->pixels[0]; + Cr = overlay->pixels[2]; + Cb = overlay->pixels[1]; + break; + case SDL_YUY2_OVERLAY: + lum = overlay->pixels[0]; + Cr = lum + 3; + Cb = lum + 1; + break; + case SDL_UYVY_OVERLAY: + lum = overlay->pixels[0]+1; + Cr = lum + 1; + Cb = lum - 1; + break; + case SDL_YVYU_OVERLAY: + lum = overlay->pixels[0]; + Cr = lum + 1; + Cb = lum + 3; + break; + default: + SDL_SetError("Unsupported YUV format in blit"); + return(-1); + } + if ( SDL_MUSTLOCK(display) ) { + if ( SDL_LockSurface(display) < 0 ) { + return(-1); + } + } + if ( stretch ) { + dstp = (Uint8 *)swdata->stretch->pixels; + } else { + dstp = (Uint8 *)display->pixels + + dst->x * display->format->BytesPerPixel + + dst->y * display->pitch; + } + mod = (display->pitch / display->format->BytesPerPixel); + + if ( scale_2x ) { + mod -= (overlay->w * 2); + swdata->Display2X(swdata->colortab, swdata->rgb_2_pix, + lum, Cr, Cb, dstp, overlay->h, overlay->w, mod); + } else { + mod -= overlay->w; + swdata->Display1X(swdata->colortab, swdata->rgb_2_pix, + lum, Cr, Cb, dstp, overlay->h, overlay->w, mod); + } + if ( SDL_MUSTLOCK(display) ) { + SDL_UnlockSurface(display); + } + if ( stretch ) { + display = swdata->display; + SDL_SoftStretch(swdata->stretch, src, display, dst); + } + SDL_UpdateRects(display, 1, dst); + + return(0); +} + +void SDL_FreeYUV_SW(_THIS, SDL_Overlay *overlay) +{ + struct private_yuvhwdata *swdata; + + swdata = overlay->hwdata; + if ( swdata ) { + if ( swdata->stretch ) { + SDL_FreeSurface(swdata->stretch); + } + if ( swdata->pixels ) { + SDL_free(swdata->pixels); + } + if ( swdata->colortab ) { + SDL_free(swdata->colortab); + } + if ( swdata->rgb_2_pix ) { + SDL_free(swdata->rgb_2_pix); + } + SDL_free(swdata); + overlay->hwdata = NULL; + } +} diff --git a/3rdparty/SDL/src/video/SDL_yuv_sw_c.h b/3rdparty/SDL/src/video/SDL_yuv_sw_c.h new file mode 100644 index 0000000..5aea3a5 --- /dev/null +++ b/3rdparty/SDL/src/video/SDL_yuv_sw_c.h @@ -0,0 +1,37 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#include "SDL_video.h" +#include "SDL_sysvideo.h" + +/* This is the software implementation of the YUV video overlay support */ + +extern SDL_Overlay *SDL_CreateYUV_SW(_THIS, int width, int height, Uint32 format, SDL_Surface *display); + +extern int SDL_LockYUV_SW(_THIS, SDL_Overlay *overlay); + +extern void SDL_UnlockYUV_SW(_THIS, SDL_Overlay *overlay); + +extern int SDL_DisplayYUV_SW(_THIS, SDL_Overlay *overlay, SDL_Rect *src, SDL_Rect *dst); + +extern void SDL_FreeYUV_SW(_THIS, SDL_Overlay *overlay); diff --git a/3rdparty/SDL/src/video/SDL_yuvfuncs.h b/3rdparty/SDL/src/video/SDL_yuvfuncs.h new file mode 100644 index 0000000..cb496b6 --- /dev/null +++ b/3rdparty/SDL/src/video/SDL_yuvfuncs.h @@ -0,0 +1,37 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* This is the definition of the YUV video surface function structure */ + +#include "SDL_video.h" +#include "SDL_sysvideo.h" + +#ifndef _THIS +#define _THIS SDL_VideoDevice *_this +#endif +struct private_yuvhwfuncs { + int (*Lock)(_THIS, SDL_Overlay *overlay); + void (*Unlock)(_THIS, SDL_Overlay *overlay); + int (*Display)(_THIS, SDL_Overlay *overlay, SDL_Rect *src, SDL_Rect *dst); + void (*FreeHW)(_THIS, SDL_Overlay *overlay); +}; diff --git a/3rdparty/SDL/src/video/Xext/README b/3rdparty/SDL/src/video/Xext/README new file mode 100644 index 0000000..a16ea68 --- /dev/null +++ b/3rdparty/SDL/src/video/Xext/README @@ -0,0 +1,10 @@ + +The reason these libraries are built outside of the standard XFree86 +tree is so that they can be linked as shared object code directly into +SDL without causing any symbol collisions with code in the application. + +You can't link static library code into shared libraries on non-x86 +Linux platforms. Since these libraries haven't become standard yet, +we'll just include them directly. + +These sources are synchronized with XFree86 4.2.1 diff --git a/3rdparty/SDL/src/video/Xext/XME/xme.c b/3rdparty/SDL/src/video/Xext/XME/xme.c new file mode 100644 index 0000000..2cead35 --- /dev/null +++ b/3rdparty/SDL/src/video/Xext/XME/xme.c @@ -0,0 +1,410 @@ +/* + * Copyright 1993-2001 by Xi Graphics, Inc. + * All Rights Reserved. + * + * Please see the LICENSE file accompanying this distribution for licensing + * information. + * + * Please send any bug fixes and modifications to src@xig.com. + * + * $XiGId: xme.c,v 1.2 2001/11/30 21:56:59 jon Exp $ + * + */ + +#define NEED_EVENTS +#define NEED_REPLIES + +/* Apparently some X11 systems can't include this multiple times... */ +#ifndef SDL_INCLUDED_XLIBINT_H +#define SDL_INCLUDED_XLIBINT_H 1 +#include <X11/Xlibint.h> +#endif + +#include <X11/Xthreads.h> +#include <X11/Xmd.h> +#include <X11/Xproto.h> +#include "../extensions/Xext.h" +#include "../extensions/extutil.h" + +/*****************************************************************************/ + + +#define XIGMISC_PROTOCOL_NAME "XiG-SUNDRY-NONSTANDARD" +#define XIGMISC_MAJOR_VERSION 2 +#define XIGMISC_MINOR_VERSION 0 + +#define XiGMiscNumberEvents 0 + +#define X_XiGMiscQueryVersion 0 +#define X_XiGMiscQueryViews 1 +#define X_XiGMiscQueryResolutions 2 +#define X_XiGMiscChangeResolution 3 +#define X_XiGMiscFullScreen 4 + +#define sz_xXiGMiscQueryVersionReq 8 +#define sz_xXiGMiscQueryViewsReq 8 +#define sz_xXiGMiscQueryResolutionsReq 8 +#define sz_xXiGMiscChangeResolutionReq 16 +#define sz_xXiGMiscFullScreenReq 16 + +#define sz_xXiGMiscQueryVersionReply 32 +#define sz_xXiGMiscQueryViewsReply 32 +#define sz_xXiGMiscQueryResolutionsReply 32 +#define sz_xXiGMiscQueryFullScreenReply 32 + +/*******************************************************************/ + +typedef struct { + CARD8 reqType; /* always codes->major_opcode */ + CARD8 xigmiscReqType; /* always X_XiGMiscQueryVersion */ + CARD16 length; + CARD16 major; + CARD16 minor; +} xXiGMiscQueryVersionReq; + +typedef struct { + CARD8 reqType; /* always codes->major_opcode */ + CARD8 xigmiscReqType; /* always X_XiGMiscQueryViews */ + CARD16 length; + CARD8 screen; + CARD8 pad0; + CARD16 pad1; +} xXiGMiscQueryViewsReq; + +typedef struct { + CARD8 reqType; /* always codes->major_opcode */ + CARD8 xigmiscReqType; /* always X_XiGMiscQueryResolutions */ + CARD16 length; + CARD8 screen; + CARD8 view; + CARD16 pad0; +} xXiGMiscQueryResolutionsReq; + +typedef struct { + CARD8 reqType; /* always codes->major_opcode */ + CARD8 xigmiscReqType; /* always X_XiGMiscChangeResolution */ + CARD16 length; + CARD8 screen; + CARD8 view; + CARD16 pad0; + CARD16 width; + CARD16 height; + INT32 refresh; +} xXiGMiscChangeResolutionReq; + +typedef struct { + CARD8 reqType; /* always codes->major_opcode */ + CARD8 xigmiscReqType; /* always X_XiGMiscFullScreen */ + CARD16 length; + CARD8 screen; + CARD8 pad0; + CARD16 pad1; + CARD32 window; + CARD32 cmap; +} xXiGMiscFullScreenReq; + +/*******************************************************************/ + +typedef struct { + BYTE type; /* X_Reply */ + CARD8 pad0; + CARD16 sequenceNumber; + CARD32 length; + CARD16 major; + CARD16 minor; + CARD32 pad1; + CARD32 pad2; + CARD32 pad3; + CARD32 pad4; + CARD32 pad5; +} xXiGMiscQueryVersionReply; + +typedef struct { + BYTE type; /* X_Reply */ + CARD8 pad0; + CARD16 sequenceNumber; + CARD32 length; + CARD32 nviews; + CARD32 pad1; + CARD32 pad2; + CARD32 pad3; + CARD32 pad4; + CARD32 pad5; +} xXiGMiscQueryViewsReply; + +typedef struct { + BYTE type; /* X_Reply */ + CARD8 pad0; + CARD16 sequenceNumber; + CARD32 length; + CARD16 active; + CARD16 nresolutions; + CARD32 pad1; + CARD32 pad2; + CARD32 pad3; + CARD32 pad4; + CARD32 pad5; +} xXiGMiscQueryResolutionsReply; + +typedef struct { + BYTE type; /* X_Reply */ + BOOL success; + CARD16 sequenceNumber; + CARD32 length; + CARD32 pad1; + CARD32 pad2; + CARD32 pad3; + CARD32 pad4; + CARD32 pad5; + CARD32 pad6; +} xXiGMiscFullScreenReply; + +/*******************************************************************/ + +typedef struct { + INT16 x; + INT16 y; + CARD16 w; + CARD16 h; +} XiGMiscViewInfo; + +typedef struct { + CARD16 width; + CARD16 height; + INT32 refresh; +} XiGMiscResolutionInfo; + +/*****************************************************************************/ + +static XExtensionInfo *xigmisc_info = NULL; +static char *xigmisc_extension_name = XIGMISC_PROTOCOL_NAME; + +#define XiGMiscCheckExtension(dpy,i,val) \ + XextCheckExtension (dpy, i, xigmisc_extension_name, val) +#define XiGMiscSimpleCheckExtension(dpy,i) \ + XextSimpleCheckExtension (dpy, i, xigmisc_extension_name) + +#if defined(__STDC__) && !defined(UNIXCPP) +#define XiGMiscGetReq(name,req,info) GetReq (name, req); \ + req->reqType = info->codes->major_opcode; \ + req->xigmiscReqType = X_##name; + +#define XiGMiscGetReqExtra(name,n,req,info) GetReqExtra (name, n, req); \ + req->reqType = info->codes->major_opcode; \ + req->xigmicReqType = X_##name; +#else +#define XiGMiscGetReq(name,req,info) GetReq (name, req); \ + req->reqType = info->codes->major_opcode; \ + req->xigmiscReqType = X_/**/name; +#define XiGMiscGetReqExtra(name,n,req,info) GetReqExtra (name, n, req); \ + req->reqType = info->codes->major_opcode; \ + req->xigmiscReqType = X_/**/name; +#endif + + + +/* + * find_display - locate the display info block + */ +static int XiGMiscCloseDisplay(); + +static XExtensionHooks xigmisc_extension_hooks = { + NULL, /* create_gc */ + NULL, /* copy_gc */ + NULL, /* flush_gc */ + NULL, /* free_gc */ + NULL, /* create_font */ + NULL, /* free_font */ + XiGMiscCloseDisplay, /* close_display */ + NULL, /* wire_to_event */ + NULL, /* event_to_wire */ + NULL, /* error */ + NULL, /* error_string */ +}; + + +static XEXT_GENERATE_CLOSE_DISPLAY (XiGMiscCloseDisplay, xigmisc_info) + +static XEXT_GENERATE_FIND_DISPLAY (XiGMiscFindDisplay, xigmisc_info, + xigmisc_extension_name, + &xigmisc_extension_hooks, XiGMiscNumberEvents, NULL) + + +/*****************************************************************************/ + +Bool XiGMiscQueryVersion(Display *dpy, int *major, int *minor) +{ + int opcode, event, error; + xXiGMiscQueryVersionReq *req; + xXiGMiscQueryVersionReply rep; + XExtDisplayInfo *info = XiGMiscFindDisplay(dpy); + + if (!XQueryExtension(dpy, XIGMISC_PROTOCOL_NAME, &opcode, &event, &error)) + return xFalse; + + XiGMiscCheckExtension(dpy, info, xFalse); + + LockDisplay (dpy); + XiGMiscGetReq (XiGMiscQueryVersion, req, info); + + req->major = XIGMISC_MAJOR_VERSION; + req->minor = XIGMISC_MINOR_VERSION; + + if (!_XReply (dpy, (xReply *)&rep, 0, xTrue)) { + UnlockDisplay(dpy); + SyncHandle(); + return xFalse; + } + + *major = rep.major; + *minor = rep.minor; + UnlockDisplay(dpy); + SyncHandle(); + + return xTrue; +} + +int XiGMiscQueryViews(Display *dpy, int screen, XiGMiscViewInfo **pviews) +{ + int n, size; + XiGMiscViewInfo *views; + xXiGMiscQueryViewsReq *req; + xXiGMiscQueryViewsReply rep; + XExtDisplayInfo *info = XiGMiscFindDisplay(dpy); + XiGMiscCheckExtension(dpy, info, 0); + + LockDisplay (dpy); + XiGMiscGetReq (XiGMiscQueryViews, req, info); + req->screen = screen; + + if (!_XReply (dpy, (xReply *)&rep, 0, xFalse)) { + UnlockDisplay(dpy); + SyncHandle(); + return 0; + } + + n = rep.nviews; + + if (n > 0) { + size = sizeof(XiGMiscViewInfo) * n; + views = (XiGMiscViewInfo*)Xmalloc(size); + if (!views) { + _XEatData(dpy, (unsigned long)size); + UnlockDisplay(dpy); + SyncHandle(); + return 0; + } + + _XReadPad(dpy, (void*)views, size); + + *pviews = views; + } + + UnlockDisplay(dpy); + SyncHandle(); + + return n; +} + +int XiGMiscQueryResolutions(Display *dpy, int screen, int view, int *pactive, XiGMiscResolutionInfo **presolutions) +{ + int n, size; + XiGMiscResolutionInfo *resolutions; + xXiGMiscQueryResolutionsReq *req; + xXiGMiscQueryResolutionsReply rep; + XExtDisplayInfo *info = XiGMiscFindDisplay(dpy); + XiGMiscCheckExtension(dpy, info, 0); + + LockDisplay (dpy); + XiGMiscGetReq (XiGMiscQueryResolutions, req, info); + req->screen = screen; + req->view = view; + + if (!_XReply (dpy, (xReply *)&rep, 0, xFalse)) { + UnlockDisplay(dpy); + SyncHandle(); + return 0; + } + + n = rep.nresolutions; + + if (n > 0) { + size = sizeof(XiGMiscResolutionInfo) * n; + resolutions = (XiGMiscResolutionInfo*)Xmalloc(size); + if (!resolutions) { + _XEatData(dpy, (unsigned long)size); + UnlockDisplay(dpy); + SyncHandle(); + return 0; + } + + _XReadPad(dpy, (void*)resolutions, size); + + *presolutions = resolutions; + *pactive = rep.active; + } + + UnlockDisplay(dpy); + SyncHandle(); + + return n; +} + +void XiGMiscChangeResolution(Display *dpy, int screen, int view, int width, int height, int refresh) +{ + xXiGMiscChangeResolutionReq *req; + XExtDisplayInfo *info = XiGMiscFindDisplay(dpy); + + XiGMiscSimpleCheckExtension(dpy, info); + + LockDisplay (dpy); + XiGMiscGetReq (XiGMiscChangeResolution, req, info); + req->screen = screen; + req->view = view; + req->width = width; + req->height = height; + req->refresh = refresh; + + UnlockDisplay(dpy); + SyncHandle(); +} + + +Bool XiGMiscFullScreen(Display *dpy, int screen, XID window, XID cmap) +{ + xXiGMiscFullScreenReq *req; + xXiGMiscFullScreenReply rep; + XExtDisplayInfo *info = XiGMiscFindDisplay(dpy); + + XiGMiscCheckExtension(dpy, info, xFalse); + + LockDisplay (dpy); + XiGMiscGetReq (XiGMiscFullScreen, req, info); + req->screen = screen; + req->pad0 = 0; + req->pad1 = 0; + req->window = window; + req->cmap = cmap; + + if (!_XReply (dpy, (xReply *)&rep, 0, xTrue)) { + UnlockDisplay(dpy); + SyncHandle(); + return xFalse; + } + + UnlockDisplay(dpy); + SyncHandle(); + + return (rep.success ? xTrue : xFalse); +} + + +/* SDL addition from Ryan: free memory used by xme. */ +void XiGMiscDestroy(void) +{ + if (xigmisc_info) { + XextDestroyExtension(xigmisc_info); + xigmisc_info = NULL; + } +} + diff --git a/3rdparty/SDL/src/video/Xext/Xinerama/Xinerama.c b/3rdparty/SDL/src/video/Xext/Xinerama/Xinerama.c new file mode 100644 index 0000000..4ff42eb --- /dev/null +++ b/3rdparty/SDL/src/video/Xext/Xinerama/Xinerama.c @@ -0,0 +1,324 @@ +/* $Xorg: XPanoramiX.c,v 1.4 2000/08/17 19:45:51 cpqbld Exp $ */ +/***************************************************************** +Copyright (c) 1991, 1997 Digital Equipment Corporation, Maynard, Massachusetts. +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +DIGITAL EQUIPMENT CORPORATION BE LIABLE FOR ANY CLAIM, DAMAGES, INCLUDING, +BUT NOT LIMITED TO CONSEQUENTIAL OR INCIDENTAL DAMAGES, OR OTHER LIABILITY, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR +IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of Digital Equipment Corporation +shall not be used in advertising or otherwise to promote the sale, use or other +dealings in this Software without prior written authorization from Digital +Equipment Corporation. +******************************************************************/ +/* $XFree86: xc/lib/Xinerama/Xinerama.c,v 1.2 2001/07/23 17:20:28 dawes Exp $ */ + +#define NEED_EVENTS +#define NEED_REPLIES + +/* Apparently some X11 systems can't include this multiple times... */ +#ifndef SDL_INCLUDED_XLIBINT_H +#define SDL_INCLUDED_XLIBINT_H 1 +#include <X11/Xlibint.h> +#endif + +#include <X11/Xutil.h> +#include "../extensions/Xext.h" +#include "../extensions/extutil.h" /* in ../include */ +#include "../extensions/panoramiXext.h" +#include "../extensions/panoramiXproto.h" /* in ../include */ +#include "../extensions/Xinerama.h" + +static XExtensionInfo _panoramiX_ext_info_data; +static XExtensionInfo *panoramiX_ext_info = &_panoramiX_ext_info_data; +static /* const */ char *panoramiX_extension_name = PANORAMIX_PROTOCOL_NAME; + +#define PanoramiXCheckExtension(dpy,i,val) \ + XextCheckExtension (dpy, i, panoramiX_extension_name, val) +#define PanoramiXSimpleCheckExtension(dpy,i) \ + XextSimpleCheckExtension (dpy, i, panoramiX_extension_name) + +static int close_display(); +static /* const */ XExtensionHooks panoramiX_extension_hooks = { + NULL, /* create_gc */ + NULL, /* copy_gc */ + NULL, /* flush_gc */ + NULL, /* free_gc */ + NULL, /* create_font */ + NULL, /* free_font */ + close_display, /* close_display */ + NULL, /* wire_to_event */ + NULL, /* event_to_wire */ + NULL, /* error */ + NULL, /* error_string */ +}; + +static XEXT_GENERATE_FIND_DISPLAY (find_display, panoramiX_ext_info, + panoramiX_extension_name, + &panoramiX_extension_hooks, + 0, NULL) + +static XEXT_GENERATE_CLOSE_DISPLAY (close_display, panoramiX_ext_info) + + + +/**************************************************************************** + * * + * PanoramiX public interfaces * + * * + ****************************************************************************/ + +Bool SDL_NAME(XPanoramiXQueryExtension) ( + Display *dpy, + int *event_basep, + int *error_basep +) +{ + XExtDisplayInfo *info = find_display (dpy); + + if (XextHasExtension(info)) { + *event_basep = info->codes->first_event; + *error_basep = info->codes->first_error; + return True; + } else { + return False; + } +} + + +Status SDL_NAME(XPanoramiXQueryVersion)( + Display *dpy, + int *major_versionp, + int *minor_versionp +) +{ + XExtDisplayInfo *info = find_display (dpy); + xPanoramiXQueryVersionReply rep; + register xPanoramiXQueryVersionReq *req; + + PanoramiXCheckExtension (dpy, info, 0); + + LockDisplay (dpy); + GetReq (PanoramiXQueryVersion, req); + req->reqType = info->codes->major_opcode; + req->panoramiXReqType = X_PanoramiXQueryVersion; + req->clientMajor = PANORAMIX_MAJOR_VERSION; + req->clientMinor = PANORAMIX_MINOR_VERSION; + if (!_XReply (dpy, (xReply *) &rep, 0, xTrue)) { + UnlockDisplay (dpy); + SyncHandle (); + return 0; + } + *major_versionp = rep.majorVersion; + *minor_versionp = rep.minorVersion; + UnlockDisplay (dpy); + SyncHandle (); + return 1; +} + +SDL_NAME(XPanoramiXInfo) *SDL_NAME(XPanoramiXAllocInfo)(void) +{ + return (SDL_NAME(XPanoramiXInfo) *) Xmalloc (sizeof (SDL_NAME(XPanoramiXInfo))); +} + +Status SDL_NAME(XPanoramiXGetState) ( + Display *dpy, + Drawable drawable, + SDL_NAME(XPanoramiXInfo) *panoramiX_info +) +{ + XExtDisplayInfo *info = find_display (dpy); + xPanoramiXGetStateReply rep; + register xPanoramiXGetStateReq *req; + + PanoramiXCheckExtension (dpy, info, 0); + + LockDisplay (dpy); + GetReq (PanoramiXGetState, req); + req->reqType = info->codes->major_opcode; + req->panoramiXReqType = X_PanoramiXGetState; + req->window = drawable; + if (!_XReply (dpy, (xReply *) &rep, 0, xTrue)) { + UnlockDisplay (dpy); + SyncHandle (); + return 0; + } + UnlockDisplay (dpy); + SyncHandle (); + panoramiX_info->window = rep.window; + panoramiX_info->State = rep.state; + return 1; +} + +Status SDL_NAME(XPanoramiXGetScreenCount) ( + Display *dpy, + Drawable drawable, + SDL_NAME(XPanoramiXInfo) *panoramiX_info +) +{ + XExtDisplayInfo *info = find_display (dpy); + xPanoramiXGetScreenCountReply rep; + register xPanoramiXGetScreenCountReq *req; + + PanoramiXCheckExtension (dpy, info, 0); + + LockDisplay (dpy); + GetReq (PanoramiXGetScreenCount, req); + req->reqType = info->codes->major_opcode; + req->panoramiXReqType = X_PanoramiXGetScreenCount; + req->window = drawable; + if (!_XReply (dpy, (xReply *) &rep, 0, xTrue)) { + UnlockDisplay (dpy); + SyncHandle (); + return 0; + } + UnlockDisplay (dpy); + SyncHandle (); + panoramiX_info->window = rep.window; + panoramiX_info->ScreenCount = rep.ScreenCount; + return 1; +} + +Status SDL_NAME(XPanoramiXGetScreenSize) ( + Display *dpy, + Drawable drawable, + int screen_num, + SDL_NAME(XPanoramiXInfo) *panoramiX_info +) +{ + XExtDisplayInfo *info = find_display (dpy); + xPanoramiXGetScreenSizeReply rep; + register xPanoramiXGetScreenSizeReq *req; + + PanoramiXCheckExtension (dpy, info, 0); + + LockDisplay (dpy); + GetReq (PanoramiXGetScreenSize, req); + req->reqType = info->codes->major_opcode; + req->panoramiXReqType = X_PanoramiXGetScreenSize; + req->window = drawable; + req->screen = screen_num; /* need to define */ + if (!_XReply (dpy, (xReply *) &rep, 0, xTrue)) { + UnlockDisplay (dpy); + SyncHandle (); + return 0; + } + UnlockDisplay (dpy); + SyncHandle (); + panoramiX_info->window = rep.window; + panoramiX_info->screen = rep.screen; + panoramiX_info->width = rep.width; + panoramiX_info->height = rep.height; + return 1; +} + +/*******************************************************************\ + Alternate interface to make up for shortcomings in the original, + namely, the omission of the screen origin. The new interface is + in the "Xinerama" namespace instead of "PanoramiX". +\*******************************************************************/ + +Bool SDL_NAME(XineramaQueryExtension) ( + Display *dpy, + int *event_base, + int *error_base +) +{ + return SDL_NAME(XPanoramiXQueryExtension)(dpy, event_base, error_base); +} + +Status SDL_NAME(XineramaQueryVersion)( + Display *dpy, + int *major, + int *minor +) +{ + return SDL_NAME(XPanoramiXQueryVersion)(dpy, major, minor); +} + +Bool SDL_NAME(XineramaIsActive)(Display *dpy) +{ + xXineramaIsActiveReply rep; + xXineramaIsActiveReq *req; + XExtDisplayInfo *info = find_display (dpy); + + if(!XextHasExtension(info)) + return False; /* server doesn't even have the extension */ + + LockDisplay (dpy); + GetReq (XineramaIsActive, req); + req->reqType = info->codes->major_opcode; + req->panoramiXReqType = X_XineramaIsActive; + if (!_XReply (dpy, (xReply *) &rep, 0, xTrue)) { + UnlockDisplay (dpy); + SyncHandle (); + return False; + } + UnlockDisplay (dpy); + SyncHandle (); + return rep.state; +} + +#include <stdio.h> + +SDL_NAME(XineramaScreenInfo) * +SDL_NAME(XineramaQueryScreens)( + Display *dpy, + int *number +) +{ + XExtDisplayInfo *info = find_display (dpy); + xXineramaQueryScreensReply rep; + xXineramaQueryScreensReq *req; + SDL_NAME(XineramaScreenInfo) *scrnInfo = NULL; + + PanoramiXCheckExtension (dpy, info, 0); + + LockDisplay (dpy); + GetReq (XineramaQueryScreens, req); + req->reqType = info->codes->major_opcode; + req->panoramiXReqType = X_XineramaQueryScreens; + if (!_XReply (dpy, (xReply *) &rep, 0, xFalse)) { + UnlockDisplay (dpy); + SyncHandle (); + return NULL; + } + + if(rep.number) { + if((scrnInfo = Xmalloc(sizeof(SDL_NAME(XineramaScreenInfo)) * rep.number))) { + xXineramaScreenInfo scratch; + int i; + + for(i = 0; i < rep.number; i++) { + _XRead(dpy, (char*)(&scratch), sz_XineramaScreenInfo); + scrnInfo[i].screen_number = i; + scrnInfo[i].x_org = scratch.x_org; + scrnInfo[i].y_org = scratch.y_org; + scrnInfo[i].width = scratch.width; + scrnInfo[i].height = scratch.height; + } + + *number = rep.number; + } else + _XEatData(dpy, rep.length << 2); + } + + UnlockDisplay (dpy); + SyncHandle (); + return scrnInfo; +} + + + diff --git a/3rdparty/SDL/src/video/Xext/Xv/Xv.c b/3rdparty/SDL/src/video/Xext/Xv/Xv.c new file mode 100644 index 0000000..7147b9e --- /dev/null +++ b/3rdparty/SDL/src/video/Xext/Xv/Xv.c @@ -0,0 +1,1151 @@ +/*********************************************************** +Copyright 1991 by Digital Equipment Corporation, Maynard, Massachusetts, +and the Massachusetts Institute of Technology, Cambridge, Massachusetts. + + All Rights Reserved + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation, and that the names of Digital or MIT not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR +ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +SOFTWARE. + +******************************************************************/ +/* $XFree86: xc/lib/Xv/Xv.c,v 1.15 2001/05/11 08:23:22 alanh Exp $ */ +/* +** File: +** +** Xv.c --- Xv library extension module. +** +** Author: +** +** David Carver (Digital Workstation Engineering/Project Athena) +** +** Revisions: +** +** 26.06.91 Carver +** - changed XvFreeAdaptors to XvFreeAdaptorInfo +** - changed XvFreeEncodings to XvFreeEncodingInfo +** +** 11.06.91 Carver +** - changed SetPortControl to SetPortAttribute +** - changed GetPortControl to GetPortAttribute +** - changed QueryBestSize +** +** 15.05.91 Carver +** - version 2.0 upgrade +** +** 240.01.91 Carver +** - version 1.4 upgrade +** +*/ + +#include <stdio.h> +#include "Xvlibint.h" +#include "../extensions/Xext.h" +#include <X11/extensions/XShm.h> +#include "../extensions/extutil.h" + +static XExtensionInfo _xv_info_data; +static XExtensionInfo *xv_info = &_xv_info_data; +static char *xv_extension_name = XvName; + +#define XvCheckExtension(dpy, i, val) \ + XextCheckExtension(dpy, i, xv_extension_name, val) + +static char *xv_error_string(); +static int xv_close_display(); +static Bool xv_wire_to_event(); + +static XExtensionHooks xv_extension_hooks = { + NULL, /* create_gc */ + NULL, /* copy_gc */ + NULL, /* flush_gc */ + NULL, /* free_gc */ + NULL, /* create_font */ + NULL, /* free_font */ + xv_close_display, /* close_display */ + xv_wire_to_event, /* wire_to_event */ + NULL, /* event_to_wire */ + NULL, /* error */ + xv_error_string /* error_string */ +}; + + +static char *xv_error_list[] = +{ + "BadPort", /* XvBadPort */ + "BadEncoding", /* XvBadEncoding */ + "BadControl" /* XvBadControl */ +}; + +static XEXT_GENERATE_CLOSE_DISPLAY (xv_close_display, xv_info) + + +static XEXT_GENERATE_FIND_DISPLAY (xv_find_display, xv_info, + xv_extension_name, + &xv_extension_hooks, + XvNumEvents, NULL) + + +static XEXT_GENERATE_ERROR_STRING (xv_error_string, xv_extension_name, + XvNumErrors, xv_error_list) + + +int +SDL_NAME(XvQueryExtension)( + Display *dpy, + unsigned int *p_version, + unsigned int *p_revision, + unsigned int *p_requestBase, + unsigned int *p_eventBase, + unsigned int *p_errorBase +){ + XExtDisplayInfo *info = xv_find_display(dpy); + xvQueryExtensionReq *req; + xvQueryExtensionReply rep; + + XvCheckExtension(dpy, info, XvBadExtension); + + LockDisplay(dpy); + + XvGetReq(QueryExtension, req); + + if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) { + UnlockDisplay(dpy); + SyncHandle(); + return XvBadExtension; + } + + *p_version = rep.version; + *p_revision = rep.revision; + *p_requestBase = info->codes->major_opcode; + *p_eventBase = info->codes->first_event; + *p_errorBase = info->codes->first_error; + + UnlockDisplay(dpy); + SyncHandle(); + + return Success; +} + +int +SDL_NAME(XvQueryAdaptors)( + Display *dpy, + Window window, + unsigned int *p_nAdaptors, + SDL_NAME(XvAdaptorInfo) **p_pAdaptors +){ + XExtDisplayInfo *info = xv_find_display(dpy); + xvQueryAdaptorsReq *req; + xvQueryAdaptorsReply rep; + int size,ii,jj; + char *name; + SDL_NAME(XvAdaptorInfo) *pas, *pa; + SDL_NAME(XvFormat) *pfs, *pf; + char *buffer; + union + { + char *buffer; + char *string; + xvAdaptorInfo *pa; + xvFormat *pf; + } u; + + XvCheckExtension(dpy, info, XvBadExtension); + + LockDisplay(dpy); + + XvGetReq(QueryAdaptors, req); + req->window = window; + + /* READ THE REPLY */ + + if (_XReply(dpy, (xReply *)&rep, 0, xFalse) == 0) { + UnlockDisplay(dpy); + SyncHandle(); + return(XvBadReply); + } + + size = rep.length << 2; + if ( (buffer = (char *)Xmalloc ((unsigned) size)) == NULL) { + UnlockDisplay(dpy); + SyncHandle(); + return(XvBadAlloc); + } + _XRead (dpy, buffer, size); + + u.buffer = buffer; + + /* GET INPUT ADAPTORS */ + + if (rep.num_adaptors == 0) { + pas = NULL; + } else { + size = rep.num_adaptors*sizeof(SDL_NAME(XvAdaptorInfo)); + if ((pas=(SDL_NAME(XvAdaptorInfo) *)Xmalloc(size))==NULL) { + Xfree(buffer); + UnlockDisplay(dpy); + SyncHandle(); + return(XvBadAlloc); + } + } + + /* INIT ADAPTOR FIELDS */ + + pa = pas; + for (ii=0; ii<rep.num_adaptors; ii++) { + pa->num_adaptors = 0; + pa->name = (char *)NULL; + pa->formats = (SDL_NAME(XvFormat) *)NULL; + pa++; + } + + pa = pas; + for (ii=0; ii<rep.num_adaptors; ii++) { + pa->type = u.pa->type; + pa->base_id = u.pa->base_id; + pa->num_ports = u.pa->num_ports; + pa->num_formats = u.pa->num_formats; + pa->num_adaptors = rep.num_adaptors - ii; + + /* GET ADAPTOR NAME */ + + size = u.pa->name_size; + u.buffer += (sz_xvAdaptorInfo + 3) & ~3; + + if ( (name = (char *)Xmalloc(size+1)) == NULL) + { + SDL_NAME(XvFreeAdaptorInfo)(pas); + Xfree(buffer); + UnlockDisplay(dpy); + SyncHandle(); + return(XvBadAlloc); + } + SDL_strlcpy(name, u.string, size); + pa->name = name; + + u.buffer += (size + 3) & ~3; + + /* GET FORMATS */ + + size = pa->num_formats*sizeof(SDL_NAME(XvFormat)); + if ((pfs=(SDL_NAME(XvFormat) *)Xmalloc(size))==NULL) { + SDL_NAME(XvFreeAdaptorInfo)(pas); + Xfree(buffer); + UnlockDisplay(dpy); + SyncHandle(); + return(XvBadAlloc); + } + + pf = pfs; + for (jj=0; jj<pa->num_formats; jj++) { + pf->depth = u.pf->depth; + pf->visual_id = u.pf->visual; + pf++; + + u.buffer += (sz_xvFormat + 3) & ~3; + } + + pa->formats = pfs; + + pa++; + + } + + *p_nAdaptors = rep.num_adaptors; + *p_pAdaptors = pas; + + Xfree(buffer); + UnlockDisplay(dpy); + SyncHandle(); + + return (Success); +} + + +void +SDL_NAME(XvFreeAdaptorInfo)(SDL_NAME(XvAdaptorInfo) *pAdaptors) +{ + + SDL_NAME(XvAdaptorInfo) *pa; + int ii; + + if (!pAdaptors) return; + + pa = pAdaptors; + + for (ii=0; ii<pAdaptors->num_adaptors; ii++, pa++) + { + if (pa->name) + { + Xfree(pa->name); + } + if (pa->formats) + { + Xfree(pa->formats); + } + } + + Xfree(pAdaptors); +} + +int +SDL_NAME(XvQueryEncodings)( + Display *dpy, + XvPortID port, + unsigned int *p_nEncodings, + SDL_NAME(XvEncodingInfo) **p_pEncodings +){ + XExtDisplayInfo *info = xv_find_display(dpy); + xvQueryEncodingsReq *req; + xvQueryEncodingsReply rep; + int size, jj; + char *name; + SDL_NAME(XvEncodingInfo) *pes, *pe; + char *buffer; + union + { + char *buffer; + char *string; + xvEncodingInfo *pe; + } u; + + XvCheckExtension(dpy, info, XvBadExtension); + + LockDisplay(dpy); + + XvGetReq(QueryEncodings, req); + req->port = port; + + /* READ THE REPLY */ + + if (_XReply(dpy, (xReply *)&rep, 0, xFalse) == 0) { + UnlockDisplay(dpy); + SyncHandle(); + return(XvBadReply); + } + + size = rep.length << 2; + if ( (buffer = (char *)Xmalloc ((unsigned) size)) == NULL) { + UnlockDisplay(dpy); + SyncHandle(); + return(XvBadAlloc); + } + _XRead (dpy, buffer, size); + + u.buffer = buffer; + + /* GET ENCODINGS */ + + size = rep.num_encodings*sizeof(SDL_NAME(XvEncodingInfo)); + if ( (pes = (SDL_NAME(XvEncodingInfo) *)Xmalloc(size)) == NULL) { + Xfree(buffer); + UnlockDisplay(dpy); + SyncHandle(); + return(XvBadAlloc); + } + + /* INITIALIZE THE ENCODING POINTER */ + + pe = pes; + for (jj=0; jj<rep.num_encodings; jj++) { + pe->name = (char *)NULL; + pe->num_encodings = 0; + pe++; + } + + pe = pes; + for (jj=0; jj<rep.num_encodings; jj++) { + pe->encoding_id = u.pe->encoding; + pe->width = u.pe->width; + pe->height = u.pe->height; + pe->rate.numerator = u.pe->rate.numerator; + pe->rate.denominator = u.pe->rate.denominator; + pe->num_encodings = rep.num_encodings - jj; + + size = u.pe->name_size; + u.buffer += (sz_xvEncodingInfo + 3) & ~3; + + if ( (name = (char *)Xmalloc(size+1)) == NULL) { + Xfree(buffer); + UnlockDisplay(dpy); + SyncHandle(); + return(XvBadAlloc); + } + SDL_strlcpy(name, u.string, size); + pe->name = name; + pe++; + + u.buffer += (size + 3) & ~3; + } + + *p_nEncodings = rep.num_encodings; + *p_pEncodings = pes; + + Xfree(buffer); + UnlockDisplay(dpy); + SyncHandle(); + + return (Success); +} + +void +SDL_NAME(XvFreeEncodingInfo)(SDL_NAME(XvEncodingInfo) *pEncodings) +{ + + SDL_NAME(XvEncodingInfo) *pe; + int ii; + + if (!pEncodings) return; + + pe = pEncodings; + + for (ii=0; ii<pEncodings->num_encodings; ii++, pe++) { + if (pe->name) Xfree(pe->name); + } + + Xfree(pEncodings); +} + +int +SDL_NAME(XvPutVideo)( + Display *dpy, + XvPortID port, + Drawable d, + GC gc, + int vx, int vy, + unsigned int vw, unsigned int vh, + int dx, int dy, + unsigned int dw, unsigned int dh +){ + XExtDisplayInfo *info = xv_find_display(dpy); + xvPutVideoReq *req; + + XvCheckExtension(dpy, info, XvBadExtension); + + LockDisplay(dpy); + + FlushGC(dpy, gc); + + XvGetReq(PutVideo, req); + + req->port = port; + req->drawable = d; + req->gc = gc->gid; + req->vid_x = vx; + req->vid_y = vy; + req->vid_w = vw; + req->vid_h = vh; + req->drw_x = dx; + req->drw_y = dy; + req->drw_w = dw; + req->drw_h = dh; + + UnlockDisplay(dpy); + SyncHandle(); + + return Success; +} + +int +SDL_NAME(XvPutStill)( + Display *dpy, + XvPortID port, + Drawable d, + GC gc, + int vx, int vy, + unsigned int vw, unsigned int vh, + int dx, int dy, + unsigned int dw, unsigned int dh +){ + XExtDisplayInfo *info = xv_find_display(dpy); + xvPutStillReq *req; + + XvCheckExtension(dpy, info, XvBadExtension); + + LockDisplay(dpy); + + FlushGC(dpy, gc); + + XvGetReq(PutStill, req); + req->port = port; + req->drawable = d; + req->gc = gc->gid; + req->vid_x = vx; + req->vid_y = vy; + req->vid_w = vw; + req->vid_h = vh; + req->drw_x = dx; + req->drw_y = dy; + req->drw_w = dw; + req->drw_h = dh; + + UnlockDisplay(dpy); + SyncHandle(); + + return Success; +} + +int +SDL_NAME(XvGetVideo)( + Display *dpy, + XvPortID port, + Drawable d, + GC gc, + int vx, int vy, + unsigned int vw, unsigned int vh, + int dx, int dy, + unsigned int dw, unsigned int dh +){ + XExtDisplayInfo *info = xv_find_display(dpy); + xvGetVideoReq *req; + + XvCheckExtension(dpy, info, XvBadExtension); + + LockDisplay(dpy); + + FlushGC(dpy, gc); + + XvGetReq(GetVideo, req); + req->port = port; + req->drawable = d; + req->gc = gc->gid; + req->vid_x = vx; + req->vid_y = vy; + req->vid_w = vw; + req->vid_h = vh; + req->drw_x = dx; + req->drw_y = dy; + req->drw_w = dw; + req->drw_h = dh; + + UnlockDisplay(dpy); + SyncHandle(); + + return Success; +} + +int +SDL_NAME(XvGetStill)( + Display *dpy, + XvPortID port, + Drawable d, + GC gc, + int vx, int vy, + unsigned int vw, unsigned int vh, + int dx, int dy, + unsigned int dw, unsigned int dh +){ + XExtDisplayInfo *info = xv_find_display(dpy); + xvGetStillReq *req; + + XvCheckExtension(dpy, info, XvBadExtension); + + LockDisplay(dpy); + + FlushGC(dpy, gc); + + XvGetReq(GetStill, req); + req->port = port; + req->drawable = d; + req->gc = gc->gid; + req->vid_x = vx; + req->vid_y = vy; + req->vid_w = vw; + req->vid_h = vh; + req->drw_x = dx; + req->drw_y = dy; + req->drw_w = dw; + req->drw_h = dh; + + UnlockDisplay(dpy); + SyncHandle(); + + return Success; +} + +int +SDL_NAME(XvStopVideo)( + Display *dpy, + XvPortID port, + Drawable draw +){ + XExtDisplayInfo *info = xv_find_display(dpy); + xvStopVideoReq *req; + + XvCheckExtension(dpy, info, XvBadExtension); + + LockDisplay(dpy); + + XvGetReq(StopVideo, req); + req->port = port; + req->drawable = draw; + + UnlockDisplay(dpy); + SyncHandle(); + + return Success; +} + +int +SDL_NAME(XvGrabPort)( + Display *dpy, + XvPortID port, + Time time +){ + XExtDisplayInfo *info = xv_find_display(dpy); + int result; + xvGrabPortReply rep; + xvGrabPortReq *req; + + XvCheckExtension(dpy, info, XvBadExtension); + + LockDisplay(dpy); + + XvGetReq(GrabPort, req); + req->port = port; + req->time = time; + + if (_XReply (dpy, (xReply *) &rep, 0, xTrue) == 0) + rep.result = GrabSuccess; + + result = rep.result; + + UnlockDisplay(dpy); + SyncHandle(); + + return result; +} + +int +SDL_NAME(XvUngrabPort)( + Display *dpy, + XvPortID port, + Time time +){ + XExtDisplayInfo *info = xv_find_display(dpy); + xvUngrabPortReq *req; + + XvCheckExtension(dpy, info, XvBadExtension); + + LockDisplay(dpy); + + XvGetReq(UngrabPort, req); + req->port = port; + req->time = time; + + UnlockDisplay(dpy); + SyncHandle(); + + return Success; +} + +int +SDL_NAME(XvSelectVideoNotify)( + Display *dpy, + Drawable drawable, + Bool onoff +){ + XExtDisplayInfo *info = xv_find_display(dpy); + xvSelectVideoNotifyReq *req; + + XvCheckExtension(dpy, info, XvBadExtension); + + LockDisplay(dpy); + + XvGetReq(SelectVideoNotify, req); + req->drawable = drawable; + req->onoff = onoff; + + UnlockDisplay(dpy); + SyncHandle(); + + return Success; +} + +int +SDL_NAME(XvSelectPortNotify)( + Display *dpy, + XvPortID port, + Bool onoff +){ + XExtDisplayInfo *info = xv_find_display(dpy); + xvSelectPortNotifyReq *req; + + XvCheckExtension(dpy, info, XvBadExtension); + + LockDisplay(dpy); + + XvGetReq(SelectPortNotify, req); + req->port = port; + req->onoff = onoff; + + UnlockDisplay(dpy); + SyncHandle(); + + return Success; +} + +int +SDL_NAME(XvSetPortAttribute) ( + Display *dpy, + XvPortID port, + Atom attribute, + int value +) +{ + XExtDisplayInfo *info = xv_find_display(dpy); + xvSetPortAttributeReq *req; + + XvCheckExtension(dpy, info, XvBadExtension); + + LockDisplay(dpy); + + XvGetReq(SetPortAttribute, req); + req->port = port; + req->attribute = attribute; + req->value = value; + + UnlockDisplay(dpy); + SyncHandle(); + + return (Success); +} + +int +SDL_NAME(XvGetPortAttribute) ( + Display *dpy, + XvPortID port, + Atom attribute, + int *p_value +) +{ + XExtDisplayInfo *info = xv_find_display(dpy); + xvGetPortAttributeReq *req; + xvGetPortAttributeReply rep; + + XvCheckExtension(dpy, info, XvBadExtension); + + LockDisplay(dpy); + + XvGetReq(GetPortAttribute, req); + req->port = port; + req->attribute = attribute; + + /* READ THE REPLY */ + + if (_XReply(dpy, (xReply *)&rep, 0, xFalse) == 0) { + UnlockDisplay(dpy); + SyncHandle(); + return(XvBadReply); + } + + *p_value = rep.value; + + UnlockDisplay(dpy); + SyncHandle(); + + return (Success); +} + +int +SDL_NAME(XvQueryBestSize)( + Display *dpy, + XvPortID port, + Bool motion, + unsigned int vid_w, + unsigned int vid_h, + unsigned int drw_w, + unsigned int drw_h, + unsigned int *p_actual_width, + unsigned int *p_actual_height +) +{ + XExtDisplayInfo *info = xv_find_display(dpy); + xvQueryBestSizeReq *req; + xvQueryBestSizeReply rep; + + XvCheckExtension(dpy, info, XvBadExtension); + + LockDisplay(dpy); + + XvGetReq(QueryBestSize, req); + req->port = port; + req->motion = motion; + req->vid_w = vid_w; + req->vid_h = vid_h; + req->drw_w = drw_w; + req->drw_h = drw_h; + + /* READ THE REPLY */ + + if (_XReply(dpy, (xReply *)&rep, 0, xFalse) == 0) { + UnlockDisplay(dpy); + SyncHandle(); + return(XvBadReply); + } + + *p_actual_width = rep.actual_width; + *p_actual_height = rep.actual_height; + + UnlockDisplay(dpy); + SyncHandle(); + + return (Success); +} + + +SDL_NAME(XvAttribute)* +SDL_NAME(XvQueryPortAttributes)(Display *dpy, XvPortID port, int *num) +{ + XExtDisplayInfo *info = xv_find_display(dpy); + xvQueryPortAttributesReq *req; + xvQueryPortAttributesReply rep; + SDL_NAME(XvAttribute) *ret = NULL; + + *num = 0; + + XvCheckExtension(dpy, info, NULL); + + LockDisplay(dpy); + + XvGetReq(QueryPortAttributes, req); + req->port = port; + + /* READ THE REPLY */ + + if (_XReply(dpy, (xReply *)&rep, 0, xFalse) == 0) { + UnlockDisplay(dpy); + SyncHandle(); + return ret; + } + + if(rep.num_attributes) { + int size = (rep.num_attributes * sizeof(SDL_NAME(XvAttribute))) + rep.text_size; + + if((ret = Xmalloc(size))) { + char* marker = (char*)(&ret[rep.num_attributes]); + xvAttributeInfo Info; + int i; + + for(i = 0; i < rep.num_attributes; i++) { + _XRead(dpy, (char*)(&Info), sz_xvAttributeInfo); + ret[i].flags = (int)Info.flags; + ret[i].min_value = Info.min; + ret[i].max_value = Info.max; + ret[i].name = marker; + _XRead(dpy, marker, Info.size); + marker += Info.size; + (*num)++; + } + } else + _XEatData(dpy, rep.length << 2); + } + + UnlockDisplay(dpy); + SyncHandle(); + + return ret; +} + +SDL_NAME(XvImageFormatValues) * SDL_NAME(XvListImageFormats) ( + Display *dpy, + XvPortID port, + int *num +){ + XExtDisplayInfo *info = xv_find_display(dpy); + xvListImageFormatsReq *req; + xvListImageFormatsReply rep; + SDL_NAME(XvImageFormatValues) *ret = NULL; + + *num = 0; + + XvCheckExtension(dpy, info, NULL); + + LockDisplay(dpy); + + XvGetReq(ListImageFormats, req); + req->port = port; + + /* READ THE REPLY */ + + if (_XReply(dpy, (xReply *)&rep, 0, xFalse) == 0) { + UnlockDisplay(dpy); + SyncHandle(); + return NULL; + } + + if(rep.num_formats) { + int size = (rep.num_formats * sizeof(SDL_NAME(XvImageFormatValues))); + + if((ret = Xmalloc(size))) { + xvImageFormatInfo Info; + int i; + + for(i = 0; i < rep.num_formats; i++) { + _XRead(dpy, (char*)(&Info), sz_xvImageFormatInfo); + ret[i].id = Info.id; + ret[i].type = Info.type; + ret[i].byte_order = Info.byte_order; + memcpy(&(ret[i].guid[0]), &(Info.guid[0]), 16); + ret[i].bits_per_pixel = Info.bpp; + ret[i].format = Info.format; + ret[i].num_planes = Info.num_planes; + ret[i].depth = Info.depth; + ret[i].red_mask = Info.red_mask; + ret[i].green_mask = Info.green_mask; + ret[i].blue_mask = Info.blue_mask; + ret[i].y_sample_bits = Info.y_sample_bits; + ret[i].u_sample_bits = Info.u_sample_bits; + ret[i].v_sample_bits = Info.v_sample_bits; + ret[i].horz_y_period = Info.horz_y_period; + ret[i].horz_u_period = Info.horz_u_period; + ret[i].horz_v_period = Info.horz_v_period; + ret[i].vert_y_period = Info.vert_y_period; + ret[i].vert_u_period = Info.vert_u_period; + ret[i].vert_v_period = Info.vert_v_period; + memcpy(&(ret[i].component_order[0]), &(Info.comp_order[0]), 32); + ret[i].scanline_order = Info.scanline_order; + (*num)++; + } + } else + _XEatData(dpy, rep.length << 2); + } + + UnlockDisplay(dpy); + SyncHandle(); + + return ret; +} + +SDL_NAME(XvImage) * SDL_NAME(XvCreateImage) ( + Display *dpy, + XvPortID port, + int id, + char *data, + int width, + int height +) { + XExtDisplayInfo *info = xv_find_display(dpy); + xvQueryImageAttributesReq *req; + xvQueryImageAttributesReply rep; + SDL_NAME(XvImage) *ret = NULL; + + XvCheckExtension(dpy, info, NULL); + + LockDisplay(dpy); + + XvGetReq(QueryImageAttributes, req); + req->id = id; + req->port = port; + req->width = width; + req->height = height; + + /* READ THE REPLY */ + + if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) { + UnlockDisplay(dpy); + SyncHandle(); + return NULL; + } + + if((ret = (SDL_NAME(XvImage)*)Xmalloc(sizeof(SDL_NAME(XvImage)) + (rep.num_planes << 3)))) { + ret->id = id; + ret->width = rep.width; + ret->height = rep.height; + ret->data_size = rep.data_size; + ret->num_planes = rep.num_planes; + ret->pitches = (int*)(&ret[1]); + ret->offsets = ret->pitches + rep.num_planes; + ret->data = data; + ret->obdata = NULL; + _XRead(dpy, (char*)(ret->pitches), rep.num_planes << 2); + _XRead(dpy, (char*)(ret->offsets), rep.num_planes << 2); + } else + _XEatData(dpy, rep.length << 2); + + UnlockDisplay(dpy); + SyncHandle(); + return ret; +} + +SDL_NAME(XvImage) * SDL_NAME(XvShmCreateImage) ( + Display *dpy, + XvPortID port, + int id, + char *data, + int width, + int height, + XShmSegmentInfo *shminfo +){ + SDL_NAME(XvImage) *ret; + + ret = SDL_NAME(XvCreateImage)(dpy, port, id, data, width, height); + + if(ret) ret->obdata = (XPointer)shminfo; + + return ret; +} + +int SDL_NAME(XvPutImage) ( + Display *dpy, + XvPortID port, + Drawable d, + GC gc, + SDL_NAME(XvImage) *image, + int src_x, + int src_y, + unsigned int src_w, + unsigned int src_h, + int dest_x, + int dest_y, + unsigned int dest_w, + unsigned int dest_h +){ + XExtDisplayInfo *info = xv_find_display(dpy); + xvPutImageReq *req; + int len; + + XvCheckExtension(dpy, info, XvBadExtension); + + LockDisplay(dpy); + + FlushGC(dpy, gc); + + XvGetReq(PutImage, req); + + req->port = port; + req->drawable = d; + req->gc = gc->gid; + req->id = image->id; + req->src_x = src_x; + req->src_y = src_y; + req->src_w = src_w; + req->src_h = src_h; + req->drw_x = dest_x; + req->drw_y = dest_y; + req->drw_w = dest_w; + req->drw_h = dest_h; + req->width = image->width; + req->height = image->height; + + len = (image->data_size + 3) >> 2; + SetReqLen(req, len, len); + + /* Yes it's kindof lame that we are sending the whole thing, + but for video all of it may be needed even if displaying + only a subsection, and I don't want to go through the + trouble of creating subregions to send */ + Data(dpy, (char *)image->data, image->data_size); + + UnlockDisplay(dpy); + SyncHandle(); + + return Success; +} + +int SDL_NAME(XvShmPutImage) ( + Display *dpy, + XvPortID port, + Drawable d, + GC gc, + SDL_NAME(XvImage) *image, + int src_x, + int src_y, + unsigned int src_w, + unsigned int src_h, + int dest_x, + int dest_y, + unsigned int dest_w, + unsigned int dest_h, + Bool send_event +){ + XExtDisplayInfo *info = xv_find_display(dpy); + XShmSegmentInfo *shminfo = (XShmSegmentInfo *)image->obdata; + xvShmPutImageReq *req; + + XvCheckExtension(dpy, info, XvBadExtension); + + LockDisplay(dpy); + + FlushGC(dpy, gc); + + XvGetReq(ShmPutImage, req); + + req->port = port; + req->drawable = d; + req->gc = gc->gid; + req->shmseg = shminfo->shmseg; + req->id = image->id; + req->src_x = src_x; + req->src_y = src_y; + req->src_w = src_w; + req->src_h = src_h; + req->drw_x = dest_x; + req->drw_y = dest_y; + req->drw_w = dest_w; + req->drw_h = dest_h; + req->offset = image->data - shminfo->shmaddr; + req->width = image->width; + req->height = image->height; + req->send_event = send_event; + + UnlockDisplay(dpy); + SyncHandle(); + + return Success; +} + + +static Bool +xv_wire_to_event(Display *dpy, XEvent *host, xEvent *wire) +{ + XExtDisplayInfo *info = xv_find_display(dpy); + SDL_NAME(XvEvent) *re = (SDL_NAME(XvEvent) *)host; + xvEvent *event = (xvEvent *)wire; + + XvCheckExtension(dpy, info, False); + + switch((event->u.u.type & 0x7F) - info->codes->first_event) + { + case XvVideoNotify: + re->xvvideo.type = event->u.u.type & 0x7f; + re->xvvideo.serial = + _XSetLastRequestRead(dpy, (xGenericReply *)event); + re->xvvideo.send_event = ((event->u.u.type & 0x80) != 0); + re->xvvideo.display = dpy; + re->xvvideo.time = event->u.videoNotify.time; + re->xvvideo.reason = event->u.videoNotify.reason; + re->xvvideo.drawable = event->u.videoNotify.drawable; + re->xvvideo.port_id = event->u.videoNotify.port; + break; + case XvPortNotify: + re->xvport.type = event->u.u.type & 0x7f; + re->xvport.serial = + _XSetLastRequestRead(dpy, (xGenericReply *)event); + re->xvport.send_event = ((event->u.u.type & 0x80) != 0); + re->xvport.display = dpy; + re->xvport.time = event->u.portNotify.time; + re->xvport.port_id = event->u.portNotify.port; + re->xvport.attribute = event->u.portNotify.attribute; + re->xvport.value = event->u.portNotify.value; + break; + default: + return False; + } + + return (True); +} + + diff --git a/3rdparty/SDL/src/video/Xext/Xv/Xvlibint.h b/3rdparty/SDL/src/video/Xext/Xv/Xvlibint.h new file mode 100644 index 0000000..20df706 --- /dev/null +++ b/3rdparty/SDL/src/video/Xext/Xv/Xvlibint.h @@ -0,0 +1,81 @@ +/*********************************************************** +Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts, +and the Massachusetts Institute of Technology, Cambridge, Massachusetts. + + All Rights Reserved + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation, and that the names of Digital or MIT not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR +ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +SOFTWARE. + +******************************************************************/ +/* $XFree86: xc/lib/Xv/Xvlibint.h,v 1.5 2001/07/25 15:04:53 dawes Exp $ */ + +#ifndef XVLIBINT_H +#define XVLIBINT_H +/* +** File: +** +** Xvlibint.h --- Xv library internal header file +** +** Author: +** +** David Carver (Digital Workstation Engineering/Project Athena) +** +** Revisions: +** +** 01.24.91 Carver +** - version 1.4 upgrade +** +*/ + +#define NEED_REPLIES + +/* Apparently some X11 systems can't include this multiple times... */ +#ifndef SDL_INCLUDED_XLIBINT_H +#define SDL_INCLUDED_XLIBINT_H 1 +#include <X11/Xlibint.h> +#endif + +#include "../extensions/Xvproto.h" +#include "../extensions/Xvlib.h" + +#if !defined(UNIXCPP) +#define XvGetReq(name, req) \ + WORD64ALIGN\ + if ((dpy->bufptr + SIZEOF(xv##name##Req)) > dpy->bufmax)\ + _XFlush(dpy);\ + req = (xv##name##Req *)(dpy->last_req = dpy->bufptr);\ + req->reqType = info->codes->major_opcode;\ + req->xvReqType = xv_##name; \ + req->length = (SIZEOF(xv##name##Req))>>2;\ + dpy->bufptr += SIZEOF(xv##name##Req);\ + dpy->request++ + +#else /* non-ANSI C uses empty comment instead of "##" for token concatenation */ +#define XvGetReq(name, req) \ + WORD64ALIGN\ + if ((dpy->bufptr + SIZEOF(xv/**/name/**/Req)) > dpy->bufmax)\ + _XFlush(dpy);\ + req = (xv/**/name/**/Req *)(dpy->last_req = dpy->bufptr);\ + req->reqType = info->codes->major_opcode;\ + req->xvReqType = xv_/**/name;\ + req->length = (SIZEOF(xv/**/name/**/Req))>>2;\ + dpy->bufptr += SIZEOF(xv/**/name/**/Req);\ + dpy->request++ +#endif + + +#endif /* XVLIBINT_H */ diff --git a/3rdparty/SDL/src/video/Xext/Xxf86dga/XF86DGA.c b/3rdparty/SDL/src/video/Xext/Xxf86dga/XF86DGA.c new file mode 100644 index 0000000..fc729f1 --- /dev/null +++ b/3rdparty/SDL/src/video/Xext/Xxf86dga/XF86DGA.c @@ -0,0 +1,721 @@ +/* $XFree86: xc/lib/Xxf86dga/XF86DGA.c,v 3.19 2001/08/18 02:41:30 dawes Exp $ */ +/* + +Copyright (c) 1995 Jon Tombs +Copyright (c) 1995,1996 The XFree86 Project, Inc + +*/ + +/* THIS IS NOT AN X CONSORTIUM STANDARD */ + +#ifdef __EMX__ /* needed here to override certain constants in X headers */ +#define INCL_DOS +#define INCL_DOSIOCTL +#include <os2.h> +#endif + +#if defined(linux) +#define HAS_MMAP_ANON +#include <sys/types.h> +#include <sys/mman.h> +/*#include <asm/page.h>*/ /* PAGE_SIZE */ +#define HAS_SC_PAGESIZE /* _SC_PAGESIZE may be an enum for Linux */ +#define HAS_GETPAGESIZE +#endif /* linux */ + +#if defined(CSRG_BASED) +#define HAS_MMAP_ANON +#define HAS_GETPAGESIZE +#include <sys/types.h> +#include <sys/mman.h> +#endif /* CSRG_BASED */ + +#if defined(DGUX) +#define HAS_GETPAGESIZE +#define MMAP_DEV_ZERO +#include <sys/types.h> +#include <sys/mman.h> +#include <unistd.h> +#endif /* DGUX */ + +#if defined(SVR4) && !defined(DGUX) +#define MMAP_DEV_ZERO +#include <sys/types.h> +#include <sys/mman.h> +#include <unistd.h> +#endif /* SVR4 && !DGUX */ + +#if defined(sun) && !defined(SVR4) /* SunOS */ +#define MMAP_DEV_ZERO /* doesn't SunOS have MAP_ANON ?? */ +#define HAS_GETPAGESIZE +#include <sys/types.h> +#include <sys/mman.h> +#endif /* sun && !SVR4 */ + +#ifdef XNO_SYSCONF +#undef _SC_PAGESIZE +#endif + +#define NEED_EVENTS +#define NEED_REPLIES + +/* Apparently some X11 systems can't include this multiple times... */ +#ifndef SDL_INCLUDED_XLIBINT_H +#define SDL_INCLUDED_XLIBINT_H 1 +#include <X11/Xlibint.h> +#endif + +#include "../extensions/xf86dga.h" +#include "../extensions/xf86dgastr.h" +#include "../extensions/Xext.h" +#include "../extensions/extutil.h" + +extern XExtDisplayInfo* SDL_NAME(xdga_find_display)(Display*); +extern char *SDL_NAME(xdga_extension_name); + +#define XF86DGACheckExtension(dpy,i,val) \ + XextCheckExtension (dpy, i, SDL_NAME(xdga_extension_name), val) + +/***************************************************************************** + * * + * public XFree86-DGA Extension routines * + * * + *****************************************************************************/ + +Bool SDL_NAME(XF86DGAQueryExtension) ( + Display *dpy, + int *event_basep, + int *error_basep +){ + return SDL_NAME(XDGAQueryExtension)(dpy, event_basep, error_basep); +} + +Bool SDL_NAME(XF86DGAQueryVersion)( + Display* dpy, + int* majorVersion, + int* minorVersion +){ + return SDL_NAME(XDGAQueryVersion)(dpy, majorVersion, minorVersion); +} + +Bool SDL_NAME(XF86DGAGetVideoLL)( + Display* dpy, + int screen, + int *offset, + int *width, + int *bank_size, + int *ram_size +){ + XExtDisplayInfo *info = SDL_NAME(xdga_find_display) (dpy); + xXF86DGAGetVideoLLReply rep; + xXF86DGAGetVideoLLReq *req; + + XF86DGACheckExtension (dpy, info, False); + + LockDisplay(dpy); + GetReq(XF86DGAGetVideoLL, req); + req->reqType = info->codes->major_opcode; + req->dgaReqType = X_XF86DGAGetVideoLL; + req->screen = screen; + if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) { + UnlockDisplay(dpy); + SyncHandle(); + return False; + } + + *offset = /*(char *)*/rep.offset; + *width = rep.width; + *bank_size = rep.bank_size; + *ram_size = rep.ram_size; + + UnlockDisplay(dpy); + SyncHandle(); + return True; +} + + +Bool SDL_NAME(XF86DGADirectVideoLL)( + Display* dpy, + int screen, + int enable +){ + XExtDisplayInfo *info = SDL_NAME(xdga_find_display) (dpy); + xXF86DGADirectVideoReq *req; + + XF86DGACheckExtension (dpy, info, False); + + LockDisplay(dpy); + GetReq(XF86DGADirectVideo, req); + req->reqType = info->codes->major_opcode; + req->dgaReqType = X_XF86DGADirectVideo; + req->screen = screen; + req->enable = enable; + UnlockDisplay(dpy); + SyncHandle(); + XSync(dpy,False); + return True; +} + +Bool SDL_NAME(XF86DGAGetViewPortSize)( + Display* dpy, + int screen, + int *width, + int *height +){ + XExtDisplayInfo *info = SDL_NAME(xdga_find_display) (dpy); + xXF86DGAGetViewPortSizeReply rep; + xXF86DGAGetViewPortSizeReq *req; + + XF86DGACheckExtension (dpy, info, False); + + LockDisplay(dpy); + GetReq(XF86DGAGetViewPortSize, req); + req->reqType = info->codes->major_opcode; + req->dgaReqType = X_XF86DGAGetViewPortSize; + req->screen = screen; + if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) { + UnlockDisplay(dpy); + SyncHandle(); + return False; + } + + *width = rep.width; + *height = rep.height; + + UnlockDisplay(dpy); + SyncHandle(); + return True; +} + + +Bool SDL_NAME(XF86DGASetViewPort)( + Display* dpy, + int screen, + int x, + int y +){ + XExtDisplayInfo *info = SDL_NAME(xdga_find_display) (dpy); + xXF86DGASetViewPortReq *req; + + XF86DGACheckExtension (dpy, info, False); + + LockDisplay(dpy); + GetReq(XF86DGASetViewPort, req); + req->reqType = info->codes->major_opcode; + req->dgaReqType = X_XF86DGASetViewPort; + req->screen = screen; + req->x = x; + req->y = y; + UnlockDisplay(dpy); + SyncHandle(); + XSync(dpy,False); + return True; +} + + +Bool SDL_NAME(XF86DGAGetVidPage)( + Display* dpy, + int screen, + int *vpage +){ + XExtDisplayInfo *info = SDL_NAME(xdga_find_display) (dpy); + xXF86DGAGetVidPageReply rep; + xXF86DGAGetVidPageReq *req; + + XF86DGACheckExtension (dpy, info, False); + + LockDisplay(dpy); + GetReq(XF86DGAGetVidPage, req); + req->reqType = info->codes->major_opcode; + req->dgaReqType = X_XF86DGAGetVidPage; + req->screen = screen; + if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) { + UnlockDisplay(dpy); + SyncHandle(); + return False; + } + + *vpage = rep.vpage; + UnlockDisplay(dpy); + SyncHandle(); + return True; +} + + +Bool SDL_NAME(XF86DGASetVidPage)( + Display* dpy, + int screen, + int vpage +){ + XExtDisplayInfo *info = SDL_NAME(xdga_find_display) (dpy); + xXF86DGASetVidPageReq *req; + + XF86DGACheckExtension (dpy, info, False); + + LockDisplay(dpy); + GetReq(XF86DGASetVidPage, req); + req->reqType = info->codes->major_opcode; + req->dgaReqType = X_XF86DGASetVidPage; + req->screen = screen; + req->vpage = vpage; + UnlockDisplay(dpy); + SyncHandle(); + XSync(dpy,False); + return True; +} + +Bool SDL_NAME(XF86DGAInstallColormap)( + Display* dpy, + int screen, + Colormap cmap +){ + XExtDisplayInfo *info = SDL_NAME(xdga_find_display) (dpy); + xXF86DGAInstallColormapReq *req; + + XF86DGACheckExtension (dpy, info, False); + + LockDisplay(dpy); + GetReq(XF86DGAInstallColormap, req); + req->reqType = info->codes->major_opcode; + req->dgaReqType = X_XF86DGAInstallColormap; + req->screen = screen; + req->id = cmap; + UnlockDisplay(dpy); + SyncHandle(); + XSync(dpy,False); + return True; +} + +Bool SDL_NAME(XF86DGAQueryDirectVideo)( + Display *dpy, + int screen, + int *flags +){ + XExtDisplayInfo *info = SDL_NAME(xdga_find_display) (dpy); + xXF86DGAQueryDirectVideoReply rep; + xXF86DGAQueryDirectVideoReq *req; + + XF86DGACheckExtension (dpy, info, False); + + LockDisplay(dpy); + GetReq(XF86DGAQueryDirectVideo, req); + req->reqType = info->codes->major_opcode; + req->dgaReqType = X_XF86DGAQueryDirectVideo; + req->screen = screen; + if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) { + UnlockDisplay(dpy); + SyncHandle(); + return False; + } + *flags = rep.flags; + UnlockDisplay(dpy); + SyncHandle(); + return True; +} + +Bool SDL_NAME(XF86DGAViewPortChanged)( + Display *dpy, + int screen, + int n +){ + XExtDisplayInfo *info = SDL_NAME(xdga_find_display) (dpy); + xXF86DGAViewPortChangedReply rep; + xXF86DGAViewPortChangedReq *req; + + XF86DGACheckExtension (dpy, info, False); + + LockDisplay(dpy); + GetReq(XF86DGAViewPortChanged, req); + req->reqType = info->codes->major_opcode; + req->dgaReqType = X_XF86DGAViewPortChanged; + req->screen = screen; + req->n = n; + if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) { + UnlockDisplay(dpy); + SyncHandle(); + return False; + } + UnlockDisplay(dpy); + SyncHandle(); + return rep.result; +} + + + +/* Helper functions */ + +#include <X11/Xmd.h> +#include "../extensions/xf86dga.h" +#include <stdlib.h> +#include <stdio.h> +#include <fcntl.h> +#if defined(ISC) +# define HAS_SVR3_MMAP +# include <sys/types.h> +# include <errno.h> + +# include <sys/at_ansi.h> +# include <sys/kd.h> + +# include <sys/sysmacros.h> +# include <sys/immu.h> +# include <sys/region.h> + +# include <sys/mmap.h> +#else +# if !defined(Lynx) +# if !defined(__EMX__) +# include <sys/mman.h> +# endif +# else +# include <sys/types.h> +# include <errno.h> +# include <smem.h> +# endif +#endif +#include <sys/wait.h> +#include <signal.h> +#include <unistd.h> + +#if defined(SVR4) && !defined(sun) && !defined(SCO325) +#define DEV_MEM "/dev/pmem" +#elif defined(SVR4) && defined(sun) +#define DEV_MEM "/dev/xsvc" +#else +#define DEV_MEM "/dev/mem" +#endif + +typedef struct { + unsigned long physaddr; /* actual requested physical address */ + unsigned long size; /* actual requested map size */ + unsigned long delta; /* delta to account for page alignment */ + void * vaddr; /* mapped address, without the delta */ + int refcount; /* reference count */ +} MapRec, *MapPtr; + +typedef struct { + Display * display; + int screen; + MapPtr map; +} ScrRec, *ScrPtr; + +static int mapFd = -1; +static int numMaps = 0; +static int numScrs = 0; +static MapPtr *mapList = NULL; +static ScrPtr *scrList = NULL; + +static MapPtr +AddMap(void) +{ + MapPtr *old; + + old = mapList; + mapList = realloc(mapList, sizeof(MapPtr) * (numMaps + 1)); + if (!mapList) { + mapList = old; + return NULL; + } + mapList[numMaps] = malloc(sizeof(MapRec)); + if (!mapList[numMaps]) + return NULL; + return mapList[numMaps++]; +} + +static ScrPtr +AddScr(void) +{ + ScrPtr *old; + + old = scrList; + scrList = realloc(scrList, sizeof(ScrPtr) * (numScrs + 1)); + if (!scrList) { + scrList = old; + return NULL; + } + scrList[numScrs] = malloc(sizeof(ScrRec)); + if (!scrList[numScrs]) + return NULL; + return scrList[numScrs++]; +} + +static MapPtr +FindMap(unsigned long address, unsigned long size) +{ + int i; + + for (i = 0; i < numMaps; i++) { + if (mapList[i]->physaddr == address && + mapList[i]->size == size) + return mapList[i]; + } + return NULL; +} + +static ScrPtr +FindScr(Display *display, int screen) +{ + int i; + + for (i = 0; i < numScrs; i++) { + if (scrList[i]->display == display && + scrList[i]->screen == screen) + return scrList[i]; + } + return NULL; +} + +static void * +MapPhysAddress(unsigned long address, unsigned long size) +{ + unsigned long offset, delta; + int pagesize = -1; + void *vaddr; + MapPtr mp; +#if defined(ISC) && defined(HAS_SVR3_MMAP) + struct kd_memloc mloc; +#elif defined(__EMX__) + APIRET rc; + ULONG action; + HFILE hfd; +#endif + + if ((mp = FindMap(address, size))) { + mp->refcount++; + return (void *)((unsigned long)mp->vaddr + mp->delta); + } + +#if defined(_SC_PAGESIZE) && defined(HAS_SC_PAGESIZE) + pagesize = sysconf(_SC_PAGESIZE); +#endif +#ifdef _SC_PAGE_SIZE + if (pagesize == -1) + pagesize = sysconf(_SC_PAGE_SIZE); +#endif +#ifdef HAS_GETPAGESIZE + if (pagesize == -1) + pagesize = getpagesize(); +#endif +#ifdef PAGE_SIZE + if (pagesize == -1) + pagesize = PAGE_SIZE; +#endif + if (pagesize == -1) + pagesize = 4096; + + delta = address % pagesize; + offset = address - delta; + +#if defined(ISC) && defined(HAS_SVR3_MMAP) + if (mapFd < 0) { + if ((mapFd = open("/dev/mmap", O_RDWR)) < 0) + return NULL; + } + mloc.vaddr = (char *)0; + mloc.physaddr = (char *)offset; + mloc.length = size + delta; + mloc.ioflg=1; + + if ((vaddr = (void *)ioctl(mapFd, MAP, &mloc)) == (void *)-1) + return NULL; +#elif defined (__EMX__) + /* + * Dragon warning here! /dev/pmap$ is never closed, except on progam exit. + * Consecutive calling of this routine will make PMAP$ driver run out + * of memory handles. Some umap/close mechanism should be provided + */ + + rc = DosOpen("/dev/pmap$", &hfd, &action, 0, FILE_NORMAL, FILE_OPEN, + OPEN_ACCESS_READWRITE | OPEN_SHARE_DENYNONE, (PEAOP2)NULL); + if (rc != 0) + return NULL; + { + struct map_ioctl { + union { + ULONG phys; + void* user; + } a; + ULONG size; + } pmap,dmap; + ULONG plen,dlen; +#define XFREE86_PMAP 0x76 +#define PMAP_MAP 0x44 + + pmap.a.phys = offset; + pmap.size = size + delta; + rc = DosDevIOCtl(hfd, XFREE86_PMAP, PMAP_MAP, + (PULONG)&pmap, sizeof(pmap), &plen, + (PULONG)&dmap, sizeof(dmap), &dlen); + if (rc == 0) { + vaddr = dmap.a.user; + } + } + if (rc != 0) + return NULL; +#elif defined (Lynx) + vaddr = (void *)smem_create("XF86DGA", (char *)offset, + size + delta, SM_READ|SM_WRITE); +#else +#ifndef MAP_FILE +#define MAP_FILE 0 +#endif + if (mapFd < 0) { + if ((mapFd = open(DEV_MEM, O_RDWR)) < 0) + return NULL; + } + vaddr = (void *)mmap(NULL, size + delta, PROT_READ | PROT_WRITE, + MAP_FILE | MAP_SHARED, mapFd, (off_t)offset); + if (vaddr == (void *)-1) + return NULL; +#endif + + if (!vaddr) { + if (!(mp = AddMap())) + return NULL; + mp->physaddr = address; + mp->size = size; + mp->delta = delta; + mp->vaddr = vaddr; + mp->refcount = 1; + } + return (void *)((unsigned long)vaddr + delta); +} + +/* + * Still need to find a clean way of detecting the death of a DGA app + * and returning things to normal - Jon + * This is here to help debugging without rebooting... Also C-A-BS + * should restore text mode. + */ + +int +SDL_NAME(XF86DGAForkApp)(int screen) +{ + pid_t pid; + int status; + int i; + + /* fork the app, parent hangs around to clean up */ + if ((pid = fork()) > 0) { + ScrPtr sp; + + waitpid(pid, &status, 0); + for (i = 0; i < numScrs; i++) { + sp = scrList[i]; + SDL_NAME(XF86DGADirectVideoLL)(sp->display, sp->screen, 0); + XSync(sp->display, False); + } + if (WIFEXITED(status)) + _exit(0); + else + _exit(-1); + } + return pid; +} + + +Bool +SDL_NAME(XF86DGADirectVideo)( + Display *dis, + int screen, + int enable +){ + ScrPtr sp; + MapPtr mp = NULL; + + if ((sp = FindScr(dis, screen))) + mp = sp->map; + + if (enable & XF86DGADirectGraphics) { +#if !defined(ISC) && !defined(HAS_SVR3_MMAP) && !defined(Lynx) \ + && !defined(__EMX__) + if (mp && mp->vaddr) + mprotect(mp->vaddr, mp->size + mp->delta, PROT_READ | PROT_WRITE); +#endif + } else { +#if !defined(ISC) && !defined(HAS_SVR3_MMAP) && !defined(Lynx) \ + && !defined(__EMX__) + if (mp && mp->vaddr) + mprotect(mp->vaddr, mp->size + mp->delta, PROT_READ); +#elif defined(Lynx) + /* XXX this doesn't allow enable after disable */ + smem_create(NULL, mp->vaddr, mp->size + mp->delta, SM_DETACH); + smem_remove("XF86DGA"); +#endif + } + + SDL_NAME(XF86DGADirectVideoLL)(dis, screen, enable); + return 1; +} + + +static void +XF86cleanup(int sig) +{ + ScrPtr sp; + int i; + static char beenhere = 0; + + if (beenhere) + _exit(3); + beenhere = 1; + + for (i = 0; i < numScrs; i++) { + sp = scrList[i]; + SDL_NAME(XF86DGADirectVideo)(sp->display, sp->screen, 0); + XSync(sp->display, False); + } + _exit(3); +} + +Bool +SDL_NAME(XF86DGAGetVideo)( + Display *dis, + int screen, + char **addr, + int *width, + int *bank, + int *ram +){ + /*unsigned long*/ int offset; + static int beenHere = 0; + ScrPtr sp; + MapPtr mp; + + if (!(sp = FindScr(dis, screen))) { + if (!(sp = AddScr())) { + fprintf(stderr, "XF86DGAGetVideo: malloc failure\n"); + exit(-2); + } + sp->display = dis; + sp->screen = screen; + sp->map = NULL; + } + + SDL_NAME(XF86DGAGetVideoLL)(dis, screen , &offset, width, bank, ram); + + *addr = MapPhysAddress(offset, *bank); + if (*addr == NULL) { + fprintf(stderr, "XF86DGAGetVideo: failed to map video memory (%s)\n", + strerror(errno)); + exit(-2); + } + + if ((mp = FindMap(offset, *bank))) + sp->map = mp; + + if (!beenHere) { + beenHere = 1; + atexit((void(*)(void))XF86cleanup); + /* one shot XF86cleanup attempts */ + signal(SIGSEGV, XF86cleanup); +#ifdef SIGBUS + signal(SIGBUS, XF86cleanup); +#endif + signal(SIGHUP, XF86cleanup); + signal(SIGFPE, XF86cleanup); + } + + return 1; +} + diff --git a/3rdparty/SDL/src/video/Xext/Xxf86dga/XF86DGA2.c b/3rdparty/SDL/src/video/Xext/Xxf86dga/XF86DGA2.c new file mode 100644 index 0000000..11d4fdd --- /dev/null +++ b/3rdparty/SDL/src/video/Xext/Xxf86dga/XF86DGA2.c @@ -0,0 +1,993 @@ +/* $XFree86: xc/lib/Xxf86dga/XF86DGA2.c,v 1.18 2001/08/17 13:27:51 dawes Exp $ */ +/* + +Copyright (c) 1995 Jon Tombs +Copyright (c) 1995,1996 The XFree86 Project, Inc + +*/ + +/* THIS IS NOT AN X CONSORTIUM STANDARD */ + +#ifdef __EMX__ /* needed here to override certain constants in X headers */ +#define INCL_DOS +#define INCL_DOSIOCTL +#include <os2.h> +#endif + +#define NEED_EVENTS +#define NEED_REPLIES + +/* Apparently some X11 systems can't include this multiple times... */ +#ifndef SDL_INCLUDED_XLIBINT_H +#define SDL_INCLUDED_XLIBINT_H 1 +#include <X11/Xlibint.h> +#endif + +#include "../extensions/xf86dga.h" +#include "../extensions/xf86dgastr.h" +#include "../extensions/Xext.h" +#include "../extensions/extutil.h" +#include <stdio.h> + +#if defined(ENABLE_FBCON) /* Needed for framebuffer console support */ +#include <sys/ioctl.h> +#include <linux/fb.h> +#endif + +/* If you change this, change the Bases[] array below as well */ +#define MAX_HEADS 16 + +char *SDL_NAME(xdga_extension_name) = XF86DGANAME; + +static XExtensionInfo _xdga_info_data; +static XExtensionInfo *xdga_info = &_xdga_info_data; + + +Bool SDL_NAME(XDGAMapFramebuffer)(int, char *, unsigned char*, CARD32, CARD32, CARD32); +void SDL_NAME(XDGAUnmapFramebuffer)(int); +unsigned char* SDL_NAME(XDGAGetMappedMemory)(int); + +#define XDGACheckExtension(dpy,i,val) \ + XextCheckExtension (dpy, i, SDL_NAME(xdga_extension_name), val) + +/***************************************************************************** + * * + * private utility routines * + * * + *****************************************************************************/ + +static int xdga_close_display(Display *dpy, XExtCodes *codes); +static Bool xdga_wire_to_event(Display *dpy, XEvent *event, xEvent *wire_ev); +static Status xdga_event_to_wire(Display *dpy, XEvent *event, xEvent *wire_ev); + +static XExtensionHooks xdga_extension_hooks = { + NULL, /* create_gc */ + NULL, /* copy_gc */ + NULL, /* flush_gc */ + NULL, /* free_gc */ + NULL, /* create_font */ + NULL, /* free_font */ + xdga_close_display, /* close_display */ + xdga_wire_to_event, /* wire_to_event */ + xdga_event_to_wire, /* event_to_wire */ + NULL, /* error */ + NULL, /* error_string */ +}; + +static XEXT_GENERATE_CLOSE_DISPLAY (xdga_close_display, xdga_info) + + +XEXT_GENERATE_FIND_DISPLAY (SDL_NAME(xdga_find_display), xdga_info, + "XFree86-DGA", + &xdga_extension_hooks, + 0, NULL) + + +static Status +xdga_event_to_wire( + Display *dpy, + XEvent *event, + xEvent *wire_ev +){ + return True; +} + +static Bool +xdga_wire_to_event( + Display *dpy, + XEvent *event, + xEvent *wire_ev +){ + dgaEvent *wire = (dgaEvent *) wire_ev; + SDL_NAME(XDGAButtonEvent) *bevent; + SDL_NAME(XDGAKeyEvent) *kevent; + SDL_NAME(XDGAMotionEvent) *mevent; + XExtDisplayInfo *info = SDL_NAME(xdga_find_display) (dpy); + + XDGACheckExtension (dpy, info, False); + + switch((wire->u.u.type & 0x7f) - info->codes->first_event) { + case MotionNotify: + mevent = (SDL_NAME(XDGAMotionEvent)*)event; + mevent->type = wire->u.u.type & 0x7F; + mevent->serial = _XSetLastRequestRead(dpy, (xGenericReply *)wire); + mevent->display = dpy; + mevent->screen = wire->u.event.screen; + mevent->time = wire->u.event.time; + mevent->state = wire->u.event.state; + mevent->dx = wire->u.event.dx; + mevent->dy = wire->u.event.dy; + return True; + case ButtonPress: + case ButtonRelease: + bevent = (SDL_NAME(XDGAButtonEvent)*)event; + bevent->type = wire->u.u.type & 0x7F; + bevent->serial = _XSetLastRequestRead(dpy, (xGenericReply *)wire); + bevent->display = dpy; + bevent->screen = wire->u.event.screen; + bevent->time = wire->u.event.time; + bevent->state = wire->u.event.state; + bevent->button = wire->u.u.detail; + return True; + case KeyPress: + case KeyRelease: + kevent = (SDL_NAME(XDGAKeyEvent)*)event; + kevent->type = wire->u.u.type & 0x7F; + kevent->serial = _XSetLastRequestRead(dpy, (xGenericReply *)wire); + kevent->display = dpy; + kevent->screen = wire->u.event.screen; + kevent->time = wire->u.event.time; + kevent->state = wire->u.event.state; + kevent->keycode = wire->u.u.detail; + return True; + } + + return False; +} + + +Bool SDL_NAME(XDGAQueryExtension) ( + Display *dpy, + int *event_basep, + int *error_basep +){ + XExtDisplayInfo *info = SDL_NAME(xdga_find_display) (dpy); + + if (XextHasExtension(info)) { + *event_basep = info->codes->first_event; + *error_basep = info->codes->first_error; + return True; + } else { + return False; + } +} + + +Bool SDL_NAME(XDGAQueryVersion)( + Display *dpy, + int *majorVersion, + int *minorVersion +){ + XExtDisplayInfo *info = SDL_NAME(xdga_find_display) (dpy); + xXDGAQueryVersionReply rep; + xXDGAQueryVersionReq *req; + + XDGACheckExtension (dpy, info, False); + + LockDisplay(dpy); + GetReq(XDGAQueryVersion, req); + req->reqType = info->codes->major_opcode; + req->dgaReqType = X_XDGAQueryVersion; + if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) { + UnlockDisplay(dpy); + SyncHandle(); + return False; + } + *majorVersion = rep.majorVersion; + *minorVersion = rep.minorVersion; + UnlockDisplay(dpy); + SyncHandle(); + if (*majorVersion >= 2) + { + int i, j; + + for (i = 0, j = info->codes->first_event; + i < XF86DGANumberEvents; + i++, j++) + { + XESetWireToEvent(dpy, j, xdga_wire_to_event); + XESetEventToWire(dpy, j, xdga_event_to_wire); + } + SDL_NAME(XDGASetClientVersion)(dpy); + } + return True; +} + +Bool SDL_NAME(XDGASetClientVersion)( + Display *dpy +){ + XExtDisplayInfo *info = SDL_NAME(xdga_find_display) (dpy); + xXDGASetClientVersionReq *req; + + XDGACheckExtension (dpy, info, False); + + LockDisplay(dpy); + GetReq(XDGASetClientVersion, req); + req->reqType = info->codes->major_opcode; + req->dgaReqType = X_XDGASetClientVersion; + req->major = XDGA_MAJOR_VERSION; + req->minor = XDGA_MINOR_VERSION; + UnlockDisplay(dpy); + SyncHandle(); + return True; +} + +Bool SDL_NAME(XDGAOpenFramebuffer)( + Display *dpy, + int screen +){ + XExtDisplayInfo *info = SDL_NAME(xdga_find_display) (dpy); + xXDGAOpenFramebufferReply rep; + xXDGAOpenFramebufferReq *req; + char *deviceName = NULL; + Bool ret; + + XDGACheckExtension (dpy, info, False); + + LockDisplay(dpy); + GetReq(XDGAOpenFramebuffer, req); + req->reqType = info->codes->major_opcode; + req->dgaReqType = X_XDGAOpenFramebuffer; + req->screen = screen; + if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) { + UnlockDisplay(dpy); + SyncHandle(); + return False; + } + + if(rep.length) { + deviceName = Xmalloc(rep.length << 2); + _XRead(dpy, deviceName, rep.length << 2); + } + + ret = SDL_NAME(XDGAMapFramebuffer)(screen, deviceName, + (unsigned char*)(long)rep.mem1, + rep.size, rep.offset, rep.extra); + + if(deviceName) + Xfree(deviceName); + + UnlockDisplay(dpy); + SyncHandle(); + return ret; +} + +void SDL_NAME(XDGACloseFramebuffer)( + Display *dpy, + int screen +){ + XExtDisplayInfo *info = SDL_NAME(xdga_find_display) (dpy); + xXDGACloseFramebufferReq *req; + + XextSimpleCheckExtension (dpy, info, SDL_NAME(xdga_extension_name)); + + SDL_NAME(XDGAUnmapFramebuffer)(screen); + + LockDisplay(dpy); + GetReq(XDGACloseFramebuffer, req); + req->reqType = info->codes->major_opcode; + req->dgaReqType = X_XDGACloseFramebuffer; + req->screen = screen; + UnlockDisplay(dpy); + SyncHandle(); +} + + + +SDL_NAME(XDGAMode)* SDL_NAME(XDGAQueryModes)( + Display *dpy, + int screen, + int *num +){ + XExtDisplayInfo *dinfo = SDL_NAME(xdga_find_display) (dpy); + xXDGAQueryModesReply rep; + xXDGAQueryModesReq *req; + SDL_NAME(XDGAMode) *modes = NULL; + + *num = 0; + + XDGACheckExtension (dpy, dinfo, NULL); + + LockDisplay(dpy); + GetReq(XDGAQueryModes, req); + req->reqType = dinfo->codes->major_opcode; + req->dgaReqType = X_XDGAQueryModes; + req->screen = screen; + + if (_XReply(dpy, (xReply *)&rep, 0, xFalse)) { + if(rep.length) { + xXDGAModeInfo info; + int i, size; + char *offset; + + size = rep.length << 2; + size -= rep.number * sz_xXDGAModeInfo; /* find text size */ + modes = (SDL_NAME(XDGAMode)*)Xmalloc((rep.number * sizeof(SDL_NAME(XDGAMode))) + size); + offset = (char*)(&modes[rep.number]); /* start of text */ + + + if(modes) { + for(i = 0; i < rep.number; i++) { + _XRead(dpy, (char*)(&info), sz_xXDGAModeInfo); + + modes[i].num = info.num; + modes[i].verticalRefresh = + (float)info.vsync_num / (float)info.vsync_den; + modes[i].flags = info.flags; + modes[i].imageWidth = info.image_width; + modes[i].imageHeight = info.image_height; + modes[i].pixmapWidth = info.pixmap_width; + modes[i].pixmapHeight = info.pixmap_height; + modes[i].bytesPerScanline = info.bytes_per_scanline; + modes[i].byteOrder = info.byte_order; + modes[i].depth = info.depth; + modes[i].bitsPerPixel = info.bpp; + modes[i].redMask = info.red_mask; + modes[i].greenMask = info.green_mask; + modes[i].blueMask = info.blue_mask; + modes[i].visualClass = info.visual_class; + modes[i].viewportWidth = info.viewport_width; + modes[i].viewportHeight = info.viewport_height; + modes[i].xViewportStep = info.viewport_xstep; + modes[i].yViewportStep = info.viewport_ystep; + modes[i].maxViewportX = info.viewport_xmax; + modes[i].maxViewportY = info.viewport_ymax; + modes[i].viewportFlags = info.viewport_flags; + modes[i].reserved1 = info.reserved1; + modes[i].reserved2 = info.reserved2; + + _XRead(dpy, offset, info.name_size); + modes[i].name = offset; + offset += info.name_size; + } + *num = rep.number; + } else + _XEatData(dpy, rep.length << 2); + } + } + + UnlockDisplay(dpy); + SyncHandle(); + + return modes; +} + + +SDL_NAME(XDGADevice) * +SDL_NAME(XDGASetMode)( + Display *dpy, + int screen, + int mode +){ + XExtDisplayInfo *dinfo = SDL_NAME(xdga_find_display) (dpy); + xXDGASetModeReply rep; + xXDGASetModeReq *req; + SDL_NAME(XDGADevice) *dev = NULL; + Pixmap pid; + + XDGACheckExtension (dpy, dinfo, NULL); + + LockDisplay(dpy); + GetReq(XDGASetMode, req); + req->reqType = dinfo->codes->major_opcode; + req->dgaReqType = X_XDGASetMode; + req->screen = screen; + req->mode = mode; + req->pid = pid = XAllocID(dpy); + + if (_XReply(dpy, (xReply *)&rep, 0, xFalse)) { + if(rep.length) { + xXDGAModeInfo info; + int size; + + size = rep.length << 2; + size -= sz_xXDGAModeInfo; /* get text size */ + + dev = (SDL_NAME(XDGADevice)*)Xmalloc(sizeof(SDL_NAME(XDGADevice)) + size); + + if(dev) { + _XRead(dpy, (char*)(&info), sz_xXDGAModeInfo); + + dev->mode.num = info.num; + dev->mode.verticalRefresh = + (float)info.vsync_num / (float)info.vsync_den; + dev->mode.flags = info.flags; + dev->mode.imageWidth = info.image_width; + dev->mode.imageHeight = info.image_height; + dev->mode.pixmapWidth = info.pixmap_width; + dev->mode.pixmapHeight = info.pixmap_height; + dev->mode.bytesPerScanline = info.bytes_per_scanline; + dev->mode.byteOrder = info.byte_order; + dev->mode.depth = info.depth; + dev->mode.bitsPerPixel = info.bpp; + dev->mode.redMask = info.red_mask; + dev->mode.greenMask = info.green_mask; + dev->mode.blueMask = info.blue_mask; + dev->mode.visualClass = info.visual_class; + dev->mode.viewportWidth = info.viewport_width; + dev->mode.viewportHeight = info.viewport_height; + dev->mode.xViewportStep = info.viewport_xstep; + dev->mode.yViewportStep = info.viewport_ystep; + dev->mode.maxViewportX = info.viewport_xmax; + dev->mode.maxViewportY = info.viewport_ymax; + dev->mode.viewportFlags = info.viewport_flags; + dev->mode.reserved1 = info.reserved1; + dev->mode.reserved2 = info.reserved2; + + dev->mode.name = (char*)(&dev[1]); + _XRead(dpy, dev->mode.name, info.name_size); + + dev->pixmap = (rep.flags & XDGAPixmap) ? pid : 0; + dev->data = SDL_NAME(XDGAGetMappedMemory)(screen); + + if(dev->data) + dev->data += rep.offset; + } + /* not sure what to do if the allocation fails */ + } + } + + UnlockDisplay(dpy); + SyncHandle(); + + return dev; +} + + +void SDL_NAME(XDGASetViewport)( + Display *dpy, + int screen, + int x, + int y, + int flags +){ + XExtDisplayInfo *info = SDL_NAME(xdga_find_display) (dpy); + xXDGASetViewportReq *req; + + XextSimpleCheckExtension (dpy, info, SDL_NAME(xdga_extension_name)); + + LockDisplay(dpy); + GetReq(XDGASetViewport, req); + req->reqType = info->codes->major_opcode; + req->dgaReqType = X_XDGASetViewport; + req->screen = screen; + req->x = x; + req->y = y; + req->flags = flags; + UnlockDisplay(dpy); + SyncHandle(); +} + + +void SDL_NAME(XDGAInstallColormap)( + Display *dpy, + int screen, + Colormap cmap +){ + XExtDisplayInfo *info = SDL_NAME(xdga_find_display) (dpy); + xXDGAInstallColormapReq *req; + + XextSimpleCheckExtension (dpy, info, SDL_NAME(xdga_extension_name)); + + LockDisplay(dpy); + GetReq(XDGAInstallColormap, req); + req->reqType = info->codes->major_opcode; + req->dgaReqType = X_XDGAInstallColormap; + req->screen = screen; + req->cmap = cmap; + UnlockDisplay(dpy); + SyncHandle(); +} + +void SDL_NAME(XDGASelectInput)( + Display *dpy, + int screen, + long mask +){ + XExtDisplayInfo *info = SDL_NAME(xdga_find_display) (dpy); + xXDGASelectInputReq *req; + + XextSimpleCheckExtension (dpy, info, SDL_NAME(xdga_extension_name)); + + LockDisplay(dpy); + GetReq(XDGASelectInput, req); + req->reqType = info->codes->major_opcode; + req->dgaReqType = X_XDGASelectInput; + req->screen = screen; + req->mask = mask; + UnlockDisplay(dpy); + SyncHandle(); +} + +void SDL_NAME(XDGAFillRectangle)( + Display *dpy, + int screen, + int x, + int y, + unsigned int width, + unsigned int height, + unsigned long color +){ + XExtDisplayInfo *info = SDL_NAME(xdga_find_display) (dpy); + xXDGAFillRectangleReq *req; + + XextSimpleCheckExtension (dpy, info, SDL_NAME(xdga_extension_name)); + + LockDisplay(dpy); + GetReq(XDGAFillRectangle, req); + req->reqType = info->codes->major_opcode; + req->dgaReqType = X_XDGAFillRectangle; + req->screen = screen; + req->x = x; + req->y = y; + req->width = width; + req->height = height; + req->color = color; + UnlockDisplay(dpy); + SyncHandle(); +} + +void SDL_NAME(XDGACopyArea)( + Display *dpy, + int screen, + int srcx, + int srcy, + unsigned int width, + unsigned int height, + int dstx, + int dsty +){ + XExtDisplayInfo *info = SDL_NAME(xdga_find_display) (dpy); + xXDGACopyAreaReq *req; + + XextSimpleCheckExtension (dpy, info, SDL_NAME(xdga_extension_name)); + + LockDisplay(dpy); + GetReq(XDGACopyArea, req); + req->reqType = info->codes->major_opcode; + req->dgaReqType = X_XDGACopyArea; + req->screen = screen; + req->srcx = srcx; + req->srcy = srcy; + req->width = width; + req->height = height; + req->dstx = dstx; + req->dsty = dsty; + UnlockDisplay(dpy); + SyncHandle(); +} + +void SDL_NAME(XDGACopyTransparentArea)( + Display *dpy, + int screen, + int srcx, + int srcy, + unsigned int width, + unsigned int height, + int dstx, + int dsty, + unsigned long key +){ + XExtDisplayInfo *info = SDL_NAME(xdga_find_display) (dpy); + xXDGACopyTransparentAreaReq *req; + + XextSimpleCheckExtension (dpy, info, SDL_NAME(xdga_extension_name)); + + LockDisplay(dpy); + GetReq(XDGACopyTransparentArea, req); + req->reqType = info->codes->major_opcode; + req->dgaReqType = X_XDGACopyTransparentArea; + req->screen = screen; + req->srcx = srcx; + req->srcy = srcy; + req->width = width; + req->height = height; + req->dstx = dstx; + req->dsty = dsty; + req->key = key; + UnlockDisplay(dpy); + SyncHandle(); +} + + +int SDL_NAME(XDGAGetViewportStatus)( + Display *dpy, + int screen +){ + XExtDisplayInfo *info = SDL_NAME(xdga_find_display) (dpy); + xXDGAGetViewportStatusReply rep; + xXDGAGetViewportStatusReq *req; + int status = 0; + + XDGACheckExtension (dpy, info, 0); + + LockDisplay(dpy); + GetReq(XDGAGetViewportStatus, req); + req->reqType = info->codes->major_opcode; + req->dgaReqType = X_XDGAGetViewportStatus; + req->screen = screen; + if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) + status = rep.status; + UnlockDisplay(dpy); + SyncHandle(); + return status; +} + +void SDL_NAME(XDGASync)( + Display *dpy, + int screen +){ + XExtDisplayInfo *info = SDL_NAME(xdga_find_display) (dpy); + xXDGASyncReply rep; + xXDGASyncReq *req; + + XextSimpleCheckExtension (dpy, info, SDL_NAME(xdga_extension_name)); + + LockDisplay(dpy); + GetReq(XDGASync, req); + req->reqType = info->codes->major_opcode; + req->dgaReqType = X_XDGASync; + req->screen = screen; + _XReply(dpy, (xReply *)&rep, 0, xFalse); + UnlockDisplay(dpy); + SyncHandle(); +} + + +void SDL_NAME(XDGAChangePixmapMode)( + Display *dpy, + int screen, + int *x, + int *y, + int mode +){ + XExtDisplayInfo *info = SDL_NAME(xdga_find_display) (dpy); + xXDGAChangePixmapModeReq *req; + xXDGAChangePixmapModeReply rep; + + XextSimpleCheckExtension (dpy, info, SDL_NAME(xdga_extension_name)); + + LockDisplay(dpy); + GetReq(XDGAChangePixmapMode, req); + req->reqType = info->codes->major_opcode; + req->dgaReqType = X_XDGAChangePixmapMode; + req->screen = screen; + req->x = *x; + req->y = *y; + req->flags = mode; + _XReply(dpy, (xReply *)&rep, 0, xFalse); + *x = rep.x; + *y = rep.y; + UnlockDisplay(dpy); + SyncHandle(); +} + +Colormap SDL_NAME(XDGACreateColormap)( + Display *dpy, + int screen, + SDL_NAME(XDGADevice) *dev, + int alloc +){ + XExtDisplayInfo *info = SDL_NAME(xdga_find_display) (dpy); + xXDGACreateColormapReq *req; + Colormap cid; + + XDGACheckExtension (dpy, info, -1); + + LockDisplay(dpy); + GetReq(XDGACreateColormap, req); + req->reqType = info->codes->major_opcode; + req->dgaReqType = X_XDGACreateColormap; + req->screen = screen; + req->mode = dev->mode.num; + req->alloc = alloc; + cid = req->id = XAllocID(dpy); + UnlockDisplay(dpy); + SyncHandle(); + + return cid; +} + + +void SDL_NAME(XDGAKeyEventToXKeyEvent)( + SDL_NAME(XDGAKeyEvent)* dk, + XKeyEvent* xk +){ + xk->type = dk->type; + xk->serial = dk->serial; + xk->send_event = False; + xk->display = dk->display; + xk->window = RootWindow(dk->display, dk->screen); + xk->root = xk->window; + xk->subwindow = None; + xk->time = dk->time; + xk->x = xk->y = xk->x_root = xk->y_root = 0; + xk->state = dk->state; + xk->keycode = dk->keycode; + xk->same_screen = True; +} + +#include <X11/Xmd.h> +#include <stdlib.h> +#include <stdio.h> +#include <fcntl.h> +#if defined(ISC) +# define HAS_SVR3_MMAP +# include <sys/types.h> +# include <errno.h> + +# include <sys/at_ansi.h> +# include <sys/kd.h> + +# include <sys/sysmacros.h> +# include <sys/immu.h> +# include <sys/region.h> + +# include <sys/mmap.h> +#else +# if !defined(Lynx) +# if !defined(__EMX__) +# include <sys/mman.h> +# endif +# else +# include <sys/types.h> +# include <errno.h> +# include <smem.h> +# endif +#endif +#include <sys/wait.h> +#include <signal.h> +#include <unistd.h> + +#if defined(SVR4) && !defined(sun) && !defined(SCO325) +#define DEV_MEM "/dev/pmem" +#elif defined(SVR4) && defined(sun) +#define DEV_MEM "/dev/xsvc" +#else +#define DEV_MEM "/dev/mem" +#endif + + + +typedef struct _DGAMapRec{ + unsigned char *physical; + unsigned char *virtual; + CARD32 size; + int fd; + int screen; + struct _DGAMapRec *next; +} DGAMapRec, *DGAMapPtr; + +static Bool +DGAMapPhysical(int, char*, unsigned char*, CARD32, CARD32, CARD32, DGAMapPtr); +static void DGAUnmapPhysical(DGAMapPtr); + +static DGAMapPtr _Maps = NULL; + + +unsigned char* +SDL_NAME(XDGAGetMappedMemory)(int screen) +{ + DGAMapPtr pMap = _Maps; + unsigned char *pntr = NULL; + + while(pMap != NULL) { + if(pMap->screen == screen) { + pntr = pMap->virtual; + break; + } + pMap = pMap->next; + } + + return pntr; +} + +Bool +SDL_NAME(XDGAMapFramebuffer)( + int screen, + char *name, /* optional device name */ + unsigned char* base, /* physical memory */ + CARD32 size, /* size */ + CARD32 offset, /* optional offset */ + CARD32 extra /* optional extra data */ +){ + DGAMapPtr pMap = _Maps; + Bool result; + + /* is it already mapped ? */ + while(pMap != NULL) { + if(pMap->screen == screen) + return True; + pMap = pMap->next; + } + + if(extra & XDGANeedRoot) { + /* we should probably check if we have root permissions and + return False here */ + + } + + pMap = (DGAMapPtr)Xmalloc(sizeof(DGAMapRec)); + + result = DGAMapPhysical(screen, name, base, size, offset, extra, pMap); + + if(result) { + pMap->next = _Maps; + _Maps = pMap; + } else + Xfree(pMap); + + return result; +} + +void +SDL_NAME(XDGAUnmapFramebuffer)(int screen) +{ + DGAMapPtr pMap = _Maps; + DGAMapPtr pPrev = NULL; + + /* is it already mapped */ + while(pMap != NULL) { + if(pMap->screen == screen) + break; + pPrev = pMap; + pMap = pMap->next; + } + + if(!pMap) + return; + + DGAUnmapPhysical(pMap); + + if(!pPrev) + _Maps = pMap->next; + else + pPrev->next = pMap->next; + + Xfree(pMap); +} + + +static Bool +DGAMapPhysical( + int screen, + char *name, /* optional device name */ + unsigned char* base, /* physical memory */ + CARD32 size, /* size */ + CARD32 offset, /* optional offset */ + CARD32 extra, /* optional extra data */ + DGAMapPtr pMap +) { +#if defined(ISC) && defined(HAS_SVR3_MMAP) + struct kd_memloc mloc; +#elif defined(__EMX__) + APIRET rc; + ULONG action; + HFILE hfd; +#endif + + base += offset; + + pMap->screen = screen; + pMap->physical = base; + pMap->size = size; + +#if defined(ISC) && defined(HAS_SVR3_MMAP) + if ((pMap->fd = open("/dev/mmap", O_RDWR)) < 0) + return False; + mloc.vaddr = (char *)0; + mloc.physaddr = (char *)base; + mloc.length = size; + mloc.ioflg=1; + + if ((pMap->virtual = (void *)ioctl(pMap->fd, MAP, &mloc)) == (void *)-1) + return False; +#elif defined (__EMX__) + /* + * Dragon warning here! /dev/pmap$ is never closed, except on progam exit. + * Consecutive calling of this routine will make PMAP$ driver run out + * of memory handles. Some umap/close mechanism should be provided + */ + + rc = DosOpen("/dev/pmap$", &hfd, &action, 0, FILE_NORMAL, FILE_OPEN, + OPEN_ACCESS_READWRITE | OPEN_SHARE_DENYNONE, (PEAOP2)NULL); + if (rc != 0) + return False; + { + struct map_ioctl { + union { + ULONG phys; + void* user; + } a; + ULONG size; + } pmap,dmap; + ULONG plen,dlen; +#define XFREE86_PMAP 0x76 +#define PMAP_MAP 0x44 + + pmap.a.phys = base; + pmap.size = size; + rc = DosDevIOCtl(hfd, XFREE86_PMAP, PMAP_MAP, + (PULONG)&pmap, sizeof(pmap), &plen, + (PULONG)&dmap, sizeof(dmap), &dlen); + if (rc == 0) { + pMap->virtual = dmap.a.user; + } + } + if (rc != 0) + return False; +#elif defined (Lynx) + pMap->virtual = smem_create("XF86DGA", (char*)base, size, SM_READ|SM_WRITE); +#else +#ifndef MAP_FILE +#define MAP_FILE 0 +#endif + if (!name) + name = DEV_MEM; + if ((pMap->fd = open(name, O_RDWR)) < 0) +#if defined(ENABLE_FBCON) + { /* /dev/fb0 fallback added by Sam Lantinga <hercules@lokigames.com> */ + /* Try to fall back to /dev/fb on Linux - FIXME: verify the device */ + struct fb_fix_screeninfo finfo; + + if ((pMap->fd = open("/dev/fb0", O_RDWR)) < 0) { + return False; + } + /* The useable framebuffer console memory may not be the whole + framebuffer that X has access to. :-( + */ + if ( ioctl(pMap->fd, FBIOGET_FSCREENINFO, &finfo) < 0 ) { + close(pMap->fd); + return False; + } + /* Warning: On PPC, the size and virtual need to be offset by: + (((long)finfo.smem_start) - + (((long)finfo.smem_start)&~(PAGE_SIZE-1))) + */ + base = 0; + size = pMap->size = finfo.smem_len; + } +#else + return False; +#endif + pMap->virtual = mmap(NULL, size, PROT_READ | PROT_WRITE, + MAP_FILE | MAP_SHARED, pMap->fd, (off_t)((size_t)base)); + if (pMap->virtual == (void *)-1) + return False; +#endif + +#if !defined(ISC) && !defined(HAS_SVR3_MMAP) && !defined(Lynx) \ + && !defined(__EMX__) + mprotect(pMap->virtual, size, PROT_READ | PROT_WRITE); +#endif + + return True; +} + + + +static void +DGAUnmapPhysical(DGAMapPtr pMap) +{ +#if !defined(ISC) && !defined(HAS_SVR3_MMAP) && !defined(Lynx) \ + && !defined(__EMX__) + mprotect(pMap->virtual,pMap->size, PROT_READ); +#elif defined(Lynx) + /* XXX this doesn't allow enable after disable */ + smem_create(NULL, pMap->virtual, pMap->size, SM_DETACH); + smem_remove("XF86DGA"); +#endif + + + /* We need to unmap and close too !!!!!!!!!!*/ +} diff --git a/3rdparty/SDL/src/video/Xext/Xxf86vm/XF86VMode.c b/3rdparty/SDL/src/video/Xext/Xxf86vm/XF86VMode.c new file mode 100644 index 0000000..5cb2190 --- /dev/null +++ b/3rdparty/SDL/src/video/Xext/Xxf86vm/XF86VMode.c @@ -0,0 +1,1226 @@ +/* $XConsortium: XF86VMode.c /main/2 1995/11/14 18:17:58 kaleb $ */ +/* $XFree86: xc/lib/Xxf86vm/XF86VMode.c,v 3.32 2001/07/25 15:04:54 dawes Exp $ */ +/* + +Copyright (c) 1995 Kaleb S. KEITHLEY + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL Kaleb S. KEITHLEY BE LIABLE FOR ANY CLAIM, DAMAGES +OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of Kaleb S. KEITHLEY +shall not be used in advertising or otherwise to promote the sale, use +or other dealings in this Software without prior written authorization +from Kaleb S. KEITHLEY. + +*/ +/* $XConsortium: XF86VMode.c /main/4 1996/01/16 07:52:25 kaleb CHECKEDOUT $ */ + +/* THIS IS NOT AN X CONSORTIUM STANDARD */ + +#define NEED_EVENTS +#define NEED_REPLIES + +#ifndef XBUILD_IN_CLIENT +/* Apparently some X11 systems can't include this multiple times... */ +#ifndef SDL_INCLUDED_XLIBINT_H +#define SDL_INCLUDED_XLIBINT_H 1 +#include <X11/Xlibint.h> +#endif +#include "../extensions/xf86vmstr.h" +#include "../extensions/Xext.h" +#include "../extensions/extutil.h" +#else +#include "include/extensions/xf86vmstr.h" +#include "include/extensions/Xext.h" +#include "include/extensions/extutil.h" +#endif + +#ifdef DEBUG +#include <stdio.h> +#endif + +#ifndef MODE_BAD +#define MODE_BAD 255 +#endif + +static XExtensionInfo _xf86vidmode_info_data; +static XExtensionInfo *xf86vidmode_info = &_xf86vidmode_info_data; +static char *xf86vidmode_extension_name = XF86VIDMODENAME; + +#define XF86VidModeCheckExtension(dpy,i,val) \ + XextCheckExtension (dpy, i, xf86vidmode_extension_name, val) + +/***************************************************************************** + * * + * private utility routines * + * * + *****************************************************************************/ + +static XEXT_CLOSE_DISPLAY_PROTO(close_display); +static /* const */ XExtensionHooks xf86vidmode_extension_hooks = { + NULL, /* create_gc */ + NULL, /* copy_gc */ + NULL, /* flush_gc */ + NULL, /* free_gc */ + NULL, /* create_font */ + NULL, /* free_font */ + close_display, /* close_display */ + NULL, /* wire_to_event */ + NULL, /* event_to_wire */ + NULL, /* error */ + NULL, /* error_string */ +}; + +static XEXT_GENERATE_FIND_DISPLAY (find_display, xf86vidmode_info, + xf86vidmode_extension_name, + &xf86vidmode_extension_hooks, + 0, NULL) + +static XEXT_GENERATE_CLOSE_DISPLAY (close_display, xf86vidmode_info) + + +/***************************************************************************** + * * + * public XFree86-VidMode Extension routines * + * * + *****************************************************************************/ + +Bool +SDL_NAME(XF86VidModeQueryExtension) (dpy, event_basep, error_basep) + Display *dpy; + int *event_basep, *error_basep; +{ + XExtDisplayInfo *info = find_display (dpy); + + if (XextHasExtension(info)) { + *event_basep = info->codes->first_event; + *error_basep = info->codes->first_error; + return True; + } else { + return False; + } +} + +Bool +SDL_NAME(XF86VidModeQueryVersion)(dpy, majorVersion, minorVersion) + Display* dpy; + int* majorVersion; + int* minorVersion; +{ + XExtDisplayInfo *info = find_display (dpy); + xXF86VidModeQueryVersionReply rep; + xXF86VidModeQueryVersionReq *req; + + XF86VidModeCheckExtension (dpy, info, False); + + LockDisplay(dpy); + GetReq(XF86VidModeQueryVersion, req); + req->reqType = info->codes->major_opcode; + req->xf86vidmodeReqType = X_XF86VidModeQueryVersion; + if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) { + UnlockDisplay(dpy); + SyncHandle(); + return False; + } + *majorVersion = rep.majorVersion; + *minorVersion = rep.minorVersion; + UnlockDisplay(dpy); + SyncHandle(); + if (*majorVersion >= 2) + SDL_NAME(XF86VidModeSetClientVersion)(dpy); + return True; +} + +Bool +SDL_NAME(XF86VidModeSetClientVersion)(Display *dpy) +{ + XExtDisplayInfo *info = find_display(dpy); + xXF86VidModeSetClientVersionReq *req; + + XF86VidModeCheckExtension(dpy, info, False); + + LockDisplay(dpy); + GetReq(XF86VidModeSetClientVersion, req); + req->reqType = info->codes->major_opcode; + req->xf86vidmodeReqType = X_XF86VidModeSetClientVersion; + req->major = XF86VIDMODE_MAJOR_VERSION; + req->minor = XF86VIDMODE_MINOR_VERSION; + UnlockDisplay(dpy); + SyncHandle(); + return True; +} + +Bool +SDL_NAME(XF86VidModeSetGamma)(Display *dpy, int screen, SDL_NAME(XF86VidModeGamma) *Gamma) +{ + XExtDisplayInfo *info = find_display(dpy); + xXF86VidModeSetGammaReq *req; + + XF86VidModeCheckExtension(dpy, info, False); + + LockDisplay(dpy); + GetReq(XF86VidModeSetGamma, req); + req->reqType = info->codes->major_opcode; + req->xf86vidmodeReqType = X_XF86VidModeSetGamma; + req->screen = screen; + req->red = (CARD32)(Gamma->red * 10000.); + req->green = (CARD32)(Gamma->green * 10000.); + req->blue = (CARD32)(Gamma->blue * 10000.); + UnlockDisplay(dpy); + SyncHandle(); + return True; +} + +Bool +SDL_NAME(XF86VidModeGetGamma)(Display *dpy, int screen, SDL_NAME(XF86VidModeGamma) *Gamma) +{ + XExtDisplayInfo *info = find_display (dpy); + xXF86VidModeGetGammaReply rep; + xXF86VidModeGetGammaReq *req; + + XF86VidModeCheckExtension (dpy, info, False); + + LockDisplay(dpy); + GetReq(XF86VidModeGetGamma, req); + req->reqType = info->codes->major_opcode; + req->xf86vidmodeReqType = X_XF86VidModeGetGamma; + req->screen = screen; + if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) { + UnlockDisplay(dpy); + SyncHandle(); + return False; + } + Gamma->red = ((float)rep.red) / 10000.; + Gamma->green = ((float)rep.green) / 10000.; + Gamma->blue = ((float)rep.blue) / 10000.; + UnlockDisplay(dpy); + SyncHandle(); + return True; +} + +Bool +SDL_NAME(XF86VidModeGetModeLine)(dpy, screen, dotclock, modeline) + Display* dpy; + int screen; + int* dotclock; + SDL_NAME(XF86VidModeModeLine)* modeline; +{ + XExtDisplayInfo *info = find_display (dpy); + xXF86VidModeGetModeLineReply rep; + xXF86OldVidModeGetModeLineReply oldrep; + xXF86VidModeGetModeLineReq *req; + int majorVersion, minorVersion; + + XF86VidModeCheckExtension (dpy, info, False); + SDL_NAME(XF86VidModeQueryVersion)(dpy, &majorVersion, &minorVersion); + + LockDisplay(dpy); + GetReq(XF86VidModeGetModeLine, req); + req->reqType = info->codes->major_opcode; + req->xf86vidmodeReqType = X_XF86VidModeGetModeLine; + req->screen = screen; + + if (majorVersion < 2) { + if (!_XReply(dpy, (xReply *)&oldrep, + (SIZEOF(xXF86OldVidModeGetModeLineReply) - SIZEOF(xReply)) >> 2, xFalse)) { + UnlockDisplay(dpy); + SyncHandle(); + return False; + } + *dotclock = oldrep.dotclock; + modeline->hdisplay = oldrep.hdisplay; + modeline->hsyncstart = oldrep.hsyncstart; + modeline->hsyncend = oldrep.hsyncend; + modeline->htotal = oldrep.htotal; + modeline->hskew = 0; + modeline->vdisplay = oldrep.vdisplay; + modeline->vsyncstart = oldrep.vsyncstart; + modeline->vsyncend = oldrep.vsyncend; + modeline->vtotal = oldrep.vtotal; + modeline->flags = oldrep.flags; + modeline->privsize = oldrep.privsize; + } else { + if (!_XReply(dpy, (xReply *)&rep, + (SIZEOF(xXF86VidModeGetModeLineReply) - SIZEOF(xReply)) >> 2, xFalse)) { + UnlockDisplay(dpy); + SyncHandle(); + return False; + } + *dotclock = rep.dotclock; + modeline->hdisplay = rep.hdisplay; + modeline->hsyncstart = rep.hsyncstart; + modeline->hsyncend = rep.hsyncend; + modeline->htotal = rep.htotal; + modeline->hskew = rep.hskew; + modeline->vdisplay = rep.vdisplay; + modeline->vsyncstart = rep.vsyncstart; + modeline->vsyncend = rep.vsyncend; + modeline->vtotal = rep.vtotal; + modeline->flags = rep.flags; + modeline->privsize = rep.privsize; + } + + if (modeline->privsize > 0) { + if (!(modeline->private = Xcalloc(modeline->privsize, sizeof(INT32)))) { + _XEatData(dpy, (modeline->privsize) * sizeof(INT32)); + Xfree(modeline->private); + return False; + } + _XRead(dpy, (char*)modeline->private, modeline->privsize * sizeof(INT32)); + } else { + modeline->private = NULL; + } + UnlockDisplay(dpy); + SyncHandle(); + return True; +} + +Bool +SDL_NAME(XF86VidModeGetAllModeLines)(dpy, screen, modecount, modelinesPtr) + Display* dpy; + int screen; + int* modecount; + SDL_NAME(XF86VidModeModeInfo) ***modelinesPtr; +{ + XExtDisplayInfo *info = find_display (dpy); + xXF86VidModeGetAllModeLinesReply rep; + xXF86VidModeGetAllModeLinesReq *req; + SDL_NAME(XF86VidModeModeInfo) *mdinfptr, **modelines; + xXF86VidModeModeInfo xmdline; + xXF86OldVidModeModeInfo oldxmdline; + int i; + int majorVersion, minorVersion; + Bool protocolBug = False; + + XF86VidModeCheckExtension (dpy, info, False); + + /* + * Note: There was a bug in the protocol implementation in versions + * 0.x with x < 8 (the .private field wasn't being passed over the wire). + * Check the server's version, and accept the old format if appropriate. + */ + + SDL_NAME(XF86VidModeQueryVersion)(dpy, &majorVersion, &minorVersion); + if (majorVersion == 0 && minorVersion < 8) { + protocolBug = True; +#ifdef DEBUG + fprintf(stderr, "XF86VidModeGetAllModeLines: Warning: Xserver is" + "running an old version (%d.%d)\n", majorVersion, + minorVersion); +#endif + } + + LockDisplay(dpy); + GetReq(XF86VidModeGetAllModeLines, req); + req->reqType = info->codes->major_opcode; + req->xf86vidmodeReqType = X_XF86VidModeGetAllModeLines; + req->screen = screen; + if (!_XReply(dpy, (xReply *)&rep, + (SIZEOF(xXF86VidModeGetAllModeLinesReply) - SIZEOF(xReply)) >> 2, xFalse)) { + UnlockDisplay(dpy); + SyncHandle(); + return False; + } + + *modecount = rep.modecount; + + if (!(modelines = (SDL_NAME(XF86VidModeModeInfo) **) Xcalloc(rep.modecount, + sizeof(SDL_NAME(XF86VidModeModeInfo) *) + +sizeof(SDL_NAME(XF86VidModeModeInfo))))) { + if (majorVersion < 2) + _XEatData(dpy, (rep.modecount) * sizeof(xXF86OldVidModeModeInfo)); + else + _XEatData(dpy, (rep.modecount) * sizeof(xXF86VidModeModeInfo)); + Xfree(modelines); + UnlockDisplay(dpy); + SyncHandle(); + return False; + } + mdinfptr = (SDL_NAME(XF86VidModeModeInfo) *) ( + (char *) modelines + + rep.modecount*sizeof(SDL_NAME(XF86VidModeModeInfo) *) + ); + + for (i = 0; i < rep.modecount; i++) { + modelines[i] = mdinfptr++; + if (majorVersion < 2) { + _XRead(dpy, (char*)&oldxmdline, sizeof(xXF86OldVidModeModeInfo)); + modelines[i]->dotclock = oldxmdline.dotclock; + modelines[i]->hdisplay = oldxmdline.hdisplay; + modelines[i]->hsyncstart = oldxmdline.hsyncstart; + modelines[i]->hsyncend = oldxmdline.hsyncend; + modelines[i]->htotal = oldxmdline.htotal; + modelines[i]->hskew = 0; + modelines[i]->vdisplay = oldxmdline.vdisplay; + modelines[i]->vsyncstart = oldxmdline.vsyncstart; + modelines[i]->vsyncend = oldxmdline.vsyncend; + modelines[i]->vtotal = oldxmdline.vtotal; + modelines[i]->flags = oldxmdline.flags; + if (protocolBug) { + modelines[i]->privsize = 0; + modelines[i]->private = NULL; + } else { + modelines[i]->privsize = oldxmdline.privsize; + if (oldxmdline.privsize > 0) { + if (!(modelines[i]->private = + Xcalloc(oldxmdline.privsize, sizeof(INT32)))) { + _XEatData(dpy, (oldxmdline.privsize) * sizeof(INT32)); + Xfree(modelines[i]->private); + } else { + _XRead(dpy, (char*)modelines[i]->private, + oldxmdline.privsize * sizeof(INT32)); + } + } else { + modelines[i]->private = NULL; + } + } + } else { + _XRead(dpy, (char*)&xmdline, sizeof(xXF86VidModeModeInfo)); + modelines[i]->dotclock = xmdline.dotclock; + modelines[i]->hdisplay = xmdline.hdisplay; + modelines[i]->hsyncstart = xmdline.hsyncstart; + modelines[i]->hsyncend = xmdline.hsyncend; + modelines[i]->htotal = xmdline.htotal; + modelines[i]->hskew = xmdline.hskew; + modelines[i]->vdisplay = xmdline.vdisplay; + modelines[i]->vsyncstart = xmdline.vsyncstart; + modelines[i]->vsyncend = xmdline.vsyncend; + modelines[i]->vtotal = xmdline.vtotal; + modelines[i]->flags = xmdline.flags; + if (protocolBug) { + modelines[i]->privsize = 0; + modelines[i]->private = NULL; + } else { + modelines[i]->privsize = xmdline.privsize; + if (xmdline.privsize > 0) { + if (!(modelines[i]->private = + Xcalloc(xmdline.privsize, sizeof(INT32)))) { + _XEatData(dpy, (xmdline.privsize) * sizeof(INT32)); + Xfree(modelines[i]->private); + } else { + _XRead(dpy, (char*)modelines[i]->private, + xmdline.privsize * sizeof(INT32)); + } + } else { + modelines[i]->private = NULL; + } + } + } + } + *modelinesPtr = modelines; + UnlockDisplay(dpy); + SyncHandle(); + return True; +} + +/* + * GetReq replacement for use with VidMode protocols earlier than 2.0 + */ +#if !defined(UNIXCPP) || defined(ANSICPP) +#define GetOldReq(name, oldname, req) \ + WORD64ALIGN\ + if ((dpy->bufptr + SIZEOF(x##oldname##Req)) > dpy->bufmax)\ + _XFlush(dpy);\ + req = (x##oldname##Req *)(dpy->last_req = dpy->bufptr);\ + req->reqType = X_##name;\ + req->length = (SIZEOF(x##oldname##Req))>>2;\ + dpy->bufptr += SIZEOF(x##oldname##Req);\ + dpy->request++ + +#else /* non-ANSI C uses empty comment instead of "##" for token concatenation */ +#define GetOldReq(name, oldname, req) \ + WORD64ALIGN\ + if ((dpy->bufptr + SIZEOF(x/**/oldname/**/Req)) > dpy->bufmax)\ + _XFlush(dpy);\ + req = (x/**/oldname/**/Req *)(dpy->last_req = dpy->bufptr);\ + req->reqType = X_/**/name;\ + req->length = (SIZEOF(x/**/oldname/**/Req))>>2;\ + dpy->bufptr += SIZEOF(x/**/oldname/**/Req);\ + dpy->request++ +#endif + +Bool +SDL_NAME(XF86VidModeAddModeLine) (dpy, screen, newmodeline, aftermodeline) + Display *dpy; + int screen; + SDL_NAME(XF86VidModeModeInfo)* newmodeline; + SDL_NAME(XF86VidModeModeInfo)* aftermodeline; +{ + XExtDisplayInfo *info = find_display (dpy); + xXF86VidModeAddModeLineReq *req; + xXF86OldVidModeAddModeLineReq *oldreq; + int majorVersion, minorVersion; + + XF86VidModeCheckExtension (dpy, info, False); + SDL_NAME(XF86VidModeQueryVersion)(dpy, &majorVersion, &minorVersion); + + LockDisplay(dpy); + if (majorVersion < 2) { + GetOldReq(XF86VidModeAddModeLine, XF86OldVidModeAddModeLine, oldreq); + oldreq->reqType = info->codes->major_opcode; + oldreq->xf86vidmodeReqType = X_XF86VidModeAddModeLine; + oldreq->screen = screen; + oldreq->dotclock = newmodeline->dotclock; + oldreq->hdisplay = newmodeline->hdisplay; + oldreq->hsyncstart = newmodeline->hsyncstart; + oldreq->hsyncend = newmodeline->hsyncend; + oldreq->htotal = newmodeline->htotal; + oldreq->vdisplay = newmodeline->vdisplay; + oldreq->vsyncstart = newmodeline->vsyncstart; + oldreq->vsyncend = newmodeline->vsyncend; + oldreq->vtotal = newmodeline->vtotal; + oldreq->flags = newmodeline->flags; + oldreq->privsize = newmodeline->privsize; + if (aftermodeline != NULL) { + oldreq->after_dotclock = aftermodeline->dotclock; + oldreq->after_hdisplay = aftermodeline->hdisplay; + oldreq->after_hsyncstart = aftermodeline->hsyncstart; + oldreq->after_hsyncend = aftermodeline->hsyncend; + oldreq->after_htotal = aftermodeline->htotal; + oldreq->after_vdisplay = aftermodeline->vdisplay; + oldreq->after_vsyncstart = aftermodeline->vsyncstart; + oldreq->after_vsyncend = aftermodeline->vsyncend; + oldreq->after_vtotal = aftermodeline->vtotal; + oldreq->after_flags = aftermodeline->flags; + } else { + oldreq->after_dotclock = 0; + oldreq->after_hdisplay = 0; + oldreq->after_hsyncstart = 0; + oldreq->after_hsyncend = 0; + oldreq->after_htotal = 0; + oldreq->after_vdisplay = 0; + oldreq->after_vsyncstart = 0; + oldreq->after_vsyncend = 0; + oldreq->after_vtotal = 0; + oldreq->after_flags = 0; + } + if (newmodeline->privsize) { + oldreq->length += newmodeline->privsize; + Data32(dpy, (long *) newmodeline->private, + newmodeline->privsize * sizeof(INT32)); + } + } else { + GetReq(XF86VidModeAddModeLine, req); + req->reqType = info->codes->major_opcode; + req->xf86vidmodeReqType = X_XF86VidModeAddModeLine; + req->screen = screen; + req->dotclock = newmodeline->dotclock; + req->hdisplay = newmodeline->hdisplay; + req->hsyncstart = newmodeline->hsyncstart; + req->hsyncend = newmodeline->hsyncend; + req->htotal = newmodeline->htotal; + req->hskew = newmodeline->hskew; + req->vdisplay = newmodeline->vdisplay; + req->vsyncstart = newmodeline->vsyncstart; + req->vsyncend = newmodeline->vsyncend; + req->vtotal = newmodeline->vtotal; + req->flags = newmodeline->flags; + req->privsize = newmodeline->privsize; + if (aftermodeline != NULL) { + req->after_dotclock = aftermodeline->dotclock; + req->after_hdisplay = aftermodeline->hdisplay; + req->after_hsyncstart = aftermodeline->hsyncstart; + req->after_hsyncend = aftermodeline->hsyncend; + req->after_htotal = aftermodeline->htotal; + req->after_hskew = aftermodeline->hskew; + req->after_vdisplay = aftermodeline->vdisplay; + req->after_vsyncstart = aftermodeline->vsyncstart; + req->after_vsyncend = aftermodeline->vsyncend; + req->after_vtotal = aftermodeline->vtotal; + req->after_flags = aftermodeline->flags; + } else { + req->after_dotclock = 0; + req->after_hdisplay = 0; + req->after_hsyncstart = 0; + req->after_hsyncend = 0; + req->after_htotal = 0; + req->after_hskew = 0; + req->after_vdisplay = 0; + req->after_vsyncstart = 0; + req->after_vsyncend = 0; + req->after_vtotal = 0; + req->after_flags = 0; + } + if (newmodeline->privsize) { + req->length += newmodeline->privsize; + Data32(dpy, (long *) newmodeline->private, + newmodeline->privsize * sizeof(INT32)); + } + } + UnlockDisplay(dpy); + SyncHandle(); + return True; +} + +Bool +SDL_NAME(XF86VidModeDeleteModeLine) (dpy, screen, modeline) + Display *dpy; + int screen; + SDL_NAME(XF86VidModeModeInfo)* modeline; +{ + XExtDisplayInfo *info = find_display (dpy); + xXF86VidModeDeleteModeLineReq *req; + xXF86OldVidModeDeleteModeLineReq *oldreq; + int majorVersion, minorVersion; + + XF86VidModeCheckExtension (dpy, info, 0); + SDL_NAME(XF86VidModeQueryVersion)(dpy, &majorVersion, &minorVersion); + + LockDisplay(dpy); + if (majorVersion < 2) { + GetOldReq(XF86VidModeDeleteModeLine, XF86OldVidModeDeleteModeLine, oldreq); + oldreq->reqType = info->codes->major_opcode; + oldreq->xf86vidmodeReqType = X_XF86VidModeDeleteModeLine; + oldreq->screen = screen; + oldreq->dotclock = modeline->dotclock; + oldreq->hdisplay = modeline->hdisplay; + oldreq->hsyncstart = modeline->hsyncstart; + oldreq->hsyncend = modeline->hsyncend; + oldreq->htotal = modeline->htotal; + oldreq->vdisplay = modeline->vdisplay; + oldreq->vsyncstart = modeline->vsyncstart; + oldreq->vsyncend = modeline->vsyncend; + oldreq->vtotal = modeline->vtotal; + oldreq->flags = modeline->flags; + oldreq->privsize = modeline->privsize; + if (modeline->privsize) { + oldreq->length += modeline->privsize; + Data32(dpy, (long *) modeline->private, + modeline->privsize * sizeof(INT32)); + } + } else { + GetReq(XF86VidModeDeleteModeLine, req); + req->reqType = info->codes->major_opcode; + req->xf86vidmodeReqType = X_XF86VidModeDeleteModeLine; + req->screen = screen; + req->dotclock = modeline->dotclock; + req->hdisplay = modeline->hdisplay; + req->hsyncstart = modeline->hsyncstart; + req->hsyncend = modeline->hsyncend; + req->htotal = modeline->htotal; + req->hskew = modeline->hskew; + req->vdisplay = modeline->vdisplay; + req->vsyncstart = modeline->vsyncstart; + req->vsyncend = modeline->vsyncend; + req->vtotal = modeline->vtotal; + req->flags = modeline->flags; + req->privsize = modeline->privsize; + if (modeline->privsize) { + req->length += modeline->privsize; + Data32(dpy, (long *) modeline->private, + modeline->privsize * sizeof(INT32)); + } + } + UnlockDisplay(dpy); + SyncHandle(); + return True; +} + +Bool +SDL_NAME(XF86VidModeModModeLine) (dpy, screen, modeline) + Display *dpy; + int screen; + SDL_NAME(XF86VidModeModeLine)* modeline; +{ + XExtDisplayInfo *info = find_display (dpy); + xXF86VidModeModModeLineReq *req; + xXF86OldVidModeModModeLineReq *oldreq; + int majorVersion, minorVersion; + + XF86VidModeCheckExtension (dpy, info, 0); + SDL_NAME(XF86VidModeQueryVersion)(dpy, &majorVersion, &minorVersion); + + LockDisplay(dpy); + if (majorVersion < 2) { + GetOldReq(XF86VidModeModModeLine, XF86OldVidModeModModeLine, oldreq); + oldreq->reqType = info->codes->major_opcode; + oldreq->xf86vidmodeReqType = X_XF86VidModeModModeLine; + oldreq->screen = screen; + oldreq->hdisplay = modeline->hdisplay; + oldreq->hsyncstart = modeline->hsyncstart; + oldreq->hsyncend = modeline->hsyncend; + oldreq->htotal = modeline->htotal; + oldreq->vdisplay = modeline->vdisplay; + oldreq->vsyncstart = modeline->vsyncstart; + oldreq->vsyncend = modeline->vsyncend; + oldreq->vtotal = modeline->vtotal; + oldreq->flags = modeline->flags; + oldreq->privsize = modeline->privsize; + if (modeline->privsize) { + oldreq->length += modeline->privsize; + Data32(dpy, (long *) modeline->private, + modeline->privsize * sizeof(INT32)); + } + } else { + GetReq(XF86VidModeModModeLine, req); + req->reqType = info->codes->major_opcode; + req->xf86vidmodeReqType = X_XF86VidModeModModeLine; + req->screen = screen; + req->hdisplay = modeline->hdisplay; + req->hsyncstart = modeline->hsyncstart; + req->hsyncend = modeline->hsyncend; + req->htotal = modeline->htotal; + req->hskew = modeline->hskew; + req->vdisplay = modeline->vdisplay; + req->vsyncstart = modeline->vsyncstart; + req->vsyncend = modeline->vsyncend; + req->vtotal = modeline->vtotal; + req->flags = modeline->flags; + req->privsize = modeline->privsize; + if (modeline->privsize) { + req->length += modeline->privsize; + Data32(dpy, (long *) modeline->private, + modeline->privsize * sizeof(INT32)); + } + } + UnlockDisplay(dpy); + SyncHandle(); + return True; +} + +Status +SDL_NAME(XF86VidModeValidateModeLine) (dpy, screen, modeline) + Display *dpy; + int screen; + SDL_NAME(XF86VidModeModeInfo)* modeline; +{ + XExtDisplayInfo *info = find_display (dpy); + xXF86VidModeValidateModeLineReq *req; + xXF86OldVidModeValidateModeLineReq *oldreq; + xXF86VidModeValidateModeLineReply rep; + int majorVersion, minorVersion; + + XF86VidModeCheckExtension (dpy, info, 0); + SDL_NAME(XF86VidModeQueryVersion)(dpy, &majorVersion, &minorVersion); + + LockDisplay(dpy); + + if (majorVersion < 2) { + GetOldReq(XF86VidModeValidateModeLine, XF86OldVidModeValidateModeLine, oldreq); + oldreq->reqType = info->codes->major_opcode; + oldreq->xf86vidmodeReqType = X_XF86VidModeValidateModeLine; + oldreq->screen = screen; + oldreq->dotclock = modeline->dotclock; + oldreq->hdisplay = modeline->hdisplay; + oldreq->hsyncstart = modeline->hsyncstart; + oldreq->hsyncend = modeline->hsyncend; + oldreq->htotal = modeline->htotal; + oldreq->vdisplay = modeline->vdisplay; + oldreq->vsyncstart = modeline->vsyncstart; + oldreq->vsyncend = modeline->vsyncend; + oldreq->vtotal = modeline->vtotal; + oldreq->flags = modeline->flags; + oldreq->privsize = modeline->privsize; + if (modeline->privsize) { + oldreq->length += modeline->privsize; + Data32(dpy, (long *) modeline->private, + modeline->privsize * sizeof(INT32)); + } + } else { + GetReq(XF86VidModeValidateModeLine, req); + req->reqType = info->codes->major_opcode; + req->xf86vidmodeReqType = X_XF86VidModeValidateModeLine; + req->screen = screen; + req->dotclock = modeline->dotclock; + req->hdisplay = modeline->hdisplay; + req->hsyncstart = modeline->hsyncstart; + req->hsyncend = modeline->hsyncend; + req->htotal = modeline->htotal; + req->hskew = modeline->hskew; + req->vdisplay = modeline->vdisplay; + req->vsyncstart = modeline->vsyncstart; + req->vsyncend = modeline->vsyncend; + req->vtotal = modeline->vtotal; + req->flags = modeline->flags; + req->privsize = modeline->privsize; + if (modeline->privsize) { + req->length += modeline->privsize; + Data32(dpy, (long *) modeline->private, + modeline->privsize * sizeof(INT32)); + } + } + if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) { + UnlockDisplay(dpy); + SyncHandle(); + return MODE_BAD; + } + UnlockDisplay(dpy); + SyncHandle(); + return rep.status; +} + +Bool +SDL_NAME(XF86VidModeSwitchMode)(dpy, screen, zoom) + Display* dpy; + int screen; + int zoom; +{ + XExtDisplayInfo *info = find_display (dpy); + xXF86VidModeSwitchModeReq *req; + + XF86VidModeCheckExtension (dpy, info, False); + + LockDisplay(dpy); + GetReq(XF86VidModeSwitchMode, req); + req->reqType = info->codes->major_opcode; + req->xf86vidmodeReqType = X_XF86VidModeSwitchMode; + req->screen = screen; + req->zoom = zoom; + UnlockDisplay(dpy); + SyncHandle(); + return True; +} + +Bool +SDL_NAME(XF86VidModeSwitchToMode)(dpy, screen, modeline) + Display* dpy; + int screen; + SDL_NAME(XF86VidModeModeInfo)* modeline; +{ + XExtDisplayInfo *info = find_display (dpy); + xXF86VidModeSwitchToModeReq *req; + xXF86OldVidModeSwitchToModeReq *oldreq; + int majorVersion, minorVersion; + Bool protocolBug = False; + + XF86VidModeCheckExtension (dpy, info, False); + + /* + * Note: There was a bug in the protocol implementation in versions + * 0.x with x < 8 (the .private field wasn't expected to be sent over + * the wire). Check the server's version, and accept the old format + * if appropriate. + */ + + SDL_NAME(XF86VidModeQueryVersion)(dpy, &majorVersion, &minorVersion); + if (majorVersion == 0 && minorVersion < 8) { + protocolBug = True; +#ifdef DEBUG + fprintf(stderr, "XF86VidModeSwitchToMode: Warning: Xserver is" + "running an old version (%d.%d)\n", majorVersion, + minorVersion); +#endif + } + + LockDisplay(dpy); + if (majorVersion < 2) { + GetOldReq(XF86VidModeSwitchToMode, XF86OldVidModeSwitchToMode, oldreq); + oldreq->reqType = info->codes->major_opcode; + oldreq->xf86vidmodeReqType = X_XF86VidModeSwitchToMode; + oldreq->screen = screen; + oldreq->dotclock = modeline->dotclock; + oldreq->hdisplay = modeline->hdisplay; + oldreq->hsyncstart = modeline->hsyncstart; + oldreq->hsyncend = modeline->hsyncend; + oldreq->htotal = modeline->htotal; + oldreq->vdisplay = modeline->vdisplay; + oldreq->vsyncstart = modeline->vsyncstart; + oldreq->vsyncend = modeline->vsyncend; + oldreq->vtotal = modeline->vtotal; + oldreq->flags = modeline->flags; + if (protocolBug) { + oldreq->privsize = 0; + } else { + oldreq->privsize = modeline->privsize; + if (modeline->privsize) { + oldreq->length += modeline->privsize; + Data32(dpy, (long *) modeline->private, + modeline->privsize * sizeof(INT32)); + } + } + } else { + GetReq(XF86VidModeSwitchToMode, req); + req->reqType = info->codes->major_opcode; + req->xf86vidmodeReqType = X_XF86VidModeSwitchToMode; + req->screen = screen; + req->dotclock = modeline->dotclock; + req->hdisplay = modeline->hdisplay; + req->hsyncstart = modeline->hsyncstart; + req->hsyncend = modeline->hsyncend; + req->htotal = modeline->htotal; + req->hskew = modeline->hskew; + req->vdisplay = modeline->vdisplay; + req->vsyncstart = modeline->vsyncstart; + req->vsyncend = modeline->vsyncend; + req->vtotal = modeline->vtotal; + req->flags = modeline->flags; + if (protocolBug) { + req->privsize = 0; + } else { + req->privsize = modeline->privsize; + if (modeline->privsize) { + req->length += modeline->privsize; + Data32(dpy, (long *) modeline->private, + modeline->privsize * sizeof(INT32)); + } + } + } + UnlockDisplay(dpy); + SyncHandle(); + return True; +} + +Bool +SDL_NAME(XF86VidModeLockModeSwitch)(dpy, screen, lock) + Display* dpy; + int screen; + int lock; +{ + XExtDisplayInfo *info = find_display (dpy); + xXF86VidModeLockModeSwitchReq *req; + + XF86VidModeCheckExtension (dpy, info, False); + + LockDisplay(dpy); + GetReq(XF86VidModeLockModeSwitch, req); + req->reqType = info->codes->major_opcode; + req->xf86vidmodeReqType = X_XF86VidModeLockModeSwitch; + req->screen = screen; + req->lock = lock; + UnlockDisplay(dpy); + SyncHandle(); + return True; +} + +Bool +SDL_NAME(XF86VidModeGetMonitor)(dpy, screen, monitor) + Display* dpy; + int screen; + SDL_NAME(XF86VidModeMonitor)* monitor; +{ + XExtDisplayInfo *info = find_display (dpy); + xXF86VidModeGetMonitorReply rep; + xXF86VidModeGetMonitorReq *req; + CARD32 syncrange; + int i; + + XF86VidModeCheckExtension (dpy, info, False); + + LockDisplay(dpy); + GetReq(XF86VidModeGetMonitor, req); + req->reqType = info->codes->major_opcode; + req->xf86vidmodeReqType = X_XF86VidModeGetMonitor; + req->screen = screen; + if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) { + UnlockDisplay(dpy); + SyncHandle(); + return False; + } + monitor->nhsync = rep.nhsync; + monitor->nvsync = rep.nvsync; +#if 0 + monitor->bandwidth = (float)rep.bandwidth / 1e6; +#endif + if (rep.vendorLength) { + if (!(monitor->vendor = (char *)Xcalloc(rep.vendorLength + 1, 1))) { + _XEatData(dpy, (rep.nhsync + rep.nvsync) * 4 + + ((rep.vendorLength+3) & ~3) + ((rep.modelLength+3) & ~3)); + UnlockDisplay(dpy); + SyncHandle(); + return False; + } + } else { + monitor->vendor = NULL; + } + if (rep.modelLength) { + if (!(monitor->model = Xcalloc(rep.modelLength + 1, 1))) { + _XEatData(dpy, (rep.nhsync + rep.nvsync) * 4 + + ((rep.vendorLength+3) & ~3) + ((rep.modelLength+3) & ~3)); + if (monitor->vendor) + Xfree(monitor->vendor); + UnlockDisplay(dpy); + SyncHandle(); + return False; + } + } else { + monitor->model = NULL; + } + if (!(monitor->hsync = Xcalloc(rep.nhsync, sizeof(SDL_NAME(XF86VidModeSyncRange))))) { + _XEatData(dpy, (rep.nhsync + rep.nvsync) * 4 + + ((rep.vendorLength+3) & ~3) + ((rep.modelLength+3) & ~3)); + + if (monitor->vendor) + Xfree(monitor->vendor); + if (monitor->model) + Xfree(monitor->model); + UnlockDisplay(dpy); + SyncHandle(); + return False; + } + if (!(monitor->vsync = Xcalloc(rep.nvsync, sizeof(SDL_NAME(XF86VidModeSyncRange))))) { + _XEatData(dpy, (rep.nhsync + rep.nvsync) * 4 + + ((rep.vendorLength+3) & ~3) + ((rep.modelLength+3) & ~3)); + if (monitor->vendor) + Xfree(monitor->vendor); + if (monitor->model) + Xfree(monitor->model); + Xfree(monitor->hsync); + UnlockDisplay(dpy); + SyncHandle(); + return False; + } + for (i = 0; i < rep.nhsync; i++) { + _XRead(dpy, (char *)&syncrange, 4); + monitor->hsync[i].lo = (float)(syncrange & 0xFFFF) / 100.0; + monitor->hsync[i].hi = (float)(syncrange >> 16) / 100.0; + } + for (i = 0; i < rep.nvsync; i++) { + _XRead(dpy, (char *)&syncrange, 4); + monitor->vsync[i].lo = (float)(syncrange & 0xFFFF) / 100.0; + monitor->vsync[i].hi = (float)(syncrange >> 16) / 100.0; + } + if (rep.vendorLength) + _XReadPad(dpy, monitor->vendor, rep.vendorLength); + else + monitor->vendor = ""; + if (rep.modelLength) + _XReadPad(dpy, monitor->model, rep.modelLength); + else + monitor->model = ""; + + UnlockDisplay(dpy); + SyncHandle(); + return True; +} + +Bool +SDL_NAME(XF86VidModeGetViewPort)(dpy, screen, x, y) + Display* dpy; + int screen; + int *x, *y; +{ + XExtDisplayInfo *info = find_display (dpy); + xXF86VidModeGetViewPortReply rep; + xXF86VidModeGetViewPortReq *req; + int majorVersion, minorVersion; + Bool protocolBug = False; + + XF86VidModeCheckExtension (dpy, info, False); + + /* + * Note: There was a bug in the protocol implementation in versions + * 0.x with x < 8 (no reply was sent, so the client would hang) + * Check the server's version, and don't wait for a reply with older + * versions. + */ + + SDL_NAME(XF86VidModeQueryVersion)(dpy, &majorVersion, &minorVersion); + if (majorVersion == 0 && minorVersion < 8) { + protocolBug = True; +#ifdef DEBUG + fprintf(stderr, "XF86VidModeGetViewPort: Warning: Xserver is" + "running an old version (%d.%d)\n", majorVersion, + minorVersion); +#endif + } + LockDisplay(dpy); + GetReq(XF86VidModeGetViewPort, req); + req->reqType = info->codes->major_opcode; + req->xf86vidmodeReqType = X_XF86VidModeGetViewPort; + req->screen = screen; + if (protocolBug) { + *x = 0; + *y = 0; + } else { + if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) { + UnlockDisplay(dpy); + SyncHandle(); + return False; + } + *x = rep.x; + *y = rep.y; + } + + UnlockDisplay(dpy); + SyncHandle(); + return True; +} + +Bool +SDL_NAME(XF86VidModeSetViewPort)(dpy, screen, x, y) + Display* dpy; + int screen; + int x, y; +{ + XExtDisplayInfo *info = find_display (dpy); + xXF86VidModeSetViewPortReq *req; + + XF86VidModeCheckExtension (dpy, info, False); + + LockDisplay(dpy); + GetReq(XF86VidModeSetViewPort, req); + req->reqType = info->codes->major_opcode; + req->xf86vidmodeReqType = X_XF86VidModeSetViewPort; + req->screen = screen; + req->x = x; + req->y = y; + + UnlockDisplay(dpy); + SyncHandle(); + return True; +} + +Bool +SDL_NAME(XF86VidModeGetDotClocks)(dpy, screen, + flagsPtr, numclocksPtr, maxclocksPtr, clocksPtr) + Display* dpy; + int screen; + int *flagsPtr, *numclocksPtr, *maxclocksPtr, *clocksPtr[]; +{ + XExtDisplayInfo *info = find_display (dpy); + xXF86VidModeGetDotClocksReply rep; + xXF86VidModeGetDotClocksReq *req; + int i, *dotclocks; + CARD32 dotclk; + + XF86VidModeCheckExtension (dpy, info, False); + + LockDisplay(dpy); + GetReq(XF86VidModeGetDotClocks, req); + req->reqType = info->codes->major_opcode; + req->xf86vidmodeReqType = X_XF86VidModeGetDotClocks; + req->screen = screen; + if (!_XReply(dpy, (xReply *)&rep, + (SIZEOF(xXF86VidModeGetDotClocksReply) - SIZEOF(xReply)) >> 2, xFalse)) + { + UnlockDisplay(dpy); + SyncHandle(); + return False; + } + *numclocksPtr = rep.clocks; + *maxclocksPtr = rep.maxclocks; + *flagsPtr = rep.flags; + + if (!(dotclocks = (int*) Xcalloc(rep.clocks, sizeof(int)))) { + _XEatData(dpy, (rep.clocks) * 4); + Xfree(dotclocks); + UnlockDisplay(dpy); + SyncHandle(); + return False; + } + + for (i = 0; i < rep.clocks; i++) { + _XRead(dpy, (char*)&dotclk, 4); + dotclocks[i] = dotclk; + } + *clocksPtr = dotclocks; + UnlockDisplay(dpy); + SyncHandle(); + return True; +} + +Bool +SDL_NAME(XF86VidModeSetGammaRamp) ( + Display *dpy, + int screen, + int size, + unsigned short *red, + unsigned short *green, + unsigned short *blue +) +{ + int length = (size + 1) & ~1; + XExtDisplayInfo *info = find_display (dpy); + xXF86VidModeSetGammaRampReq *req; + + XF86VidModeCheckExtension (dpy, info, False); + LockDisplay(dpy); + GetReq(XF86VidModeSetGammaRamp, req); + req->reqType = info->codes->major_opcode; + req->xf86vidmodeReqType = X_XF86VidModeSetGammaRamp; + req->screen = screen; + req->length += (length >> 1) * 3; + req->size = size; + _XSend(dpy, (char*)red, size * 2); + _XSend(dpy, (char*)green, size * 2); + _XSend(dpy, (char*)blue, size * 2); + UnlockDisplay(dpy); + SyncHandle(); + return True; +} + + +Bool +SDL_NAME(XF86VidModeGetGammaRamp) ( + Display *dpy, + int screen, + int size, + unsigned short *red, + unsigned short *green, + unsigned short *blue +) +{ + XExtDisplayInfo *info = find_display (dpy); + xXF86VidModeGetGammaRampReq *req; + xXF86VidModeGetGammaRampReply rep; + + XF86VidModeCheckExtension (dpy, info, False); + + LockDisplay(dpy); + GetReq(XF86VidModeGetGammaRamp, req); + req->reqType = info->codes->major_opcode; + req->xf86vidmodeReqType = X_XF86VidModeGetGammaRamp; + req->screen = screen; + req->size = size; + if (!_XReply (dpy, (xReply *) &rep, 0, xFalse)) { + UnlockDisplay (dpy); + SyncHandle (); + return False; + } + if(rep.size) { + _XRead(dpy, (char*)red, rep.size << 1); + _XRead(dpy, (char*)green, rep.size << 1); + _XRead(dpy, (char*)blue, rep.size << 1); + } + + UnlockDisplay(dpy); + SyncHandle(); + return True; +} + +Bool SDL_NAME(XF86VidModeGetGammaRampSize)( + Display *dpy, + int screen, + int *size +) +{ + XExtDisplayInfo *info = find_display (dpy); + xXF86VidModeGetGammaRampSizeReq *req; + xXF86VidModeGetGammaRampSizeReply rep; + + *size = 0; + + XF86VidModeCheckExtension (dpy, info, False); + + LockDisplay(dpy); + GetReq(XF86VidModeGetGammaRampSize, req); + req->reqType = info->codes->major_opcode; + req->xf86vidmodeReqType = X_XF86VidModeGetGammaRampSize; + req->screen = screen; + if (!_XReply (dpy, (xReply *) &rep, 0, xTrue)) { + UnlockDisplay (dpy); + SyncHandle (); + return False; + } + *size = rep.size; + UnlockDisplay(dpy); + SyncHandle(); + return True; +} + diff --git a/3rdparty/SDL/src/video/Xext/extensions/Xext.h b/3rdparty/SDL/src/video/Xext/extensions/Xext.h new file mode 100644 index 0000000..9edf319 --- /dev/null +++ b/3rdparty/SDL/src/video/Xext/extensions/Xext.h @@ -0,0 +1,50 @@ +/* +Copyright 1989, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + */ +/* $XFree86: xc/include/extensions/Xext.h,v 1.7 2005/01/27 03:03:09 dawes Exp $ */ + +#ifndef _XEXT_H_ +#define _XEXT_H_ + +#include <X11/Xfuncproto.h> + +_XFUNCPROTOBEGIN + +typedef int (*XExtensionErrorHandler)(Display *, _Xconst char *, + _Xconst char *); + +extern XExtensionErrorHandler XSetExtensionErrorHandler( + XExtensionErrorHandler handler +); + +extern int XMissingExtension( + Display* /* dpy */, + _Xconst char* /* ext_name */ +); + +_XFUNCPROTOEND + +#define X_EXTENSION_UNKNOWN "unknown" +#define X_EXTENSION_MISSING "missing" + +#endif /* _XEXT_H_ */ diff --git a/3rdparty/SDL/src/video/Xext/extensions/Xinerama.h b/3rdparty/SDL/src/video/Xext/extensions/Xinerama.h new file mode 100644 index 0000000..54f2fe1 --- /dev/null +++ b/3rdparty/SDL/src/video/Xext/extensions/Xinerama.h @@ -0,0 +1,46 @@ +/* $XFree86: xc/include/extensions/Xinerama.h,v 3.2 2000/03/01 01:04:20 dawes Exp $ */ + +#ifndef _Xinerama_h +#define _Xinerama_h + +#include "SDL_name.h" + +typedef struct { + int screen_number; + short x_org; + short y_org; + short width; + short height; +} SDL_NAME(XineramaScreenInfo); + +Bool SDL_NAME(XineramaQueryExtension) ( + Display *dpy, + int *event_base, + int *error_base +); + +Status SDL_NAME(XineramaQueryVersion)( + Display *dpy, + int *major, + int *minor +); + +Bool SDL_NAME(XineramaIsActive)(Display *dpy); + + +/* + Returns the number of heads and a pointer to an array of + structures describing the position and size of the individual + heads. Returns NULL and number = 0 if Xinerama is not active. + + Returned array should be freed with XFree(). +*/ + +SDL_NAME(XineramaScreenInfo) * +SDL_NAME(XineramaQueryScreens)( + Display *dpy, + int *number +); + +#endif /* _Xinerama_h */ + diff --git a/3rdparty/SDL/src/video/Xext/extensions/Xv.h b/3rdparty/SDL/src/video/Xext/extensions/Xv.h new file mode 100644 index 0000000..a6a0271 --- /dev/null +++ b/3rdparty/SDL/src/video/Xext/extensions/Xv.h @@ -0,0 +1,129 @@ +/*********************************************************** +Copyright 1991 by Digital Equipment Corporation, Maynard, Massachusetts, +and the Massachusetts Institute of Technology, Cambridge, Massachusetts. + + All Rights Reserved + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation, and that the names of Digital or MIT not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR +ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +SOFTWARE. + +******************************************************************/ +/* $XFree86: xc/include/extensions/Xv.h,v 1.5 1999/12/11 19:28:48 mvojkovi Exp $ */ + +#ifndef XV_H +#define XV_H +/* +** File: +** +** Xv.h --- Xv shared library and server header file +** +** Author: +** +** David Carver (Digital Workstation Engineering/Project Athena) +** +** Revisions: +** +** 05.15.91 Carver +** - version 2.0 upgrade +** +** 01.24.91 Carver +** - version 1.4 upgrade +** +*/ + +#include <X11/X.h> + +#define XvName "XVideo" +#define XvVersion 2 +#define XvRevision 2 + +/* Symbols */ + +typedef XID XvPortID; +typedef XID XvEncodingID; + +#define XvNone 0 + +#define XvInput 0 +#define XvOutput 1 + +#define XvInputMask (1L<<XvInput) +#define XvOutputMask (1L<<XvOutput) +#define XvVideoMask 0x00000004 +#define XvStillMask 0x00000008 +#define XvImageMask 0x00000010 + +/* These two are not client viewable */ +#define XvPixmapMask 0x00010000 +#define XvWindowMask 0x00020000 + + +#define XvGettable 0x01 +#define XvSettable 0x02 + +#define XvRGB 0 +#define XvYUV 1 + +#define XvPacked 0 +#define XvPlanar 1 + +#define XvTopToBottom 0 +#define XvBottomToTop 1 + + +/* Events */ + +#define XvVideoNotify 0 +#define XvPortNotify 1 +#define XvNumEvents 2 + +/* Video Notify Reasons */ + +#define XvStarted 0 +#define XvStopped 1 +#define XvBusy 2 +#define XvPreempted 3 +#define XvHardError 4 +#define XvLastReason 4 + +#define XvNumReasons (XvLastReason + 1) + +#define XvStartedMask (1L<<XvStarted) +#define XvStoppedMask (1L<<XvStopped) +#define XvBusyMask (1L<<XvBusy) +#define XvPreemptedMask (1L<<XvPreempted) +#define XvHardErrorMask (1L<<XvHardError) + +#define XvAnyReasonMask ((1L<<XvNumReasons) - 1) +#define XvNoReasonMask 0 + +/* Errors */ + +#define XvBadPort 0 +#define XvBadEncoding 1 +#define XvBadControl 2 +#define XvNumErrors 3 + +/* Status */ + +#define XvBadExtension 1 +#define XvAlreadyGrabbed 2 +#define XvInvalidTime 3 +#define XvBadReply 4 +#define XvBadAlloc 5 + +#endif /* XV_H */ + diff --git a/3rdparty/SDL/src/video/Xext/extensions/Xvlib.h b/3rdparty/SDL/src/video/Xext/extensions/Xvlib.h new file mode 100644 index 0000000..0d0a55d --- /dev/null +++ b/3rdparty/SDL/src/video/Xext/extensions/Xvlib.h @@ -0,0 +1,433 @@ +/*********************************************************** +Copyright 1991 by Digital Equipment Corporation, Maynard, Massachusetts, +and the Massachusetts Institute of Technology, Cambridge, Massachusetts. + + All Rights Reserved + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation, and that the names of Digital or MIT not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR +ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +SOFTWARE. + +******************************************************************/ +/* $XFree86: xc/include/extensions/Xvlib.h,v 1.3 1999/12/11 19:28:48 mvojkovi Exp $ */ + +#ifndef XVLIB_H +#define XVLIB_H +/* +** File: +** +** Xvlib.h --- Xv library public header file +** +** Author: +** +** David Carver (Digital Workstation Engineering/Project Athena) +** +** Revisions: +** +** 26.06.91 Carver +** - changed XvFreeAdaptors to XvFreeAdaptorInfo +** - changed XvFreeEncodings to XvFreeEncodingInfo +** +** 11.06.91 Carver +** - changed SetPortControl to SetPortAttribute +** - changed GetPortControl to GetPortAttribute +** - changed QueryBestSize +** +** 05.15.91 Carver +** - version 2.0 upgrade +** +** 01.24.91 Carver +** - version 1.4 upgrade +** +*/ + +#include <X11/Xfuncproto.h> +#include "Xv.h" +#include "SDL_name.h" + +typedef struct { + int numerator; + int denominator; +} SDL_NAME(XvRational); + +typedef struct { + int flags; /* XvGettable, XvSettable */ + int min_value; + int max_value; + char *name; +} SDL_NAME(XvAttribute); + +typedef struct { + XvEncodingID encoding_id; + char *name; + unsigned long width; + unsigned long height; + SDL_NAME(XvRational) rate; + unsigned long num_encodings; +} SDL_NAME(XvEncodingInfo); + +typedef struct { + char depth; + unsigned long visual_id; +} SDL_NAME(XvFormat); + +typedef struct { + XvPortID base_id; + unsigned long num_ports; + char type; + char *name; + unsigned long num_formats; + SDL_NAME(XvFormat) *formats; + unsigned long num_adaptors; +} SDL_NAME(XvAdaptorInfo); + +typedef struct { + int type; + unsigned long serial; /* # of last request processed by server */ + Bool send_event; /* true if this came from a SendEvent request */ + Display *display; /* Display the event was read from */ + Drawable drawable; /* drawable */ + unsigned long reason; /* what generated this event */ + XvPortID port_id; /* what port */ + Time time; /* milliseconds */ +} SDL_NAME(XvVideoNotifyEvent); + +typedef struct { + int type; + unsigned long serial; /* # of last request processed by server */ + Bool send_event; /* true if this came from a SendEvent request */ + Display *display; /* Display the event was read from */ + XvPortID port_id; /* what port */ + Time time; /* milliseconds */ + Atom attribute; /* atom that identifies attribute */ + long value; /* value of attribute */ +} SDL_NAME(XvPortNotifyEvent); + +typedef union { + int type; + SDL_NAME(XvVideoNotifyEvent) xvvideo; + SDL_NAME(XvPortNotifyEvent) xvport; + long pad[24]; +} SDL_NAME(XvEvent); + +typedef struct { + int id; /* Unique descriptor for the format */ + int type; /* XvRGB, XvYUV */ + int byte_order; /* LSBFirst, MSBFirst */ + char guid[16]; /* Globally Unique IDentifier */ + int bits_per_pixel; + int format; /* XvPacked, XvPlanar */ + int num_planes; + + /* for RGB formats only */ + int depth; + unsigned int red_mask; + unsigned int green_mask; + unsigned int blue_mask; + + /* for YUV formats only */ + unsigned int y_sample_bits; + unsigned int u_sample_bits; + unsigned int v_sample_bits; + unsigned int horz_y_period; + unsigned int horz_u_period; + unsigned int horz_v_period; + unsigned int vert_y_period; + unsigned int vert_u_period; + unsigned int vert_v_period; + char component_order[32]; /* eg. UYVY */ + int scanline_order; /* XvTopToBottom, XvBottomToTop */ +} SDL_NAME(XvImageFormatValues); + +typedef struct { + int id; + int width, height; + int data_size; /* bytes */ + int num_planes; + int *pitches; /* bytes */ + int *offsets; /* bytes */ + char *data; + XPointer obdata; +} SDL_NAME(XvImage); + +_XFUNCPROTOBEGIN + +extern int SDL_NAME(XvQueryExtension)( +#if NeedFunctionPrototypes + Display* /* display */, + unsigned int* /* p_version */, + unsigned int* /* p_revision */, + unsigned int* /* p_requestBase */, + unsigned int* /* p_eventBase */, + unsigned int* /* p_errorBase */ +#endif +); + +extern int SDL_NAME(XvQueryAdaptors)( +#if NeedFunctionPrototypes + Display* /* display */, + Window /* window */, + unsigned int* /* p_nAdaptors */, + SDL_NAME(XvAdaptorInfo)** /* p_pAdaptors */ +#endif +); + +extern int SDL_NAME(XvQueryEncodings)( +#if NeedFunctionPrototypes + Display* /* display */, + XvPortID /* port */, + unsigned int* /* p_nEncoding */, + SDL_NAME(XvEncodingInfo)** /* p_pEncoding */ +#endif +); + +extern int SDL_NAME(XvPutVideo)( +#if NeedFunctionPrototypes + Display* /* display */, + XvPortID /* port */, + Drawable /* d */, + GC /* gc */, + int /* vx */, + int /* vy */, + unsigned int /* vw */, + unsigned int /* vh */, + int /* dx */, + int /* dy */, + unsigned int /* dw */, + unsigned int /* dh */ +#endif +); + +extern int SDL_NAME(XvPutStill)( +#if NeedFunctionPrototypes + Display* /* display */, + XvPortID /* port */, + Drawable /* d */, + GC /* gc */, + int /* vx */, + int /* vy */, + unsigned int /* vw */, + unsigned int /* vh */, + int /* dx */, + int /* dy */, + unsigned int /* dw */, + unsigned int /* dh */ +#endif +); + +extern int SDL_NAME(XvGetVideo)( +#if NeedFunctionPrototypes + Display* /* display */, + XvPortID /* port */, + Drawable /* d */, + GC /* gc */, + int /* vx */, + int /* vy */, + unsigned int /* vw */, + unsigned int /* vh */, + int /* dx */, + int /* dy */, + unsigned int /* dw */, + unsigned int /* dh */ +#endif +); + +extern int SDL_NAME(XvGetStill)( +#if NeedFunctionPrototypes + Display* /* display */, + XvPortID /* port */, + Drawable /* d */, + GC /* gc */, + int /* vx */, + int /* vy */, + unsigned int /* vw */, + unsigned int /* vh */, + int /* dx */, + int /* dy */, + unsigned int /* dw */, + unsigned int /* dh */ +#endif +); + +extern int SDL_NAME(XvStopVideo)( +#if NeedFunctionPrototypes + Display* /* display */, + XvPortID /* port */, + Drawable /* drawable */ +#endif +); + +extern int SDL_NAME(XvGrabPort)( +#if NeedFunctionPrototypes + Display* /* display */, + XvPortID /* port */, + Time /* time */ +#endif +); + +extern int SDL_NAME(XvUngrabPort)( +#if NeedFunctionPrototypes + Display* /* display */, + XvPortID /* port */, + Time /* time */ +#endif +); + +extern int SDL_NAME(XvSelectVideoNotify)( +#if NeedFunctionPrototypes + Display* /* display */, + Drawable /* drawable */, + Bool /* onoff */ +#endif +); + +extern int SDL_NAME(XvSelectPortNotify)( +#if NeedFunctionPrototypes + Display* /* display */, + XvPortID /* port */, + Bool /* onoff */ +#endif +); + +extern int SDL_NAME(XvSetPortAttribute)( +#if NeedFunctionPrototypes + Display* /* display */, + XvPortID /* port */, + Atom /* attribute */, + int /* value */ +#endif +); + +extern int SDL_NAME(XvGetPortAttribute)( +#if NeedFunctionPrototypes + Display* /* display */, + XvPortID /* port */, + Atom /* attribute */, + int* /* p_value */ +#endif +); + +extern int SDL_NAME(XvQueryBestSize)( +#if NeedFunctionPrototypes + Display* /* display */, + XvPortID /* port */, + Bool /* motion */, + unsigned int /* vid_w */, + unsigned int /* vid_h */, + unsigned int /* drw_w */, + unsigned int /* drw_h */, + unsigned int* /* p_actual_width */, + unsigned int* /* p_actual_width */ +#endif +); + +extern SDL_NAME(XvAttribute)* SDL_NAME(XvQueryPortAttributes)( +#if NeedFunctionPrototypes + Display* /* display */, + XvPortID /* port */, + int* /* number */ +#endif +); + + +extern void SDL_NAME(XvFreeAdaptorInfo)( +#if NeedFunctionPrototypes + SDL_NAME(XvAdaptorInfo)* /* adaptors */ +#endif +); + +extern void SDL_NAME(XvFreeEncodingInfo)( +#if NeedFunctionPrototypes + SDL_NAME(XvEncodingInfo)* /* encodings */ +#endif +); + + +extern SDL_NAME(XvImageFormatValues) * SDL_NAME(XvListImageFormats) ( +#if NeedFunctionPrototypes + Display *display, + XvPortID port_id, + int *count_return +#endif +); + +extern SDL_NAME(XvImage) * SDL_NAME(XvCreateImage) ( +#if NeedFunctionPrototypes + Display *display, + XvPortID port, + int id, + char *data, + int width, + int height +#endif +); + +extern int SDL_NAME(XvPutImage) ( +#if NeedFunctionPrototypes + Display *display, + XvPortID id, + Drawable d, + GC gc, + SDL_NAME(XvImage) *image, + int src_x, + int src_y, + unsigned int src_w, + unsigned int src_h, + int dest_x, + int dest_y, + unsigned int dest_w, + unsigned int dest_h +#endif +); + +extern int SDL_NAME(XvShmPutImage) ( +#if NeedFunctionPrototypes + Display *display, + XvPortID id, + Drawable d, + GC gc, + SDL_NAME(XvImage) *image, + int src_x, + int src_y, + unsigned int src_w, + unsigned int src_h, + int dest_x, + int dest_y, + unsigned int dest_w, + unsigned int dest_h, + Bool send_event +#endif +); + +#ifdef _XSHM_H_ + +extern SDL_NAME(XvImage) * SDL_NAME(XvShmCreateImage) ( +#if NeedFunctionPrototypes + Display *display, + XvPortID port, + int id, + char* data, + int width, + int height, + XShmSegmentInfo *shminfo +#endif +); + +#endif + + +_XFUNCPROTOEND + +#endif /* XVLIB_H */ diff --git a/3rdparty/SDL/src/video/Xext/extensions/Xvproto.h b/3rdparty/SDL/src/video/Xext/extensions/Xvproto.h new file mode 100644 index 0000000..b4d8f22 --- /dev/null +++ b/3rdparty/SDL/src/video/Xext/extensions/Xvproto.h @@ -0,0 +1,604 @@ +/*********************************************************** +Copyright 1991 by Digital Equipment Corporation, Maynard, Massachusetts, +and the Massachusetts Institute of Technology, Cambridge, Massachusetts. + + All Rights Reserved + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation, and that the names of Digital or MIT not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR +ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +SOFTWARE. + +******************************************************************/ +/* $XFree86: xc/include/extensions/Xvproto.h,v 1.6 2001/05/07 21:37:12 tsi Exp $ */ + +#ifndef XVPROTO_H +#define XVPROTO_H +/* +** File: +** +** Xvproto.h --- Xv protocol header file +** +** Author: +** +** David Carver (Digital Workstation Engineering/Project Athena) +** +** Revisions: +** +** 11.06.91 Carver +** - changed SetPortControl to SetPortAttribute +** - changed GetPortControl to GetPortAttribute +** - changed QueryBestSize +** +** 15.05.91 Carver +** - version 2.0 upgrade +** +** 24.01.91 Carver +** - version 1.4 upgrade +** +*/ + +#include <X11/Xmd.h> + +/* Symbols: These are undefined at the end of this file to restore the + values they have in Xv.h */ + +#define XvPortID CARD32 +#define XvEncodingID CARD32 +#define ShmSeg CARD32 +#define VisualID CARD32 +#define Drawable CARD32 +#define GContext CARD32 +#define Time CARD32 +#define Atom CARD32 + +/* Structures */ + +typedef struct { + INT32 numerator B32; + INT32 denominator B32; +} xvRational; +#define sz_xvRational 8 + +typedef struct { + XvPortID base_id B32; + CARD16 name_size B16; + CARD16 num_ports B16; + CARD16 num_formats B16; + CARD8 type; + CARD8 pad; +} xvAdaptorInfo; +#define sz_xvAdaptorInfo 12 + +typedef struct { + XvEncodingID encoding B32; + CARD16 name_size B16; + CARD16 width B16, height B16; + xvRational rate; + CARD16 pad B16; +} xvEncodingInfo; +#define sz_xvEncodingInfo (12 + sz_xvRational) + +typedef struct { + VisualID visual B32; + CARD8 depth; + CARD8 pad1; + CARD16 pad2 B16; +} xvFormat; +#define sz_xvFormat 8 + +typedef struct { + CARD32 flags B32; + INT32 min B32; + INT32 max B32; + CARD32 size B32; +} xvAttributeInfo; +#define sz_xvAttributeInfo 16 + +typedef struct { + CARD32 id B32; + CARD8 type; + CARD8 byte_order; + CARD16 pad1 B16; + CARD8 guid[16]; + CARD8 bpp; + CARD8 num_planes; + CARD16 pad2 B16; + CARD8 depth; + CARD8 pad3; + CARD16 pad4 B16; + CARD32 red_mask B32; + CARD32 green_mask B32; + CARD32 blue_mask B32; + CARD8 format; + CARD8 pad5; + CARD16 pad6 B16; + CARD32 y_sample_bits B32; + CARD32 u_sample_bits B32; + CARD32 v_sample_bits B32; + CARD32 horz_y_period B32; + CARD32 horz_u_period B32; + CARD32 horz_v_period B32; + CARD32 vert_y_period B32; + CARD32 vert_u_period B32; + CARD32 vert_v_period B32; + CARD8 comp_order[32]; + CARD8 scanline_order; + CARD8 pad7; + CARD16 pad8 B16; + CARD32 pad9 B32; + CARD32 pad10 B32; +} xvImageFormatInfo; +#define sz_xvImageFormatInfo 128 + + +/* Requests */ + +#define xv_QueryExtension 0 +#define xv_QueryAdaptors 1 +#define xv_QueryEncodings 2 +#define xv_GrabPort 3 +#define xv_UngrabPort 4 +#define xv_PutVideo 5 +#define xv_PutStill 6 +#define xv_GetVideo 7 +#define xv_GetStill 8 +#define xv_StopVideo 9 +#define xv_SelectVideoNotify 10 +#define xv_SelectPortNotify 11 +#define xv_QueryBestSize 12 +#define xv_SetPortAttribute 13 +#define xv_GetPortAttribute 14 +#define xv_QueryPortAttributes 15 +#define xv_ListImageFormats 16 +#define xv_QueryImageAttributes 17 +#define xv_PutImage 18 +#define xv_ShmPutImage 19 +#define xv_LastRequest xv_ShmPutImage + +#define xvNumRequests (xv_LastRequest + 1) + +typedef struct { + CARD8 reqType; + CARD8 xvReqType; + CARD16 length B16; +} xvQueryExtensionReq; +#define sz_xvQueryExtensionReq 4 + +typedef struct { + CARD8 reqType; + CARD8 xvReqType; + CARD16 length B16; + CARD32 window B32; +} xvQueryAdaptorsReq; +#define sz_xvQueryAdaptorsReq 8 + +typedef struct { + CARD8 reqType; + CARD8 xvReqType; + CARD16 length B16; + CARD32 port B32; +} xvQueryEncodingsReq; +#define sz_xvQueryEncodingsReq 8 + +typedef struct { + CARD8 reqType; + CARD8 xvReqType; + CARD16 length B16; + XvPortID port B32; + Drawable drawable B32; + GContext gc B32; + INT16 vid_x B16; + INT16 vid_y B16; + CARD16 vid_w B16; + CARD16 vid_h B16; + INT16 drw_x B16; + INT16 drw_y B16; + CARD16 drw_w B16; + CARD16 drw_h B16; +} xvPutVideoReq; +#define sz_xvPutVideoReq 32 + +typedef struct { + CARD8 reqType; + CARD8 xvReqType; + CARD16 length B16; + XvPortID port B32; + Drawable drawable B32; + GContext gc B32; + INT16 vid_x B16; + INT16 vid_y B16; + CARD16 vid_w B16; + CARD16 vid_h B16; + INT16 drw_x B16; + INT16 drw_y B16; + CARD16 drw_w B16; + CARD16 drw_h B16; +} xvPutStillReq; +#define sz_xvPutStillReq 32 + +typedef struct { + CARD8 reqType; + CARD8 xvReqType; + CARD16 length B16; + XvPortID port B32; + Drawable drawable B32; + GContext gc B32; + INT16 vid_x B16; + INT16 vid_y B16; + CARD16 vid_w B16; + CARD16 vid_h B16; + INT16 drw_x B16; + INT16 drw_y B16; + CARD16 drw_w B16; + CARD16 drw_h B16; +} xvGetVideoReq; +#define sz_xvGetVideoReq 32 + +typedef struct { + CARD8 reqType; + CARD8 xvReqType; + CARD16 length B16; + XvPortID port B32; + Drawable drawable B32; + GContext gc B32; + INT16 vid_x B16; + INT16 vid_y B16; + CARD16 vid_w B16; + CARD16 vid_h B16; + INT16 drw_x B16; + INT16 drw_y B16; + CARD16 drw_w B16; + CARD16 drw_h B16; +} xvGetStillReq; +#define sz_xvGetStillReq 32 + +typedef struct { + CARD8 reqType; + CARD8 xvReqType; + CARD16 length B16; + XvPortID port B32; + Time time B32; +} xvGrabPortReq; +#define sz_xvGrabPortReq 12 + +typedef struct { + CARD8 reqType; + CARD8 xvReqType; + CARD16 length B16; + XvPortID port B32; + Time time B32; +} xvUngrabPortReq; +#define sz_xvUngrabPortReq 12 + +typedef struct { + CARD8 reqType; + CARD8 xvReqType; + CARD16 length B16; + Drawable drawable B32; + BOOL onoff; + CARD8 pad1; + CARD16 pad2; +} xvSelectVideoNotifyReq; +#define sz_xvSelectVideoNotifyReq 12 + +typedef struct { + CARD8 reqType; + CARD8 xvReqType; + CARD16 length B16; + XvPortID port B32; + BOOL onoff; + CARD8 pad1; + CARD16 pad2; +} xvSelectPortNotifyReq; +#define sz_xvSelectPortNotifyReq 12 + +typedef struct { + CARD8 reqType; + CARD8 xvReqType; + CARD16 length B16; + XvPortID port B32; + Drawable drawable B32; +} xvStopVideoReq; +#define sz_xvStopVideoReq 12 + +typedef struct { + CARD8 reqType; + CARD8 xvReqType; + CARD16 length B16; + XvPortID port B32; + Atom attribute B32; + INT32 value B32; +} xvSetPortAttributeReq; +#define sz_xvSetPortAttributeReq 16 + +typedef struct { + CARD8 reqType; + CARD8 xvReqType; + CARD16 length B16; + XvPortID port B32; + Atom attribute B32; +} xvGetPortAttributeReq; +#define sz_xvGetPortAttributeReq 12 + +typedef struct { + CARD8 reqType; + CARD8 xvReqType; + CARD16 length B16; + XvPortID port B32; + CARD16 vid_w B16; + CARD16 vid_h B16; + CARD16 drw_w B16; + CARD16 drw_h B16; + CARD8 motion; + CARD8 pad1; + CARD16 pad2 B16; +} xvQueryBestSizeReq; +#define sz_xvQueryBestSizeReq 20 + +typedef struct { + CARD8 reqType; + CARD8 xvReqType; + CARD16 length B16; + XvPortID port B32; +} xvQueryPortAttributesReq; +#define sz_xvQueryPortAttributesReq 8 + +typedef struct { + CARD8 reqType; + CARD8 xvReqType; + CARD16 length B16; + XvPortID port B32; + Drawable drawable B32; + GContext gc B32; + CARD32 id B32; + INT16 src_x B16; + INT16 src_y B16; + CARD16 src_w B16; + CARD16 src_h B16; + INT16 drw_x B16; + INT16 drw_y B16; + CARD16 drw_w B16; + CARD16 drw_h B16; + CARD16 width B16; + CARD16 height B16; +} xvPutImageReq; +#define sz_xvPutImageReq 40 + +typedef struct { + CARD8 reqType; + CARD8 xvReqType; + CARD16 length B16; + XvPortID port B32; + Drawable drawable B32; + GContext gc B32; + ShmSeg shmseg B32; + CARD32 id B32; + CARD32 offset B32; + INT16 src_x B16; + INT16 src_y B16; + CARD16 src_w B16; + CARD16 src_h B16; + INT16 drw_x B16; + INT16 drw_y B16; + CARD16 drw_w B16; + CARD16 drw_h B16; + CARD16 width B16; + CARD16 height B16; + CARD8 send_event; + CARD8 pad1; + CARD16 pad2 B16; +} xvShmPutImageReq; +#define sz_xvShmPutImageReq 52 + +typedef struct { + CARD8 reqType; + CARD8 xvReqType; + CARD16 length B16; + XvPortID port B32; +} xvListImageFormatsReq; +#define sz_xvListImageFormatsReq 8 + +typedef struct { + CARD8 reqType; + CARD8 xvReqType; + CARD16 length B16; + CARD32 port B32; + CARD32 id B32; + CARD16 width B16; + CARD16 height B16; +} xvQueryImageAttributesReq; +#define sz_xvQueryImageAttributesReq 16 + + +/* Replies */ + +typedef struct _QueryExtensionReply { + BYTE type; /* X_Reply */ + CARD8 padb1; + CARD16 sequenceNumber B16; + CARD32 length B32; + CARD16 version B16; + CARD16 revision B16; + CARD32 padl4 B32; + CARD32 padl5 B32; + CARD32 padl6 B32; + CARD32 padl7 B32; + CARD32 padl8 B32; +} xvQueryExtensionReply; +#define sz_xvQueryExtensionReply 32 + +typedef struct _QueryAdaptorsReply { + BYTE type; /* X_Reply */ + CARD8 padb1; + CARD16 sequenceNumber B16; + CARD32 length B32; + CARD16 num_adaptors B16; + CARD16 pads3 B16; + CARD32 padl4 B32; + CARD32 padl5 B32; + CARD32 padl6 B32; + CARD32 padl7 B32; + CARD32 padl8 B32; +} xvQueryAdaptorsReply; +#define sz_xvQueryAdaptorsReply 32 + +typedef struct _QueryEncodingsReply { + BYTE type; /* X_Reply */ + CARD8 padb1; + CARD16 sequenceNumber B16; + CARD32 length B32; + CARD16 num_encodings B16; + CARD32 padl3 B32; + CARD32 padl4 B32; + CARD32 padl5 B32; + CARD32 padl6 B32; + CARD32 padl7 B32; + CARD32 padl8 B32; +} xvQueryEncodingsReply; +#define sz_xvQueryEncodingsReply 32 + +typedef struct { + BYTE type; /* X_Reply */ + BYTE result; + CARD16 sequenceNumber B16; + CARD32 length B32; /* 0 */ + CARD32 padl3 B32; + CARD32 padl4 B32; + CARD32 padl5 B32; + CARD32 padl6 B32; + CARD32 padl7 B32; + CARD32 padl8 B32; +} xvGrabPortReply; +#define sz_xvGrabPortReply 32 + +typedef struct { + BYTE type; /* X_Reply */ + BYTE padb1; + CARD16 sequenceNumber B16; + CARD32 length B32; /* 0 */ + INT32 value B32; + CARD32 padl4 B32; + CARD32 padl5 B32; + CARD32 padl6 B32; + CARD32 padl7 B32; + CARD32 padl8 B32; +} xvGetPortAttributeReply; +#define sz_xvGetPortAttributeReply 32 + +typedef struct { + BYTE type; /* X_Reply */ + BYTE padb1; + CARD16 sequenceNumber B16; + CARD32 length B32; /* 0 */ + CARD16 actual_width B16; + CARD16 actual_height B16; + CARD32 padl4 B32; + CARD32 padl5 B32; + CARD32 padl6 B32; + CARD32 padl7 B32; + CARD32 padl8 B32; +} xvQueryBestSizeReply; +#define sz_xvQueryBestSizeReply 32 + +typedef struct { + BYTE type; /* X_Reply */ + BYTE padb1; + CARD16 sequenceNumber B16; + CARD32 length B32; /* 0 */ + CARD32 num_attributes B32; + CARD32 text_size B32; + CARD32 padl5 B32; + CARD32 padl6 B32; + CARD32 padl7 B32; + CARD32 padl8 B32; +} xvQueryPortAttributesReply; +#define sz_xvQueryPortAttributesReply 32 + +typedef struct { + BYTE type; /* X_Reply */ + BYTE padb1; + CARD16 sequenceNumber B16; + CARD32 length B32; + CARD32 num_formats B32; + CARD32 padl4 B32; + CARD32 padl5 B32; + CARD32 padl6 B32; + CARD32 padl7 B32; + CARD32 padl8 B32; +} xvListImageFormatsReply; +#define sz_xvListImageFormatsReply 32 + +typedef struct { + BYTE type; /* X_Reply */ + BYTE padb1; + CARD16 sequenceNumber B16; + CARD32 length B32; + CARD32 num_planes B32; + CARD32 data_size B32; + CARD16 width B16; + CARD16 height B16; + CARD32 padl6 B32; + CARD32 padl7 B32; + CARD32 padl8 B32; +} xvQueryImageAttributesReply; +#define sz_xvQueryImageAttributesReply 32 + +/* DEFINE EVENT STRUCTURE */ + +typedef struct { + union { + struct { + BYTE type; + BYTE detail; + CARD16 sequenceNumber B16; + } u; + struct { + BYTE type; + BYTE reason; + CARD16 sequenceNumber B16; + Time time B32; + Drawable drawable B32; + XvPortID port B32; + CARD32 padl5 B32; + CARD32 padl6 B32; + CARD32 padl7 B32; + CARD32 padl8 B32; + } videoNotify; + struct { + BYTE type; + BYTE padb1; + CARD16 sequenceNumber B16; + Time time B32; + XvPortID port B32; + Atom attribute B32; + INT32 value B32; + CARD32 padl6 B32; + CARD32 padl7 B32; + CARD32 padl8 B32; + } portNotify; + } u; +} xvEvent; + +#undef XvPortID +#undef XvEncodingID +#undef ShmSeg +#undef VisualID +#undef Drawable +#undef GContext +#undef Time +#undef Atom + +#endif /* XVPROTO_H */ + diff --git a/3rdparty/SDL/src/video/Xext/extensions/extutil.h b/3rdparty/SDL/src/video/Xext/extensions/extutil.h new file mode 100644 index 0000000..f3a741e --- /dev/null +++ b/3rdparty/SDL/src/video/Xext/extensions/extutil.h @@ -0,0 +1,226 @@ +/* + * $Xorg: extutil.h,v 1.4 2001/02/09 02:03:24 xorgcvs Exp $ + * +Copyright 1989, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + * + * Author: Jim Fulton, MIT The Open Group + * + * Xlib Extension-Writing Utilities + * + * This package contains utilities for writing the client API for various + * protocol extensions. THESE INTERFACES ARE NOT PART OF THE X STANDARD AND + * ARE SUBJECT TO CHANGE! + */ +/* $XFree86: xc/include/extensions/extutil.h,v 1.9 2001/12/14 19:53:28 dawes Exp $ */ + +#ifndef _EXTUTIL_H_ +#define _EXTUTIL_H_ + +#include "SDL_stdinc.h" /* For portable string functions */ + +#include "./Xext.h" + +/* + * We need to keep a list of open displays since the Xlib display list isn't + * public. We also have to per-display info in a separate block since it isn't + * stored directly in the Display structure. + */ +typedef struct _XExtDisplayInfo { + struct _XExtDisplayInfo *next; /* keep a linked list */ + Display *display; /* which display this is */ + XExtCodes *codes; /* the extension protocol codes */ + XPointer data; /* extra data for extension to use */ +} XExtDisplayInfo; + +typedef struct _XExtensionInfo { + XExtDisplayInfo *head; /* start of list */ + XExtDisplayInfo *cur; /* most recently used */ + int ndisplays; /* number of displays */ +} XExtensionInfo; + +typedef struct _XExtensionHooks { + int (*create_gc)( +#if NeedNestedPrototypes + Display* /* display */, + GC /* gc */, + XExtCodes* /* codes */ +#endif +); + int (*copy_gc)( +#if NeedNestedPrototypes + Display* /* display */, + GC /* gc */, + XExtCodes* /* codes */ +#endif +); + int (*flush_gc)( +#if NeedNestedPrototypes + Display* /* display */, + GC /* gc */, + XExtCodes* /* codes */ +#endif +); + int (*free_gc)( +#if NeedNestedPrototypes + Display* /* display */, + GC /* gc */, + XExtCodes* /* codes */ +#endif +); + int (*create_font)( +#if NeedNestedPrototypes + Display* /* display */, + XFontStruct* /* fs */, + XExtCodes* /* codes */ +#endif +); + int (*free_font)( +#if NeedNestedPrototypes + Display* /* display */, + XFontStruct* /* fs */, + XExtCodes* /* codes */ +#endif +); + int (*close_display)( +#if NeedNestedPrototypes + Display* /* display */, + XExtCodes* /* codes */ +#endif +); + Bool (*wire_to_event)( +#if NeedNestedPrototypes + Display* /* display */, + XEvent* /* re */, + xEvent* /* event */ +#endif +); + Status (*event_to_wire)( +#if NeedNestedPrototypes + Display* /* display */, + XEvent* /* re */, + xEvent* /* event */ +#endif +); + int (*error)( +#if NeedNestedPrototypes + Display* /* display */, + xError* /* err */, + XExtCodes* /* codes */, + int* /* ret_code */ +#endif +); + char *(*error_string)( +#if NeedNestedPrototypes + Display* /* display */, + int /* code */, + XExtCodes* /* codes */, + char* /* buffer */, + int /* nbytes */ +#endif +); +} XExtensionHooks; + +extern XExtensionInfo *XextCreateExtension( +#if NeedFunctionPrototypes + void +#endif +); +extern void XextDestroyExtension( +#if NeedFunctionPrototypes + XExtensionInfo* /* info */ +#endif +); +extern XExtDisplayInfo *XextAddDisplay( +#if NeedFunctionPrototypes + XExtensionInfo* /* extinfo */, + Display* /* dpy */, + char* /* ext_name */, + XExtensionHooks* /* hooks */, + int /* nevents */, + XPointer /* data */ +#endif +); +extern int XextRemoveDisplay( +#if NeedFunctionPrototypes + XExtensionInfo* /* extinfo */, + Display* /* dpy */ +#endif +); +extern XExtDisplayInfo *XextFindDisplay( +#if NeedFunctionPrototypes + XExtensionInfo* /* extinfo */, + Display* /* dpy */ +#endif +); + +#define XextHasExtension(i) ((i) && ((i)->codes)) +#define XextCheckExtension(dpy,i,name,val) \ + if (!XextHasExtension(i)) { XMissingExtension (dpy, name); return val; } +#define XextSimpleCheckExtension(dpy,i,name) \ + if (!XextHasExtension(i)) { XMissingExtension (dpy, name); return; } + + +/* + * helper macros to generate code that is common to all extensions; caller + * should prefix it with static if extension source is in one file; this + * could be a utility function, but have to stack 6 unused arguments for + * something that is called many, many times would be bad. + */ +#define XEXT_GENERATE_FIND_DISPLAY(proc,extinfo,extname,hooks,nev,data) \ +XExtDisplayInfo *proc (Display *dpy) \ +{ \ + XExtDisplayInfo *dpyinfo; \ + if (!extinfo) { if (!(extinfo = XextCreateExtension())) return NULL; } \ + if (!(dpyinfo = XextFindDisplay (extinfo, dpy))) \ + dpyinfo = XextAddDisplay (extinfo,dpy,extname,hooks,nev,data); \ + return dpyinfo; \ +} + +#define XEXT_FIND_DISPLAY_PROTO(proc) \ + XExtDisplayInfo *proc(Display *dpy) + +#define XEXT_GENERATE_CLOSE_DISPLAY(proc,extinfo) \ +int proc (Display *dpy, XExtCodes *codes) \ +{ \ + return XextRemoveDisplay (extinfo, dpy); \ +} + +#define XEXT_CLOSE_DISPLAY_PROTO(proc) \ + int proc(Display *dpy, XExtCodes *codes) + +#define XEXT_GENERATE_ERROR_STRING(proc,extname,nerr,errl) \ +char *proc (Display *dpy, int code, XExtCodes *codes, char *buf, int n) \ +{ \ + code -= codes->first_error; \ + if (code >= 0 && code < nerr) { \ + char tmp[256]; \ + SDL_snprintf (tmp, SDL_arraysize(tmp), "%s.%d", extname, code); \ + XGetErrorDatabaseText (dpy, "XProtoError", tmp, errl[code], buf, n); \ + return buf; \ + } \ + return (char *)0; \ +} + +#define XEXT_ERROR_STRING_PROTO(proc) \ + char *proc(Display *dpy, int code, XExtCodes *codes, char *buf, int n) +#endif diff --git a/3rdparty/SDL/src/video/Xext/extensions/panoramiXext.h b/3rdparty/SDL/src/video/Xext/extensions/panoramiXext.h new file mode 100644 index 0000000..e89d891 --- /dev/null +++ b/3rdparty/SDL/src/video/Xext/extensions/panoramiXext.h @@ -0,0 +1,52 @@ +/* $Xorg: panoramiXext.h,v 1.4 2000/08/18 04:05:45 coskrey Exp $ */ +/***************************************************************** +Copyright (c) 1991, 1997 Digital Equipment Corporation, Maynard, Massachusetts. +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +DIGITAL EQUIPMENT CORPORATION BE LIABLE FOR ANY CLAIM, DAMAGES, INCLUDING, +BUT NOT LIMITED TO CONSEQUENTIAL OR INCIDENTAL DAMAGES, OR OTHER LIABILITY, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR +IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of Digital Equipment Corporation +shall not be used in advertising or otherwise to promote the sale, use or other +dealings in this Software without prior written authorization from Digital +Equipment Corporation. +******************************************************************/ +/* + * PanoramiX definitions + */ +/* $XFree86: xc/include/extensions/panoramiXext.h,v 3.6 2001/01/17 17:53:22 dawes Exp $ */ + +#include "SDL_name.h" + +/* THIS IS NOT AN X PROJECT TEAM SPECIFICATION */ + +#define PANORAMIX_MAJOR_VERSION 1 /* current version number */ +#define PANORAMIX_MINOR_VERSION 1 + +typedef struct { + Window window; /* PanoramiX window - may not exist */ + int screen; + int State; /* PanroamiXOff, PanoramiXOn */ + int width; /* width of this screen */ + int height; /* height of this screen */ + int ScreenCount; /* real physical number of screens */ + XID eventMask; /* selected events for this client */ +} SDL_NAME(XPanoramiXInfo); + +extern SDL_NAME(XPanoramiXInfo) *SDL_NAME(XPanoramiXAllocInfo) ( +#if NeedFunctionPrototypes + void +#endif +); diff --git a/3rdparty/SDL/src/video/Xext/extensions/panoramiXproto.h b/3rdparty/SDL/src/video/Xext/extensions/panoramiXproto.h new file mode 100644 index 0000000..fe3826e --- /dev/null +++ b/3rdparty/SDL/src/video/Xext/extensions/panoramiXproto.h @@ -0,0 +1,192 @@ +/* $Xorg: panoramiXproto.h,v 1.4 2000/08/18 04:05:45 coskrey Exp $ */ +/***************************************************************** +Copyright (c) 1991, 1997 Digital Equipment Corporation, Maynard, Massachusetts. +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +DIGITAL EQUIPMENT CORPORATION BE LIABLE FOR ANY CLAIM, DAMAGES, INCLUDING, +BUT NOT LIMITED TO CONSEQUENTIAL OR INCIDENTAL DAMAGES, OR OTHER LIABILITY, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR +IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of Digital Equipment Corporation +shall not be used in advertising or otherwise to promote the sale, use or other +dealings in this Software without prior written authorization from Digital +Equipment Corporation. +******************************************************************/ +/* $XFree86: xc/include/extensions/panoramiXproto.h,v 3.6 2001/01/17 17:53:22 dawes Exp $ */ + +/* THIS IS NOT AN X PROJECT TEAM SPECIFICATION */ + +#ifndef _PANORAMIXPROTO_H_ +#define _PANORAMIXPROTO_H_ + +#define PANORAMIX_PROTOCOL_NAME "XINERAMA" + +#define X_PanoramiXQueryVersion 0 +#define X_PanoramiXGetState 1 +#define X_PanoramiXGetScreenCount 2 +#define X_PanoramiXGetScreenSize 3 + +#define X_XineramaIsActive 4 +#define X_XineramaQueryScreens 5 + +typedef struct _PanoramiXQueryVersion { + CARD8 reqType; /* always PanoramiXReqCode */ + CARD8 panoramiXReqType; /* always X_PanoramiXQueryVersion */ + CARD16 length B16; + CARD8 clientMajor; + CARD8 clientMinor; + CARD16 unused B16; +} xPanoramiXQueryVersionReq; + +#define sz_xPanoramiXQueryVersionReq 8 + +typedef struct { + CARD8 type; /* must be X_Reply */ + CARD8 pad1; /* unused */ + CARD16 sequenceNumber B16; /* last sequence number */ + CARD32 length B32; /* 0 */ + CARD16 majorVersion B16; + CARD16 minorVersion B16; + CARD32 pad2 B32; /* unused */ + CARD32 pad3 B32; /* unused */ + CARD32 pad4 B32; /* unused */ + CARD32 pad5 B32; /* unused */ + CARD32 pad6 B32; /* unused */ +} xPanoramiXQueryVersionReply; + +#define sz_xPanoramiXQueryVersionReply 32 + + +typedef struct _PanoramiXGetState { + CARD8 reqType; /* always PanoramiXReqCode */ + CARD8 panoramiXReqType; /* always X_PanoramiXGetState */ + CARD16 length B16; + CARD32 window B32; +} xPanoramiXGetStateReq; +#define sz_xPanoramiXGetStateReq 8 + +typedef struct { + BYTE type; + BYTE state; + CARD16 sequenceNumber B16; + CARD32 length B32; + CARD32 window B32; + CARD32 pad1 B32; /* unused */ + CARD32 pad2 B32; /* unused */ + CARD32 pad3 B32; /* unused */ + CARD32 pad4 B32; /* unused */ + CARD32 pad5 B32; /* unused */ +} xPanoramiXGetStateReply; + +#define sz_panoramiXGetStateReply 32 + +typedef struct _PanoramiXGetScreenCount { + CARD8 reqType; /* always PanoramiXReqCode */ + CARD8 panoramiXReqType; /* always X_PanoramiXGetScreenCount */ + CARD16 length B16; + CARD32 window B32; +} xPanoramiXGetScreenCountReq; +#define sz_xPanoramiXGetScreenCountReq 8 + +typedef struct { + BYTE type; + BYTE ScreenCount; + CARD16 sequenceNumber B16; + CARD32 length B32; + CARD32 window B32; + CARD32 pad1 B32; /* unused */ + CARD32 pad2 B32; /* unused */ + CARD32 pad3 B32; /* unused */ + CARD32 pad4 B32; /* unused */ + CARD32 pad5 B32; /* unused */ +} xPanoramiXGetScreenCountReply; +#define sz_panoramiXGetScreenCountReply 32 + +typedef struct _PanoramiXGetScreenSize { + CARD8 reqType; /* always PanoramiXReqCode */ + CARD8 panoramiXReqType; /* always X_PanoramiXGetState */ + CARD16 length B16; + CARD32 window B32; + CARD32 screen B32; +} xPanoramiXGetScreenSizeReq; +#define sz_xPanoramiXGetScreenSizeReq 12 + +typedef struct { + BYTE type; + CARD8 pad1; + CARD16 sequenceNumber B16; + CARD32 length B32; + CARD32 width B32; + CARD32 height B32; + CARD32 window B32; + CARD32 screen B32; + CARD32 pad2 B32; /* unused */ + CARD32 pad3 B32; /* unused */ +} xPanoramiXGetScreenSizeReply; +#define sz_panoramiXGetScreenSizeReply 32 + +/************ Alternate protocol ******************/ + +typedef struct { + CARD8 reqType; + CARD8 panoramiXReqType; + CARD16 length B16; +} xXineramaIsActiveReq; +#define sz_xXineramaIsActiveReq 4 + +typedef struct { + BYTE type; + CARD8 pad1; + CARD16 sequenceNumber B16; + CARD32 length B32; + CARD32 state B32; + CARD32 pad2 B32; + CARD32 pad3 B32; + CARD32 pad4 B32; + CARD32 pad5 B32; + CARD32 pad6 B32; +} xXineramaIsActiveReply; +#define sz_XineramaIsActiveReply 32 + + +typedef struct { + CARD8 reqType; + CARD8 panoramiXReqType; + CARD16 length B16; +} xXineramaQueryScreensReq; +#define sz_xXineramaQueryScreensReq 4 + +typedef struct { + BYTE type; + CARD8 pad1; + CARD16 sequenceNumber B16; + CARD32 length B32; + CARD32 number B32; + CARD32 pad2 B32; + CARD32 pad3 B32; + CARD32 pad4 B32; + CARD32 pad5 B32; + CARD32 pad6 B32; +} xXineramaQueryScreensReply; +#define sz_XineramaQueryScreensReply 32 + +typedef struct { + INT16 x_org B16; + INT16 y_org B16; + CARD16 width B16; + CARD16 height B16; +} xXineramaScreenInfo; +#define sz_XineramaScreenInfo 8 + +#endif diff --git a/3rdparty/SDL/src/video/Xext/extensions/xf86dga.h b/3rdparty/SDL/src/video/Xext/extensions/xf86dga.h new file mode 100644 index 0000000..c71ef4b --- /dev/null +++ b/3rdparty/SDL/src/video/Xext/extensions/xf86dga.h @@ -0,0 +1,265 @@ +/* + Copyright (c) 1999 XFree86 Inc +*/ +/* $XFree86: xc/include/extensions/xf86dga.h,v 3.21 2001/08/01 00:44:36 tsi Exp $ */ + +#ifndef _XF86DGA_H_ +#define _XF86DGA_H_ + +#include <X11/Xfuncproto.h> +#include "xf86dga1.h" +#include "SDL_name.h" + +#define X_XDGAQueryVersion 0 + +/* 1 through 9 are in xf86dga1.h */ + +/* 10 and 11 are reserved to avoid conflicts with rogue DGA extensions */ + +#define X_XDGAQueryModes 12 +#define X_XDGASetMode 13 +#define X_XDGASetViewport 14 +#define X_XDGAInstallColormap 15 +#define X_XDGASelectInput 16 +#define X_XDGAFillRectangle 17 +#define X_XDGACopyArea 18 +#define X_XDGACopyTransparentArea 19 +#define X_XDGAGetViewportStatus 20 +#define X_XDGASync 21 +#define X_XDGAOpenFramebuffer 22 +#define X_XDGACloseFramebuffer 23 +#define X_XDGASetClientVersion 24 +#define X_XDGAChangePixmapMode 25 +#define X_XDGACreateColormap 26 + + +#define XDGAConcurrentAccess 0x00000001 +#define XDGASolidFillRect 0x00000002 +#define XDGABlitRect 0x00000004 +#define XDGABlitTransRect 0x00000008 +#define XDGAPixmap 0x00000010 + +#define XDGAInterlaced 0x00010000 +#define XDGADoublescan 0x00020000 + +#define XDGAFlipImmediate 0x00000001 +#define XDGAFlipRetrace 0x00000002 + +#define XDGANeedRoot 0x00000001 + +#define XF86DGANumberEvents 7 + +#define XDGAPixmapModeLarge 0 +#define XDGAPixmapModeSmall 1 + +#define XF86DGAClientNotLocal 0 +#define XF86DGANoDirectVideoMode 1 +#define XF86DGAScreenNotActive 2 +#define XF86DGADirectNotActivated 3 +#define XF86DGAOperationNotSupported 4 +#define XF86DGANumberErrors (XF86DGAOperationNotSupported + 1) + + +typedef struct { + int num; /* A unique identifier for the mode (num > 0) */ + char *name; /* name of mode given in the XF86Config */ + float verticalRefresh; + int flags; /* DGA_CONCURRENT_ACCESS, etc... */ + int imageWidth; /* linear accessible portion (pixels) */ + int imageHeight; + int pixmapWidth; /* Xlib accessible portion (pixels) */ + int pixmapHeight; /* both fields ignored if no concurrent access */ + int bytesPerScanline; + int byteOrder; /* MSBFirst, LSBFirst */ + int depth; + int bitsPerPixel; + unsigned long redMask; + unsigned long greenMask; + unsigned long blueMask; + short visualClass; + int viewportWidth; + int viewportHeight; + int xViewportStep; /* viewport position granularity */ + int yViewportStep; + int maxViewportX; /* max viewport origin */ + int maxViewportY; + int viewportFlags; /* types of page flipping possible */ + int reserved1; + int reserved2; +} SDL_NAME(XDGAMode); + + +typedef struct { + SDL_NAME(XDGAMode) mode; + unsigned char *data; + Pixmap pixmap; +} SDL_NAME(XDGADevice); + + +#ifndef _XF86DGA_SERVER_ +_XFUNCPROTOBEGIN + +typedef struct { + int type; + unsigned long serial; + Display *display; + int screen; + Time time; + unsigned int state; + unsigned int button; +} SDL_NAME(XDGAButtonEvent); + +typedef struct { + int type; + unsigned long serial; + Display *display; + int screen; + Time time; + unsigned int state; + unsigned int keycode; +} SDL_NAME(XDGAKeyEvent); + +typedef struct { + int type; + unsigned long serial; + Display *display; + int screen; + Time time; + unsigned int state; + int dx; + int dy; +} SDL_NAME(XDGAMotionEvent); + +typedef union { + int type; + SDL_NAME(XDGAButtonEvent) xbutton; + SDL_NAME(XDGAKeyEvent) xkey; + SDL_NAME(XDGAMotionEvent) xmotion; + long pad[24]; +} SDL_NAME(XDGAEvent); + +Bool SDL_NAME(XDGAQueryExtension)( + Display *dpy, + int *eventBase, + int *erroBase +); + +Bool SDL_NAME(XDGAQueryVersion)( + Display *dpy, + int *majorVersion, + int *minorVersion +); + +SDL_NAME(XDGAMode)* SDL_NAME(XDGAQueryModes)( + Display *dpy, + int screen, + int *num +); + +SDL_NAME(XDGADevice)* SDL_NAME(XDGASetMode)( + Display *dpy, + int screen, + int mode +); + +Bool SDL_NAME(XDGAOpenFramebuffer)( + Display *dpy, + int screen +); + +void SDL_NAME(XDGACloseFramebuffer)( + Display *dpy, + int screen +); + +void SDL_NAME(XDGASetViewport)( + Display *dpy, + int screen, + int x, + int y, + int flags +); + +void SDL_NAME(XDGAInstallColormap)( + Display *dpy, + int screen, + Colormap cmap +); + +Colormap SDL_NAME(XDGACreateColormap)( + Display *dpy, + int screen, + SDL_NAME(XDGADevice) *device, + int alloc +); + +void SDL_NAME(XDGASelectInput)( + Display *dpy, + int screen, + long event_mask +); + +void SDL_NAME(XDGAFillRectangle)( + Display *dpy, + int screen, + int x, + int y, + unsigned int width, + unsigned int height, + unsigned long color +); + + +void SDL_NAME(XDGACopyArea)( + Display *dpy, + int screen, + int srcx, + int srcy, + unsigned int width, + unsigned int height, + int dstx, + int dsty +); + + +void SDL_NAME(XDGACopyTransparentArea)( + Display *dpy, + int screen, + int srcx, + int srcy, + unsigned int width, + unsigned int height, + int dstx, + int dsty, + unsigned long key +); + +int SDL_NAME(XDGAGetViewportStatus)( + Display *dpy, + int screen +); + +void SDL_NAME(XDGASync)( + Display *dpy, + int screen +); + +Bool SDL_NAME(XDGASetClientVersion)( + Display *dpy +); + +void SDL_NAME(XDGAChangePixmapMode)( + Display *dpy, + int screen, + int *x, + int *y, + int mode +); + + +void SDL_NAME(XDGAKeyEventToXKeyEvent)(SDL_NAME(XDGAKeyEvent)* dk, XKeyEvent* xk); + + +_XFUNCPROTOEND +#endif /* _XF86DGA_SERVER_ */ +#endif /* _XF86DGA_H_ */ diff --git a/3rdparty/SDL/src/video/Xext/extensions/xf86dga1.h b/3rdparty/SDL/src/video/Xext/extensions/xf86dga1.h new file mode 100644 index 0000000..4a49e9f --- /dev/null +++ b/3rdparty/SDL/src/video/Xext/extensions/xf86dga1.h @@ -0,0 +1,169 @@ +/* $XFree86: xc/include/extensions/xf86dga1.h,v 1.2 1999/04/17 07:05:41 dawes Exp $ */ +/* + +Copyright (c) 1995 Jon Tombs +Copyright (c) 1995 XFree86 Inc + +*/ + +/************************************************************************ + + THIS IS THE OLD DGA API AND IS OBSOLETE. PLEASE DO NOT USE IT ANYMORE + +************************************************************************/ + +#ifndef _XF86DGA1_H_ +#define _XF86DGA1_H_ + +#include <X11/Xfuncproto.h> +#include "SDL_name.h" + +#define X_XF86DGAQueryVersion 0 +#define X_XF86DGAGetVideoLL 1 +#define X_XF86DGADirectVideo 2 +#define X_XF86DGAGetViewPortSize 3 +#define X_XF86DGASetViewPort 4 +#define X_XF86DGAGetVidPage 5 +#define X_XF86DGASetVidPage 6 +#define X_XF86DGAInstallColormap 7 +#define X_XF86DGAQueryDirectVideo 8 +#define X_XF86DGAViewPortChanged 9 + +#define XF86DGADirectPresent 0x0001 +#define XF86DGADirectGraphics 0x0002 +#define XF86DGADirectMouse 0x0004 +#define XF86DGADirectKeyb 0x0008 +#define XF86DGAHasColormap 0x0100 +#define XF86DGADirectColormap 0x0200 + + + + +#ifndef _XF86DGA_SERVER_ + +_XFUNCPROTOBEGIN + +Bool SDL_NAME(XF86DGAQueryVersion)( +#if NeedFunctionPrototypes + Display* /* dpy */, + int* /* majorVersion */, + int* /* minorVersion */ +#endif +); + +Bool SDL_NAME(XF86DGAQueryExtension)( +#if NeedFunctionPrototypes + Display* /* dpy */, + int* /* event_base */, + int* /* error_base */ +#endif +); + +Status SDL_NAME(XF86DGAGetVideoLL)( +#if NeedFunctionPrototypes + Display* /* dpy */, + int /* screen */, + int * /* base addr */, + int * /* width */, + int * /* bank_size */, + int * /* ram_size */ +#endif +); + +Status SDL_NAME(XF86DGAGetVideo)( +#if NeedFunctionPrototypes + Display* /* dpy */, + int /* screen */, + char ** /* base addr */, + int * /* width */, + int * /* bank_size */, + int * /* ram_size */ +#endif +); + +Status SDL_NAME(XF86DGADirectVideo)( +#if NeedFunctionPrototypes + Display* /* dpy */, + int /* screen */, + int /* enable */ +#endif +); + +Status SDL_NAME(XF86DGADirectVideoLL)( +#if NeedFunctionPrototypes + Display* /* dpy */, + int /* screen */, + int /* enable */ +#endif +); + +Status SDL_NAME(XF86DGAGetViewPortSize)( +#if NeedFunctionPrototypes + Display* /* dpy */, + int /* screen */, + int * /* width */, + int * /* height */ +#endif +); + +Status SDL_NAME(XF86DGASetViewPort)( +#if NeedFunctionPrototypes + Display* /* dpy */, + int /* screen */, + int x /* X */, + int y /* Y */ +#endif +); + +Status SDL_NAME(XF86DGAGetVidPage)( +#if NeedFunctionPrototypes + Display* /* dpy */, + int /* screen */, + int * /* vid page */ +#endif +); + +Status SDL_NAME(XF86DGASetVidPage)( +#if NeedFunctionPrototypes + Display* /* dpy */, + int /* screen */, + int /* vid page */ +#endif +); + +Status SDL_NAME(XF86DGAInstallColormap)( +#if NeedFunctionPrototypes + Display* /* dpy */, + int /* screen */, + Colormap /*Colormap */ +#endif +); + +int SDL_NAME(XF86DGAForkApp)( +#if NeedFunctionPrototypes + int screen +#endif +); + +Status SDL_NAME(XF86DGAQueryDirectVideo)( +#if NeedFunctionPrototypes + Display * /* dpy */, + int /* screen */, + int * /* flags */ +#endif +); + +Bool SDL_NAME(XF86DGAViewPortChanged)( +#if NeedFunctionPrototypes + Display * /* dpy */, + int /* screen */, + int /* n */ +#endif +); + + +_XFUNCPROTOEND + +#endif /* _XF86DGA_SERVER_ */ + +#endif /* _XF86DGA1_H_ */ diff --git a/3rdparty/SDL/src/video/Xext/extensions/xf86dga1str.h b/3rdparty/SDL/src/video/Xext/extensions/xf86dga1str.h new file mode 100644 index 0000000..5695fbd --- /dev/null +++ b/3rdparty/SDL/src/video/Xext/extensions/xf86dga1str.h @@ -0,0 +1,194 @@ +/* $XFree86: xc/include/extensions/xf86dga1str.h,v 1.2 1999/05/03 12:15:37 dawes Exp $ */ +/* + +Copyright (c) 1995 Jon Tombs +Copyright (c) 1995 XFree86 Inc. + +*/ + +#ifndef _XF86DGASTR1_H_ +#define _XF86DGASTR1_H_ + +typedef struct _XF86DGAQueryVersion { + CARD8 reqType; /* always DGAReqCode */ + CARD8 dgaReqType; /* always X_DGAQueryVersion */ + CARD16 length B16; +} xXF86DGAQueryVersionReq; +#define sz_xXF86DGAQueryVersionReq 4 + +typedef struct { + BYTE type; /* X_Reply */ + BOOL pad1; + CARD16 sequenceNumber B16; + CARD32 length B32; + CARD16 majorVersion B16; /* major version of DGA protocol */ + CARD16 minorVersion B16; /* minor version of DGA protocol */ + CARD32 pad2 B32; + CARD32 pad3 B32; + CARD32 pad4 B32; + CARD32 pad5 B32; + CARD32 pad6 B32; +} xXF86DGAQueryVersionReply; +#define sz_xXF86DGAQueryVersionReply 32 + +typedef struct _XF86DGAGetVideoLL { + CARD8 reqType; /* always DGAReqCode */ + CARD8 dgaReqType; /* always X_XF86DGAGetVideoLL */ + CARD16 length B16; + CARD16 screen B16; + CARD16 pad B16; +} xXF86DGAGetVideoLLReq; +#define sz_xXF86DGAGetVideoLLReq 8 + +typedef struct _XF86DGAInstallColormap{ + CARD8 reqType; + CARD8 dgaReqType; + CARD16 length B16; + CARD16 screen B16; + CARD16 pad2; + CARD32 id B32; /* colormap. */ +} xXF86DGAInstallColormapReq; +#define sz_xXF86DGAInstallColormapReq 12 + + +typedef struct { + BYTE type; + BOOL pad1; + CARD16 sequenceNumber B16; + CARD32 length B32; + CARD32 offset B32; + CARD32 width B32; + CARD32 bank_size B32; + CARD32 ram_size B32; + CARD32 pad4 B32; + CARD32 pad5 B32; +} xXF86DGAGetVideoLLReply; +#define sz_xXF86DGAGetVideoLLReply 32 + +typedef struct _XF86DGADirectVideo { + CARD8 reqType; /* always DGAReqCode */ + CARD8 dgaReqType; /* always X_XF86DGADirectVideo */ + CARD16 length B16; + CARD16 screen B16; + CARD16 enable B16; +} xXF86DGADirectVideoReq; +#define sz_xXF86DGADirectVideoReq 8 + + +typedef struct _XF86DGAGetViewPortSize { + CARD8 reqType; /* always DGAReqCode */ + CARD8 dgaReqType; /* always X_XF86DGAGetViewPort */ + CARD16 length B16; + CARD16 screen B16; + CARD16 pad B16; +} xXF86DGAGetViewPortSizeReq; +#define sz_xXF86DGAGetViewPortSizeReq 8 + +typedef struct { + BYTE type; + BOOL pad1; + CARD16 sequenceNumber B16; + CARD32 length B32; + CARD32 width B32; + CARD32 height B32; + CARD32 pad2 B32; + CARD32 pad3 B32; + CARD32 pad4 B32; + CARD32 pad5 B32; +} xXF86DGAGetViewPortSizeReply; +#define sz_xXF86DGAGetViewPortSizeReply 32 + +typedef struct _XF86DGASetViewPort { + CARD8 reqType; /* always DGAReqCode */ + CARD8 dgaReqType; /* always X_XF86DGASetViewPort */ + CARD16 length B16; + CARD16 screen B16; + CARD16 pad B16; + CARD32 x B32; + CARD32 y B32; +} xXF86DGASetViewPortReq; +#define sz_xXF86DGASetViewPortReq 16 + +typedef struct _XF86DGAGetVidPage { + CARD8 reqType; /* always DGAReqCode */ + CARD8 dgaReqType; /* always X_XF86DGAGetVidPage */ + CARD16 length B16; + CARD16 screen B16; + CARD16 pad B16; +} xXF86DGAGetVidPageReq; +#define sz_xXF86DGAGetVidPageReq 8 + +typedef struct { + BYTE type; + BOOL pad1; + CARD16 sequenceNumber B16; + CARD32 length B32; + CARD32 vpage B32; + CARD32 pad B32; + CARD32 pad2 B32; + CARD32 pad3 B32; + CARD32 pad4 B32; + CARD32 pad5 B32; +} xXF86DGAGetVidPageReply; +#define sz_xXF86DGAGetVidPageReply 32 + + +typedef struct _XF86DGASetVidPage { + CARD8 reqType; /* always DGAReqCode */ + CARD8 dgaReqType; /* always X_XF86DGASetVidPage */ + CARD16 length B16; + CARD16 screen B16; + CARD16 vpage B16; +} xXF86DGASetVidPageReq; +#define sz_xXF86DGASetVidPageReq 8 + + +typedef struct _XF86DGAQueryDirectVideo { + CARD8 reqType; /* always DGAReqCode */ + CARD8 dgaReqType; /* always X_DGAQueryVersion */ + CARD16 length B16; + CARD16 screen B16; + CARD16 pad B16; +} xXF86DGAQueryDirectVideoReq; +#define sz_xXF86DGAQueryDirectVideoReq 8 + +typedef struct { + BYTE type; + BOOL pad1; + CARD16 sequenceNumber B16; + CARD32 length B32; + CARD32 flags B32; + CARD32 pad B32; + CARD32 pad2 B32; + CARD32 pad3 B32; + CARD32 pad4 B32; + CARD32 pad5 B32; +} xXF86DGAQueryDirectVideoReply; +#define sz_xXF86DGAQueryDirectVideoReply 32 + + +typedef struct _XF86DGAViewPortChanged { + CARD8 reqType; /* always DGAReqCode */ + CARD8 dgaReqType; /* always X_DGAQueryVersion */ + CARD16 length B16; + CARD16 screen B16; + CARD16 n B16; +} xXF86DGAViewPortChangedReq; +#define sz_xXF86DGAViewPortChangedReq 8 + +typedef struct { + BYTE type; + BOOL pad1; + CARD16 sequenceNumber B16; + CARD32 length B32; + CARD32 result B32; + CARD32 pad B32; + CARD32 pad2 B32; + CARD32 pad3 B32; + CARD32 pad4 B32; + CARD32 pad5 B32; +} xXF86DGAViewPortChangedReply; +#define sz_xXF86DGAViewPortChangedReply 32 + +#endif /* _XF86DGASTR1_H_ */ + diff --git a/3rdparty/SDL/src/video/Xext/extensions/xf86dgastr.h b/3rdparty/SDL/src/video/Xext/extensions/xf86dgastr.h new file mode 100644 index 0000000..b249feb --- /dev/null +++ b/3rdparty/SDL/src/video/Xext/extensions/xf86dgastr.h @@ -0,0 +1,344 @@ +/* $XFree86: xc/include/extensions/xf86dgastr.h,v 3.14 2001/08/01 00:44:36 tsi Exp $ */ +/* + +Copyright (c) 1995 Jon Tombs +Copyright (c) 1995 XFree86 Inc. + +*/ + +#ifndef _XF86DGASTR_H_ +#define _XF86DGASTR_H_ + +#include "xf86dga1str.h" + +#define XF86DGANAME "XFree86-DGA" + +#define XDGA_MAJOR_VERSION 2 /* current version numbers */ +#define XDGA_MINOR_VERSION 0 + + +typedef struct _XDGAQueryVersion { + CARD8 reqType; /* always DGAReqCode */ + CARD8 dgaReqType; /* always X_DGAQueryVersion */ + CARD16 length B16; +} xXDGAQueryVersionReq; +#define sz_xXDGAQueryVersionReq 4 + +typedef struct { + BYTE type; /* X_Reply */ + BOOL pad1; + CARD16 sequenceNumber B16; + CARD32 length B32; + CARD16 majorVersion B16; /* major version of DGA protocol */ + CARD16 minorVersion B16; /* minor version of DGA protocol */ + CARD32 pad2 B32; + CARD32 pad3 B32; + CARD32 pad4 B32; + CARD32 pad5 B32; + CARD32 pad6 B32; +} xXDGAQueryVersionReply; +#define sz_xXDGAQueryVersionReply 32 + +typedef struct _XDGAQueryModes { + CARD8 reqType; + CARD8 dgaReqType; + CARD16 length B16; + CARD32 screen B32; +} xXDGAQueryModesReq; +#define sz_xXDGAQueryModesReq 8 + +typedef struct { + BYTE type; /* X_Reply */ + BOOL pad1; + CARD16 sequenceNumber B16; + CARD32 length B32; + CARD32 number B32; /* number of modes available */ + CARD32 pad2 B32; + CARD32 pad3 B32; + CARD32 pad4 B32; + CARD32 pad5 B32; + CARD32 pad6 B32; +} xXDGAQueryModesReply; +#define sz_xXDGAQueryModesReply 32 + + +typedef struct _XDGASetMode { + CARD8 reqType; + CARD8 dgaReqType; + CARD16 length B16; + CARD32 screen B32; + CARD32 mode B32; /* mode number to init */ + CARD32 pid B32; /* Pixmap descriptor */ +} xXDGASetModeReq; +#define sz_xXDGASetModeReq 16 + +typedef struct { + BYTE type; /* X_Reply */ + BOOL pad1; + CARD16 sequenceNumber B16; + CARD32 length B32; + CARD32 offset B32; /* offset into framebuffer map */ + CARD32 flags B32; + CARD32 pad2 B32; + CARD32 pad3 B32; + CARD32 pad4 B32; + CARD32 pad5 B32; +} xXDGASetModeReply; +#define sz_xXDGASetModeReply 32 + +typedef struct { + CARD8 byte_order; + CARD8 depth; + CARD16 num B16; + CARD16 bpp B16; + CARD16 name_size B16; + CARD32 vsync_num B32; + CARD32 vsync_den B32; + CARD32 flags B32; + CARD16 image_width B16; + CARD16 image_height B16; + CARD16 pixmap_width B16; + CARD16 pixmap_height B16; + CARD32 bytes_per_scanline B32; + CARD32 red_mask B32; + CARD32 green_mask B32; + CARD32 blue_mask B32; + CARD16 visual_class B16; + CARD16 pad1 B16; + CARD16 viewport_width B16; + CARD16 viewport_height B16; + CARD16 viewport_xstep B16; + CARD16 viewport_ystep B16; + CARD16 viewport_xmax B16; + CARD16 viewport_ymax B16; + CARD32 viewport_flags B32; + CARD32 reserved1 B32; + CARD32 reserved2 B32; +} xXDGAModeInfo; +#define sz_xXDGAModeInfo 72 + +typedef struct _XDGAOpenFramebuffer { + CARD8 reqType; + CARD8 dgaReqType; + CARD16 length B16; + CARD32 screen B32; +} xXDGAOpenFramebufferReq; +#define sz_xXDGAOpenFramebufferReq 8 + +typedef struct { + BYTE type; /* X_Reply */ + BOOL pad1; + CARD16 sequenceNumber B16; + CARD32 length B32; /* device name size if there is one */ + CARD32 mem1 B32; /* physical memory */ + CARD32 mem2 B32; /* spillover for _alpha_ */ + CARD32 size B32; /* size of map in bytes */ + CARD32 offset B32; /* optional offset into device */ + CARD32 extra B32; /* extra info associated with the map */ + CARD32 pad2 B32; +} xXDGAOpenFramebufferReply; +#define sz_xXDGAOpenFramebufferReply 32 + + +typedef struct _XDGACloseFramebuffer { + CARD8 reqType; + CARD8 dgaReqType; + CARD16 length B16; + CARD32 screen B32; +} xXDGACloseFramebufferReq; +#define sz_xXDGACloseFramebufferReq 8 + + +typedef struct _XDGASetViewport { + CARD8 reqType; + CARD8 dgaReqType; + CARD16 length B16; + CARD32 screen B32; + CARD16 x B16; + CARD16 y B16; + CARD32 flags B32; +} xXDGASetViewportReq; +#define sz_xXDGASetViewportReq 16 + + +typedef struct _XDGAInstallColormap { + CARD8 reqType; + CARD8 dgaReqType; + CARD16 length B16; + CARD32 screen B32; + CARD32 cmap B32; +} xXDGAInstallColormapReq; +#define sz_xXDGAInstallColormapReq 12 + +typedef struct _XDGASelectInput { + CARD8 reqType; + CARD8 dgaReqType; + CARD16 length B16; + CARD32 screen B32; + CARD32 mask B32; +} xXDGASelectInputReq; +#define sz_xXDGASelectInputReq 12 + +typedef struct _XDGAFillRectangle { + CARD8 reqType; + CARD8 dgaReqType; + CARD16 length B16; + CARD32 screen B32; + CARD16 x B16; + CARD16 y B16; + CARD16 width B16; + CARD16 height B16; + CARD32 color B32; +} xXDGAFillRectangleReq; +#define sz_xXDGAFillRectangleReq 20 + + +typedef struct _XDGACopyArea { + CARD8 reqType; + CARD8 dgaReqType; + CARD16 length B16; + CARD32 screen B32; + CARD16 srcx B16; + CARD16 srcy B16; + CARD16 width B16; + CARD16 height B16; + CARD16 dstx B16; + CARD16 dsty B16; +} xXDGACopyAreaReq; +#define sz_xXDGACopyAreaReq 20 + +typedef struct _XDGACopyTransparentArea { + CARD8 reqType; + CARD8 dgaReqType; + CARD16 length B16; + CARD32 screen B32; + CARD16 srcx B16; + CARD16 srcy B16; + CARD16 width B16; + CARD16 height B16; + CARD16 dstx B16; + CARD16 dsty B16; + CARD32 key B32; +} xXDGACopyTransparentAreaReq; +#define sz_xXDGACopyTransparentAreaReq 24 + + +typedef struct _XDGAGetViewportStatus { + CARD8 reqType; + CARD8 dgaReqType; + CARD16 length B16; + CARD32 screen B32; +} xXDGAGetViewportStatusReq; +#define sz_xXDGAGetViewportStatusReq 8 + +typedef struct { + BYTE type; + BOOL pad1; + CARD16 sequenceNumber B16; + CARD32 length B32; + CARD32 status B32; + CARD32 pad2 B32; + CARD32 pad3 B32; + CARD32 pad4 B32; + CARD32 pad5 B32; + CARD32 pad6 B32; +} xXDGAGetViewportStatusReply; +#define sz_xXDGAGetViewportStatusReply 32 + +typedef struct _XDGASync { + CARD8 reqType; + CARD8 dgaReqType; + CARD16 length B16; + CARD32 screen B32; +} xXDGASyncReq; +#define sz_xXDGASyncReq 8 + +typedef struct { + BYTE type; + BOOL pad1; + CARD16 sequenceNumber B16; + CARD32 length B32; + CARD32 pad2 B32; + CARD32 pad3 B32; + CARD32 pad4 B32; + CARD32 pad5 B32; + CARD32 pad6 B32; + CARD32 pad7 B32; +} xXDGASyncReply; +#define sz_xXDGASyncReply 32 + +typedef struct _XDGASetClientVersion { + CARD8 reqType; + CARD8 dgaReqType; + CARD16 length B16; + CARD16 major B16; + CARD16 minor B16; +} xXDGASetClientVersionReq; +#define sz_xXDGASetClientVersionReq 8 + + +typedef struct { + CARD8 reqType; + CARD8 dgaReqType; + CARD16 length B16; + CARD32 screen B32; + CARD16 x B16; + CARD16 y B16; + CARD32 flags B32; +} xXDGAChangePixmapModeReq; +#define sz_xXDGAChangePixmapModeReq 16 + +typedef struct { + BYTE type; + BOOL pad1; + CARD16 sequenceNumber B16; + CARD32 length B32; + CARD16 x B16; + CARD16 y B16; + CARD32 pad3 B32; + CARD32 pad4 B32; + CARD32 pad5 B32; + CARD32 pad6 B32; + CARD32 pad7 B32; +} xXDGAChangePixmapModeReply; +#define sz_xXDGAChangePixmapModeReply 32 + +typedef struct _XDGACreateColormap { + CARD8 reqType; + CARD8 dgaReqType; + CARD16 length B16; + CARD32 screen B32; + CARD32 id B32; + CARD32 mode B32; + CARD8 alloc; + CARD8 pad1; + CARD16 pad2; +} xXDGACreateColormapReq; +#define sz_xXDGACreateColormapReq 20 + + +typedef struct { + union { + struct { + BYTE type; + BYTE detail; + CARD16 sequenceNumber B16; + } u; + struct { + CARD32 pad0 B32; + CARD32 time B32; + INT16 dx B16; + INT16 dy B16; + INT16 screen B16; + CARD16 state B16; + CARD32 pad1 B32; + CARD32 pad2 B32; + CARD32 pad3 B32; + CARD32 pad4 B32; + } event; + } u; +} dgaEvent; + + +#endif /* _XF86DGASTR_H_ */ + diff --git a/3rdparty/SDL/src/video/Xext/extensions/xf86vmode.h b/3rdparty/SDL/src/video/Xext/extensions/xf86vmode.h new file mode 100644 index 0000000..eb56c0e --- /dev/null +++ b/3rdparty/SDL/src/video/Xext/extensions/xf86vmode.h @@ -0,0 +1,314 @@ +/* $XFree86: xc/include/extensions/xf86vmode.h,v 3.30 2001/05/07 20:09:50 mvojkovi Exp $ */ +/* + +Copyright 1995 Kaleb S. KEITHLEY + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL Kaleb S. KEITHLEY BE LIABLE FOR ANY CLAIM, DAMAGES +OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of Kaleb S. KEITHLEY +shall not be used in advertising or otherwise to promote the sale, use +or other dealings in this Software without prior written authorization +from Kaleb S. KEITHLEY + +*/ +/* $Xorg: xf86vmode.h,v 1.3 2000/08/18 04:05:46 coskrey Exp $ */ + +/* THIS IS NOT AN X CONSORTIUM STANDARD OR AN X PROJECT TEAM SPECIFICATION */ + +#ifndef _XF86VIDMODE_H_ +#define _XF86VIDMODE_H_ + +#include <X11/Xfuncproto.h> +#include <X11/Xmd.h> +#include "SDL_name.h" + +#define X_XF86VidModeQueryVersion 0 +#define X_XF86VidModeGetModeLine 1 +#define X_XF86VidModeModModeLine 2 +#define X_XF86VidModeSwitchMode 3 +#define X_XF86VidModeGetMonitor 4 +#define X_XF86VidModeLockModeSwitch 5 +#define X_XF86VidModeGetAllModeLines 6 +#define X_XF86VidModeAddModeLine 7 +#define X_XF86VidModeDeleteModeLine 8 +#define X_XF86VidModeValidateModeLine 9 +#define X_XF86VidModeSwitchToMode 10 +#define X_XF86VidModeGetViewPort 11 +#define X_XF86VidModeSetViewPort 12 +/* new for version 2.x of this extension */ +#define X_XF86VidModeGetDotClocks 13 +#define X_XF86VidModeSetClientVersion 14 +#define X_XF86VidModeSetGamma 15 +#define X_XF86VidModeGetGamma 16 +#define X_XF86VidModeGetGammaRamp 17 +#define X_XF86VidModeSetGammaRamp 18 +#define X_XF86VidModeGetGammaRampSize 19 + +#define CLKFLAG_PROGRAMABLE 1 + +#ifdef XF86VIDMODE_EVENTS +#define XF86VidModeNotify 0 +#define XF86VidModeNumberEvents (XF86VidModeNotify + 1) + +#define XF86VidModeNotifyMask 0x00000001 + +#define XF86VidModeNonEvent 0 +#define XF86VidModeModeChange 1 +#else +#define XF86VidModeNumberEvents 0 +#endif + +#define XF86VidModeBadClock 0 +#define XF86VidModeBadHTimings 1 +#define XF86VidModeBadVTimings 2 +#define XF86VidModeModeUnsuitable 3 +#define XF86VidModeExtensionDisabled 4 +#define XF86VidModeClientNotLocal 5 +#define XF86VidModeZoomLocked 6 +#define XF86VidModeNumberErrors (XF86VidModeZoomLocked + 1) + +#ifndef _XF86VIDMODE_SERVER_ + +typedef struct { + unsigned short hdisplay; + unsigned short hsyncstart; + unsigned short hsyncend; + unsigned short htotal; + unsigned short hskew; + unsigned short vdisplay; + unsigned short vsyncstart; + unsigned short vsyncend; + unsigned short vtotal; + unsigned int flags; + int privsize; +#if defined(__cplusplus) || defined(c_plusplus) + /* private is a C++ reserved word */ + INT32 *c_private; +#else + INT32 *private; +#endif +} SDL_NAME(XF86VidModeModeLine); + +typedef struct { + unsigned int dotclock; + unsigned short hdisplay; + unsigned short hsyncstart; + unsigned short hsyncend; + unsigned short htotal; + unsigned short hskew; + unsigned short vdisplay; + unsigned short vsyncstart; + unsigned short vsyncend; + unsigned short vtotal; + unsigned int flags; + int privsize; +#if defined(__cplusplus) || defined(c_plusplus) + /* private is a C++ reserved word */ + INT32 *c_private; +#else + INT32 *private; +#endif +} SDL_NAME(XF86VidModeModeInfo); + +typedef struct { + float hi; + float lo; +} SDL_NAME(XF86VidModeSyncRange); + +typedef struct { + char* vendor; + char* model; + float EMPTY; + unsigned char nhsync; + SDL_NAME(XF86VidModeSyncRange)* hsync; + unsigned char nvsync; + SDL_NAME(XF86VidModeSyncRange)* vsync; +} SDL_NAME(XF86VidModeMonitor); + +typedef struct { + int type; /* of event */ + unsigned long serial; /* # of last request processed by server */ + Bool send_event; /* true if this came from a SendEvent req */ + Display *display; /* Display the event was read from */ + Window root; /* root window of event screen */ + int state; /* What happened */ + int kind; /* What happened */ + Bool forced; /* extents of new region */ + Time time; /* event timestamp */ +} SDL_NAME(XF86VidModeNotifyEvent); + +typedef struct { + float red; /* Red Gamma value */ + float green; /* Green Gamma value */ + float blue; /* Blue Gamma value */ +} SDL_NAME(XF86VidModeGamma); + + +#define SDL_XF86VidModeSelectNextMode(disp, scr) \ + SDL_NAME(XF86VidModeSwitchMode)(disp, scr, 1) +#define SDL_XF86VidModeSelectPrevMode(disp, scr) \ + SDL_NAME(XF86VidModeSwitchMode)(disp, scr, -1) + +_XFUNCPROTOBEGIN + +Bool SDL_NAME(XF86VidModeQueryVersion)( + Display* /* dpy */, + int* /* majorVersion */, + int* /* minorVersion */ +); + +Bool SDL_NAME(XF86VidModeQueryExtension)( + Display* /* dpy */, + int* /* event_base */, + int* /* error_base */ +); + +Bool SDL_NAME(XF86VidModeSetClientVersion)( + Display* /* dpy */ +); + +Bool SDL_NAME(XF86VidModeGetModeLine)( + Display* /* dpy */, + int /* screen */, + int* /* dotclock */, + SDL_NAME(XF86VidModeModeLine)* /* modeline */ +); + +Bool SDL_NAME(XF86VidModeGetAllModeLines)( + Display* /* dpy */, + int /* screen */, + int* /* modecount */, + SDL_NAME(XF86VidModeModeInfo)*** /* modelinesPtr */ +); + +Bool SDL_NAME(XF86VidModeAddModeLine)( + Display* /* dpy */, + int /* screen */, + SDL_NAME(XF86VidModeModeInfo)* /* new modeline */, + SDL_NAME(XF86VidModeModeInfo)* /* after modeline */ +); + +Bool SDL_NAME(XF86VidModeDeleteModeLine)( + Display* /* dpy */, + int /* screen */, + SDL_NAME(XF86VidModeModeInfo)* /* modeline */ +); + +Bool SDL_NAME(XF86VidModeModModeLine)( + Display* /* dpy */, + int /* screen */, + SDL_NAME(XF86VidModeModeLine)* /* modeline */ +); + +Status SDL_NAME(XF86VidModeValidateModeLine)( + Display* /* dpy */, + int /* screen */, + SDL_NAME(XF86VidModeModeInfo)* /* modeline */ +); + +Bool SDL_NAME(XF86VidModeSwitchMode)( + Display* /* dpy */, + int /* screen */, + int /* zoom */ +); + +Bool SDL_NAME(XF86VidModeSwitchToMode)( + Display* /* dpy */, + int /* screen */, + SDL_NAME(XF86VidModeModeInfo)* /* modeline */ +); + +Bool SDL_NAME(XF86VidModeLockModeSwitch)( + Display* /* dpy */, + int /* screen */, + int /* lock */ +); + +Bool SDL_NAME(XF86VidModeGetMonitor)( + Display* /* dpy */, + int /* screen */, + SDL_NAME(XF86VidModeMonitor)* /* monitor */ +); + +Bool SDL_NAME(XF86VidModeGetViewPort)( + Display* /* dpy */, + int /* screen */, + int* /* x return */, + int* /* y return */ +); + +Bool SDL_NAME(XF86VidModeSetViewPort)( + Display* /* dpy */, + int /* screen */, + int /* x */, + int /* y */ +); + +Bool SDL_NAME(XF86VidModeGetDotClocks)( + Display* /* dpy */, + int /* screen */, + int* /* flags return */, + int* /* number of clocks return */, + int* /* max dot clock return */, + int** /* clocks return */ +); + +Bool SDL_NAME(XF86VidModeGetGamma)( + Display* /* dpy */, + int /* screen */, + SDL_NAME(XF86VidModeGamma)* /* Gamma */ +); + +Bool SDL_NAME(XF86VidModeSetGamma)( + Display* /* dpy */, + int /* screen */, + SDL_NAME(XF86VidModeGamma)* /* Gamma */ +); + +Bool SDL_NAME(XF86VidModeSetGammaRamp)( + Display* /* dpy */, + int /* screen */, + int /* size */, + unsigned short* /* red array */, + unsigned short* /* green array */, + unsigned short* /* blue array */ +); + +Bool SDL_NAME(XF86VidModeGetGammaRamp)( + Display* /* dpy */, + int /* screen */, + int /* size */, + unsigned short* /* red array */, + unsigned short* /* green array */, + unsigned short* /* blue array */ +); + +Bool SDL_NAME(XF86VidModeGetGammaRampSize)( + Display* /* dpy */, + int /* screen */, + int* /* size */ +); + + +_XFUNCPROTOEND + +#endif + +#endif diff --git a/3rdparty/SDL/src/video/Xext/extensions/xf86vmstr.h b/3rdparty/SDL/src/video/Xext/extensions/xf86vmstr.h new file mode 100644 index 0000000..0c3078d --- /dev/null +++ b/3rdparty/SDL/src/video/Xext/extensions/xf86vmstr.h @@ -0,0 +1,546 @@ +/* $XFree86: xc/include/extensions/xf86vmstr.h,v 3.27 2001/08/01 00:44:36 tsi Exp $ */ +/* + +Copyright 1995 Kaleb S. KEITHLEY + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL Kaleb S. KEITHLEY BE LIABLE FOR ANY CLAIM, DAMAGES +OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of Kaleb S. KEITHLEY +shall not be used in advertising or otherwise to promote the sale, use +or other dealings in this Software without prior written authorization +from Kaleb S. KEITHLEY + +*/ +/* $Xorg: xf86vmstr.h,v 1.3 2000/08/18 04:05:46 coskrey Exp $ */ + +/* THIS IS NOT AN X CONSORTIUM STANDARD OR AN X PROJECT TEAM SPECIFICATION */ + +#ifndef _XF86VIDMODESTR_H_ +#define _XF86VIDMODESTR_H_ + +#include "xf86vmode.h" + +#define XF86VIDMODENAME "XFree86-VidModeExtension" + +#define XF86VIDMODE_MAJOR_VERSION 2 /* current version numbers */ +#define XF86VIDMODE_MINOR_VERSION 1 +/* + * major version 0 == uses parameter-to-wire functions in XFree86 libXxf86vm. + * major version 1 == uses parameter-to-wire functions hard-coded in xvidtune + * client. + * major version 2 == uses new protocol version in XFree86 4.0. + */ + +typedef struct _XF86VidModeQueryVersion { + CARD8 reqType; /* always XF86VidModeReqCode */ + CARD8 xf86vidmodeReqType; /* always X_XF86VidModeQueryVersion */ + CARD16 length B16; +} xXF86VidModeQueryVersionReq; +#define sz_xXF86VidModeQueryVersionReq 4 + +typedef struct { + BYTE type; /* X_Reply */ + BOOL pad1; + CARD16 sequenceNumber B16; + CARD32 length B32; + CARD16 majorVersion B16; /* major version of XF86VidMode */ + CARD16 minorVersion B16; /* minor version of XF86VidMode */ + CARD32 pad2 B32; + CARD32 pad3 B32; + CARD32 pad4 B32; + CARD32 pad5 B32; + CARD32 pad6 B32; +} xXF86VidModeQueryVersionReply; +#define sz_xXF86VidModeQueryVersionReply 32 + +typedef struct _XF86VidModeGetModeLine { + CARD8 reqType; /* always XF86VidModeReqCode */ + CARD8 xf86vidmodeReqType; + CARD16 length B16; + CARD16 screen B16; + CARD16 pad B16; +} xXF86VidModeGetModeLineReq, + xXF86VidModeGetAllModeLinesReq, + xXF86VidModeGetMonitorReq, + xXF86VidModeGetViewPortReq, + xXF86VidModeGetDotClocksReq; +#define sz_xXF86VidModeGetModeLineReq 8 +#define sz_xXF86VidModeGetAllModeLinesReq 8 +#define sz_xXF86VidModeGetMonitorReq 8 +#define sz_xXF86VidModeGetViewPortReq 8 +#define sz_xXF86VidModeGetDotClocksReq 8 + +typedef struct { + BYTE type; /* X_Reply */ + BOOL pad1; + CARD16 sequenceNumber B16; + CARD32 length B32; + CARD32 dotclock B32; + CARD16 hdisplay B16; + CARD16 hsyncstart B16; + CARD16 hsyncend B16; + CARD16 htotal B16; + CARD16 hskew B16; + CARD16 vdisplay B16; + CARD16 vsyncstart B16; + CARD16 vsyncend B16; + CARD16 vtotal B16; + CARD16 pad2 B16; + CARD32 flags B32; + CARD32 reserved1 B32; + CARD32 reserved2 B32; + CARD32 reserved3 B32; + CARD32 privsize B32; +} xXF86VidModeGetModeLineReply; +#define sz_xXF86VidModeGetModeLineReply 52 + +/* 0.x version */ +typedef struct { + BYTE type; /* X_Reply */ + BOOL pad1; + CARD16 sequenceNumber B16; + CARD32 length B32; + CARD32 dotclock B32; + CARD16 hdisplay B16; + CARD16 hsyncstart B16; + CARD16 hsyncend B16; + CARD16 htotal B16; + CARD16 vdisplay B16; + CARD16 vsyncstart B16; + CARD16 vsyncend B16; + CARD16 vtotal B16; + CARD32 flags B32; + CARD32 privsize B32; +} xXF86OldVidModeGetModeLineReply; +#define sz_xXF86OldVidModeGetModeLineReply 36 + +typedef struct { + CARD32 dotclock B32; + CARD16 hdisplay B16; + CARD16 hsyncstart B16; + CARD16 hsyncend B16; + CARD16 htotal B16; + CARD32 hskew B16; + CARD16 vdisplay B16; + CARD16 vsyncstart B16; + CARD16 vsyncend B16; + CARD16 vtotal B16; + CARD16 pad1 B16; + CARD32 flags B32; + CARD32 reserved1 B32; + CARD32 reserved2 B32; + CARD32 reserved3 B32; + CARD32 privsize B32; +} xXF86VidModeModeInfo; + +/* 0.x version */ +typedef struct { + CARD32 dotclock B32; + CARD16 hdisplay B16; + CARD16 hsyncstart B16; + CARD16 hsyncend B16; + CARD16 htotal B16; + CARD16 vdisplay B16; + CARD16 vsyncstart B16; + CARD16 vsyncend B16; + CARD16 vtotal B16; + CARD32 flags B32; + CARD32 privsize B32; +} xXF86OldVidModeModeInfo; + +typedef struct { + BYTE type; /* X_Reply */ + BOOL pad1; + CARD16 sequenceNumber B16; + CARD32 length B32; + CARD32 modecount B32; + CARD32 pad2 B32; + CARD32 pad3 B32; + CARD32 pad4 B32; + CARD32 pad5 B32; + CARD32 pad6 B32; +} xXF86VidModeGetAllModeLinesReply; +#define sz_xXF86VidModeGetAllModeLinesReply 32 + +typedef struct _XF86VidModeAddModeLine { + CARD8 reqType; /* always XF86VidModeReqCode */ + CARD8 xf86vidmodeReqType; /* always X_XF86VidModeAddMode */ + CARD16 length B16; + CARD32 screen B32; /* could be CARD16 but need the pad */ + CARD32 dotclock B32; + CARD16 hdisplay B16; + CARD16 hsyncstart B16; + CARD16 hsyncend B16; + CARD16 htotal B16; + CARD16 hskew B16; + CARD16 vdisplay B16; + CARD16 vsyncstart B16; + CARD16 vsyncend B16; + CARD16 vtotal B16; + CARD16 pad1 B16; + CARD32 flags B32; + CARD32 reserved1 B32; + CARD32 reserved2 B32; + CARD32 reserved3 B32; + CARD32 privsize B32; + CARD32 after_dotclock B32; + CARD16 after_hdisplay B16; + CARD16 after_hsyncstart B16; + CARD16 after_hsyncend B16; + CARD16 after_htotal B16; + CARD16 after_hskew B16; + CARD16 after_vdisplay B16; + CARD16 after_vsyncstart B16; + CARD16 after_vsyncend B16; + CARD16 after_vtotal B16; + CARD16 pad2 B16; + CARD32 after_flags B32; + CARD32 reserved4 B32; + CARD32 reserved5 B32; + CARD32 reserved6 B32; +} xXF86VidModeAddModeLineReq; +#define sz_xXF86VidModeAddModeLineReq 92 + +/* 0.x version */ +typedef struct _XF86OldVidModeAddModeLine { + CARD8 reqType; /* always XF86VidModeReqCode */ + CARD8 xf86vidmodeReqType; /* always X_XF86VidModeAddMode */ + CARD16 length B16; + CARD32 screen B32; /* could be CARD16 but need the pad */ + CARD32 dotclock B32; + CARD16 hdisplay B16; + CARD16 hsyncstart B16; + CARD16 hsyncend B16; + CARD16 htotal B16; + CARD16 vdisplay B16; + CARD16 vsyncstart B16; + CARD16 vsyncend B16; + CARD16 vtotal B16; + CARD32 flags B32; + CARD32 privsize B32; + CARD32 after_dotclock B32; + CARD16 after_hdisplay B16; + CARD16 after_hsyncstart B16; + CARD16 after_hsyncend B16; + CARD16 after_htotal B16; + CARD16 after_vdisplay B16; + CARD16 after_vsyncstart B16; + CARD16 after_vsyncend B16; + CARD16 after_vtotal B16; + CARD32 after_flags B32; +} xXF86OldVidModeAddModeLineReq; +#define sz_xXF86OldVidModeAddModeLineReq 60 + +typedef struct _XF86VidModeModModeLine { + CARD8 reqType; /* always XF86VidModeReqCode */ + CARD8 xf86vidmodeReqType; /* always X_XF86VidModeModModeLine */ + CARD16 length B16; + CARD32 screen B32; /* could be CARD16 but need the pad */ + CARD16 hdisplay B16; + CARD16 hsyncstart B16; + CARD16 hsyncend B16; + CARD16 htotal B16; + CARD16 hskew B16; + CARD16 vdisplay B16; + CARD16 vsyncstart B16; + CARD16 vsyncend B16; + CARD16 vtotal B16; + CARD16 pad1 B16; + CARD32 flags B32; + CARD32 reserved1 B32; + CARD32 reserved2 B32; + CARD32 reserved3 B32; + CARD32 privsize B32; +} xXF86VidModeModModeLineReq; +#define sz_xXF86VidModeModModeLineReq 48 + +/* 0.x version */ +typedef struct _XF86OldVidModeModModeLine { + CARD8 reqType; /* always XF86OldVidModeReqCode */ + CARD8 xf86vidmodeReqType; /* always X_XF86OldVidModeModModeLine */ + CARD16 length B16; + CARD32 screen B32; /* could be CARD16 but need the pad */ + CARD16 hdisplay B16; + CARD16 hsyncstart B16; + CARD16 hsyncend B16; + CARD16 htotal B16; + CARD16 vdisplay B16; + CARD16 vsyncstart B16; + CARD16 vsyncend B16; + CARD16 vtotal B16; + CARD32 flags B32; + CARD32 privsize B32; +} xXF86OldVidModeModModeLineReq; +#define sz_xXF86OldVidModeModModeLineReq 32 + +typedef struct _XF86VidModeValidateModeLine { + CARD8 reqType; /* always XF86VidModeReqCode */ + CARD8 xf86vidmodeReqType; + CARD16 length B16; + CARD32 screen B32; /* could be CARD16 but need the pad */ + CARD32 dotclock B32; + CARD16 hdisplay B16; + CARD16 hsyncstart B16; + CARD16 hsyncend B16; + CARD16 htotal B16; + CARD16 hskew B16; + CARD16 vdisplay B16; + CARD16 vsyncstart B16; + CARD16 vsyncend B16; + CARD16 vtotal B16; + CARD16 pad1 B16; + CARD32 flags B32; + CARD32 reserved1 B32; + CARD32 reserved2 B32; + CARD32 reserved3 B32; + CARD32 privsize B32; +} xXF86VidModeDeleteModeLineReq, + xXF86VidModeValidateModeLineReq, + xXF86VidModeSwitchToModeReq; +#define sz_xXF86VidModeDeleteModeLineReq 52 +#define sz_xXF86VidModeValidateModeLineReq 52 +#define sz_xXF86VidModeSwitchToModeReq 52 + +/* 0.x version */ +typedef struct _XF86OldVidModeValidateModeLine { + CARD8 reqType; /* always XF86OldVidModeReqCode */ + CARD8 xf86vidmodeReqType; + CARD16 length B16; + CARD32 screen B32; /* could be CARD16 but need the pad */ + CARD32 dotclock B32; + CARD16 hdisplay B16; + CARD16 hsyncstart B16; + CARD16 hsyncend B16; + CARD16 htotal B16; + CARD16 vdisplay B16; + CARD16 vsyncstart B16; + CARD16 vsyncend B16; + CARD16 vtotal B16; + CARD32 flags B32; + CARD32 privsize B32; +} xXF86OldVidModeDeleteModeLineReq, + xXF86OldVidModeValidateModeLineReq, + xXF86OldVidModeSwitchToModeReq; +#define sz_xXF86OldVidModeDeleteModeLineReq 36 +#define sz_xXF86OldVidModeValidateModeLineReq 36 +#define sz_xXF86OldVidModeSwitchToModeReq 36 + +typedef struct _XF86VidModeSwitchMode { + CARD8 reqType; /* always XF86VidModeReqCode */ + CARD8 xf86vidmodeReqType; /* always X_XF86VidModeSwitchMode */ + CARD16 length B16; + CARD16 screen B16; + CARD16 zoom B16; +} xXF86VidModeSwitchModeReq; +#define sz_xXF86VidModeSwitchModeReq 8 + +typedef struct _XF86VidModeLockModeSwitch { + CARD8 reqType; /* always XF86VidModeReqCode */ + CARD8 xf86vidmodeReqType; /* always X_XF86VidModeLockModeSwitch */ + CARD16 length B16; + CARD16 screen B16; + CARD16 lock B16; +} xXF86VidModeLockModeSwitchReq; +#define sz_xXF86VidModeLockModeSwitchReq 8 + +typedef struct { + BYTE type; /* X_Reply */ + BOOL pad1; + CARD16 sequenceNumber B16; + CARD32 length B32; + CARD32 status B32; + CARD32 pad2 B32; + CARD32 pad3 B32; + CARD32 pad4 B32; + CARD32 pad5 B32; + CARD32 pad6 B32; +} xXF86VidModeValidateModeLineReply; +#define sz_xXF86VidModeValidateModeLineReply 32 + +typedef struct { + BYTE type; /* X_Reply */ + BOOL pad1; + CARD16 sequenceNumber B16; + CARD32 length B32; + CARD8 vendorLength; + CARD8 modelLength; + CARD8 nhsync; + CARD8 nvsync; + CARD32 pad2 B32; + CARD32 pad3 B32; + CARD32 pad4 B32; + CARD32 pad5 B32; + CARD32 pad6 B32; +} xXF86VidModeGetMonitorReply; +#define sz_xXF86VidModeGetMonitorReply 32 + +typedef struct { + BYTE type; + BOOL pad1; + CARD16 sequenceNumber B16; + CARD32 length B32; + CARD32 x B32; + CARD32 y B32; + CARD32 pad2 B32; + CARD32 pad3 B32; + CARD32 pad4 B32; + CARD32 pad5 B32; +} xXF86VidModeGetViewPortReply; +#define sz_xXF86VidModeGetViewPortReply 32 + +typedef struct _XF86VidModeSetViewPort { + CARD8 reqType; /* always VidModeReqCode */ + CARD8 xf86vidmodeReqType; /* always X_XF86VidModeSetViewPort */ + CARD16 length B16; + CARD16 screen B16; + CARD16 pad B16; + CARD32 x B32; + CARD32 y B32; +} xXF86VidModeSetViewPortReq; +#define sz_xXF86VidModeSetViewPortReq 16 + +typedef struct { + BYTE type; + BOOL pad1; + CARD16 sequenceNumber B16; + CARD32 length B32; + CARD32 flags B32; + CARD32 clocks B32; + CARD32 maxclocks B32; + CARD32 pad2 B32; + CARD32 pad3 B32; + CARD32 pad4 B32; +} xXF86VidModeGetDotClocksReply; +#define sz_xXF86VidModeGetDotClocksReply 32 + +typedef struct _XF86VidModeSetClientVersion { + CARD8 reqType; /* always XF86VidModeReqCode */ + CARD8 xf86vidmodeReqType; + CARD16 length B16; + CARD16 major B16; + CARD16 minor B16; +} xXF86VidModeSetClientVersionReq; +#define sz_xXF86VidModeSetClientVersionReq 8 + +typedef struct _XF86VidModeGetGamma { + CARD8 reqType; /* always XF86VidModeReqCode */ + CARD8 xf86vidmodeReqType; + CARD16 length B16; + CARD16 screen B16; + CARD16 pad B16; + CARD32 pad1 B32; + CARD32 pad2 B32; + CARD32 pad3 B32; + CARD32 pad4 B32; + CARD32 pad5 B32; + CARD32 pad6 B32; +} xXF86VidModeGetGammaReq; +#define sz_xXF86VidModeGetGammaReq 32 + +typedef struct { + BYTE type; + BOOL pad; + CARD16 sequenceNumber B16; + CARD32 length B32; + CARD32 red B32; + CARD32 green B32; + CARD32 blue B32; + CARD32 pad1 B32; + CARD32 pad2 B32; + CARD32 pad3 B32; +} xXF86VidModeGetGammaReply; +#define sz_xXF86VidModeGetGammaReply 32 + +typedef struct _XF86VidModeSetGamma { + CARD8 reqType; /* always XF86VidModeReqCode */ + CARD8 xf86vidmodeReqType; + CARD16 length B16; + CARD16 screen B16; + CARD16 pad B16; + CARD32 red B32; + CARD32 green B32; + CARD32 blue B32; + CARD32 pad1 B32; + CARD32 pad2 B32; + CARD32 pad3 B32; +} xXF86VidModeSetGammaReq; +#define sz_xXF86VidModeSetGammaReq 32 + + +typedef struct _XF86VidModeSetGammaRamp { + CARD8 reqType; /* always XF86VidModeReqCode */ + CARD8 xf86vidmodeReqType; + CARD16 length B16; + CARD16 screen B16; + CARD16 size B16; +} xXF86VidModeSetGammaRampReq; +#define sz_xXF86VidModeSetGammaRampReq 8 + +typedef struct _XF86VidModeGetGammaRamp { + CARD8 reqType; /* always XF86VidModeReqCode */ + CARD8 xf86vidmodeReqType; + CARD16 length B16; + CARD16 screen B16; + CARD16 size B16; +} xXF86VidModeGetGammaRampReq; +#define sz_xXF86VidModeGetGammaRampReq 8 + +typedef struct { + BYTE type; + BOOL pad; + CARD16 sequenceNumber B16; + CARD32 length B32; + CARD16 size B16; + CARD16 pad0 B16; + CARD32 pad1 B32; + CARD32 pad2 B32; + CARD32 pad3 B32; + CARD32 pad4 B32; + CARD32 pad5 B32; +} xXF86VidModeGetGammaRampReply; +#define sz_xXF86VidModeGetGammaRampReply 32 + +typedef struct _XF86VidModeGetGammaRampSize { + CARD8 reqType; /* always XF86VidModeReqCode */ + CARD8 xf86vidmodeReqType; + CARD16 length B16; + CARD16 screen B16; + CARD16 pad B16; +} xXF86VidModeGetGammaRampSizeReq; +#define sz_xXF86VidModeGetGammaRampSizeReq 8 + +typedef struct { + BYTE type; + BOOL pad; + CARD16 sequenceNumber B16; + CARD32 length B32; + CARD16 size B16; + CARD16 pad0 B16; + CARD32 pad1 B32; + CARD32 pad2 B32; + CARD32 pad3 B32; + CARD32 pad4 B32; + CARD32 pad5 B32; +} xXF86VidModeGetGammaRampSizeReply; +#define sz_xXF86VidModeGetGammaRampSizeReply 32 + + +#endif /* _XF86VIDMODESTR_H_ */ + diff --git a/3rdparty/SDL/src/video/Xext/extensions/xme.h b/3rdparty/SDL/src/video/Xext/extensions/xme.h new file mode 100644 index 0000000..f550623 --- /dev/null +++ b/3rdparty/SDL/src/video/Xext/extensions/xme.h @@ -0,0 +1,45 @@ +/* + * Copyright 1993-2001 by Xi Graphics, Inc. + * All Rights Reserved. + * + * Please see the LICENSE file accompanying this distribution for licensing + * information. + * + * Please send any bug fixes and modifications to src@xig.com. + * + * $XiGId: xme.h,v 1.1.1.1 2001/11/19 19:01:10 jon Exp $ + * + */ + + +#ifndef _XME_H_INCLUDED +#define _XME_H_INCLUDED + +typedef struct { + short x; + short y; + unsigned short w; + unsigned short h; +} XiGMiscViewInfo; + +typedef struct { + unsigned short width; + unsigned short height; + int refresh; +} XiGMiscResolutionInfo; + +extern Bool XiGMiscQueryVersion(Display *dpy, int *major, int *minor); +extern int XiGMiscQueryViews(Display *dpy, int screen, + XiGMiscViewInfo **pviews); +extern int XiGMiscQueryResolutions(Display *dpy, int screen, int view, + int *pactive, + XiGMiscResolutionInfo **presolutions); +extern void XiGMiscChangeResolution(Display *dpy, int screen, int view, + int width, int height, int refresh); + +/* SDL addition from Ryan: free memory used by xme. */ +extern void XiGMiscDestroy(void); + +#endif /* _XME_H_INCLUDED */ + + diff --git a/3rdparty/SDL/src/video/aalib/SDL_aaevents.c b/3rdparty/SDL/src/video/aalib/SDL_aaevents.c new file mode 100644 index 0000000..a26ab2d --- /dev/null +++ b/3rdparty/SDL/src/video/aalib/SDL_aaevents.c @@ -0,0 +1,202 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* Handle the event stream, converting AA events into SDL events */ + +#include <stdio.h> + +#include <aalib.h> + +#include "SDL.h" +#include "../../events/SDL_sysevents.h" +#include "../../events/SDL_events_c.h" +#include "SDL_aavideo.h" +#include "SDL_aaevents_c.h" + +/* The translation tables from a console scancode to a SDL keysym */ +static SDLKey keymap[401]; + +static SDL_keysym *TranslateKey(int scancode, SDL_keysym *keysym); + + +void AA_PumpEvents(_THIS) +{ + int posted = 0; + int mouse_button, mouse_x, mouse_y; + int evt; + SDL_keysym keysym; + + static int prev_button = -1, prev_x = -1, prev_y = -1; + + if( ! this->screen ) /* Wait till we got the screen initialized */ + return; + + do { + posted = 0; + /* Gather events */ + + /* Get mouse status */ + SDL_mutexP(AA_mutex); + aa_getmouse (AA_context, &mouse_x, &mouse_y, &mouse_button); + SDL_mutexV(AA_mutex); + mouse_x = mouse_x * this->screen->w / aa_scrwidth (AA_context); + mouse_y = mouse_y * this->screen->h / aa_scrheight (AA_context); + + /* Compare against previous state and generate events */ + if( prev_button != mouse_button ) { + if( mouse_button & AA_BUTTON1 ) { + if ( ! (prev_button & AA_BUTTON1) ) { + posted += SDL_PrivateMouseButton(SDL_PRESSED, 1, 0, 0); + } + } else { + if ( prev_button & AA_BUTTON1 ) { + posted += SDL_PrivateMouseButton(SDL_RELEASED, 1, 0, 0); + } + } + if( mouse_button & AA_BUTTON2 ) { + if ( ! (prev_button & AA_BUTTON2) ) { + posted += SDL_PrivateMouseButton(SDL_PRESSED, 2, 0, 0); + } + } else { + if ( prev_button & AA_BUTTON2 ) { + posted += SDL_PrivateMouseButton(SDL_RELEASED, 2, 0, 0); + } + } + if( mouse_button & AA_BUTTON3 ) { + if ( ! (prev_button & AA_BUTTON3) ) { + posted += SDL_PrivateMouseButton(SDL_PRESSED, 3, 0, 0); + } + } else { + if ( prev_button & AA_BUTTON3 ) { + posted += SDL_PrivateMouseButton(SDL_RELEASED, 3, 0, 0); + } + } + } + if ( prev_x != mouse_x || prev_y != mouse_y ) { + posted += SDL_PrivateMouseMotion(0, 0, mouse_x, mouse_y); + } + + prev_button = mouse_button; + prev_x = mouse_x; prev_y = mouse_y; + + /* Get keyboard event */ + SDL_mutexP(AA_mutex); + evt = aa_getevent(AA_context, 0); + SDL_mutexV(AA_mutex); + if ( (evt > AA_NONE) && (evt < AA_RELEASE) && (evt != AA_MOUSE) && (evt != AA_RESIZE) ) { + /* Key pressed */ +/* printf("Key pressed: %d (%c)\n", evt, evt); */ + posted += SDL_PrivateKeyboard(SDL_PRESSED, TranslateKey(evt, &keysym)); + } else if ( evt >= AA_RELEASE ) { + /* Key released */ + evt &= ~AA_RELEASE; +/* printf("Key released: %d (%c)\n", evt, evt); */ + posted += SDL_PrivateKeyboard(SDL_RELEASED, TranslateKey(evt, &keysym)); + } + } while ( posted ); +} + +void AA_InitOSKeymap(_THIS) +{ + int i; + static const char *std_keys = " 01234567890&#'()_-|$*+-=/\\:;.,!?<>{}[]@~%^\x9"; + const char *std; + + /* Initialize the AAlib key translation table */ + for ( i=0; i<SDL_arraysize(keymap); ++i ) + keymap[i] = SDLK_UNKNOWN; + + /* Alphabet keys */ + for ( i = 0; i<26; ++i ){ + keymap['a' + i] = SDLK_a+i; + keymap['A' + i] = SDLK_a+i; + } + /* Function keys */ + for ( i = 0; i<12; ++i ){ + keymap[334 + i] = SDLK_F1+i; + } + /* Keys that have the same symbols and don't have to be translated */ + for( std = std_keys; *std; std ++ ) { + keymap[*std] = *std; + } + + keymap[13] = SDLK_RETURN; + keymap[AA_BACKSPACE] = SDLK_BACKSPACE; + + keymap[369] = SDLK_LSHIFT; + keymap[370] = SDLK_RSHIFT; + keymap[371] = SDLK_LCTRL; + keymap[372] = SDLK_RCTRL; + keymap[377] = SDLK_LALT; + keymap[270] = SDLK_RALT; + keymap[271] = SDLK_NUMLOCK; + keymap[373] = SDLK_CAPSLOCK; + keymap[164] = SDLK_SCROLLOCK; + + keymap[243] = SDLK_INSERT; + keymap[304] = SDLK_DELETE; + keymap[224] = SDLK_HOME; + keymap[231] = SDLK_END; + keymap[229] = SDLK_PAGEUP; + keymap[230] = SDLK_PAGEDOWN; + + keymap[241] = SDLK_PRINT; + keymap[163] = SDLK_BREAK; + + keymap[302] = SDLK_KP0; + keymap[300] = SDLK_KP1; + keymap[297] = SDLK_KP2; + keymap[299] = SDLK_KP3; + keymap[294] = SDLK_KP4; + keymap[301] = SDLK_KP5; + keymap[296] = SDLK_KP6; + keymap[293] = SDLK_KP7; + keymap[295] = SDLK_KP8; + keymap[298] = SDLK_KP9; + + keymap[AA_ESC] = SDLK_ESCAPE; + keymap[AA_UP] = SDLK_UP; + keymap[AA_DOWN] = SDLK_DOWN; + keymap[AA_LEFT] = SDLK_LEFT; + keymap[AA_RIGHT] = SDLK_RIGHT; +} + +static SDL_keysym *TranslateKey(int scancode, SDL_keysym *keysym) +{ + /* Sanity check */ + if ( scancode >= SDL_arraysize(keymap) ) + scancode = AA_UNKNOWN; + + /* Set the keysym information */ + keysym->scancode = scancode; + keysym->sym = keymap[scancode]; + keysym->mod = KMOD_NONE; + + /* If UNICODE is on, get the UNICODE value for the key */ + keysym->unicode = 0; + if ( SDL_TranslateUNICODE ) { + /* Populate the unicode field with the ASCII value */ + keysym->unicode = scancode; + } + return(keysym); +} diff --git a/3rdparty/SDL/src/video/aalib/SDL_aaevents_c.h b/3rdparty/SDL/src/video/aalib/SDL_aaevents_c.h new file mode 100644 index 0000000..6dbc9f6 --- /dev/null +++ b/3rdparty/SDL/src/video/aalib/SDL_aaevents_c.h @@ -0,0 +1,35 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#include "SDL_aavideo.h" + +/* Variables and functions exported by SDL_sysevents.c to other parts + of the native video subsystem (SDL_sysvideo.c) +*/ +extern void AA_initkeymaps(int fd); +extern void AA_mousecallback(int button, int dx, int dy, + int u1,int u2,int u3, int u4); +extern void AA_keyboardcallback(int scancode, int pressed); + +extern void AA_InitOSKeymap(_THIS); +extern void AA_PumpEvents(_THIS); diff --git a/3rdparty/SDL/src/video/aalib/SDL_aamouse.c b/3rdparty/SDL/src/video/aalib/SDL_aamouse.c new file mode 100644 index 0000000..dc784a5 --- /dev/null +++ b/3rdparty/SDL/src/video/aalib/SDL_aamouse.c @@ -0,0 +1,35 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#include <stdio.h> + +#include "SDL_mouse.h" +#include "../../events/SDL_events_c.h" + +#include "SDL_aamouse_c.h" + + +/* The implementation dependent data for the window manager cursor */ +struct WMcursor { + int unused; +}; diff --git a/3rdparty/SDL/src/video/aalib/SDL_aamouse_c.h b/3rdparty/SDL/src/video/aalib/SDL_aamouse_c.h new file mode 100644 index 0000000..6ce3d98 --- /dev/null +++ b/3rdparty/SDL/src/video/aalib/SDL_aamouse_c.h @@ -0,0 +1,26 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#include "SDL_aavideo.h" + +/* Functions to be exported */ diff --git a/3rdparty/SDL/src/video/aalib/SDL_aavideo.c b/3rdparty/SDL/src/video/aalib/SDL_aavideo.c new file mode 100644 index 0000000..e6d5d3e --- /dev/null +++ b/3rdparty/SDL/src/video/aalib/SDL_aavideo.c @@ -0,0 +1,388 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* AAlib based SDL video driver implementation. +*/ + +#include <unistd.h> +#include <sys/stat.h> + + +#include "SDL_video.h" +#include "SDL_mouse.h" +#include "../SDL_sysvideo.h" +#include "../SDL_pixels_c.h" +#include "../../events/SDL_events_c.h" + +#include "SDL_aavideo.h" +#include "SDL_aaevents_c.h" +#include "SDL_aamouse_c.h" + +#include <aalib.h> + +/* Initialization/Query functions */ +static int AA_VideoInit(_THIS, SDL_PixelFormat *vformat); +static SDL_Rect **AA_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags); +static SDL_Surface *AA_SetVideoMode(_THIS, SDL_Surface *current, int width, int height, int bpp, Uint32 flags); +static int AA_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors); +static void AA_VideoQuit(_THIS); + +/* Hardware surface functions */ +static int AA_AllocHWSurface(_THIS, SDL_Surface *surface); +static int AA_LockHWSurface(_THIS, SDL_Surface *surface); +static int AA_FlipHWSurface(_THIS, SDL_Surface *surface); +static void AA_UnlockHWSurface(_THIS, SDL_Surface *surface); +static void AA_FreeHWSurface(_THIS, SDL_Surface *surface); + +/* Cache the VideoDevice struct */ +static struct SDL_VideoDevice *local_this; + +/* AAlib driver bootstrap functions */ + +static int AA_Available(void) +{ + return 1; /* Always available ! */ +} + +static void AA_DeleteDevice(SDL_VideoDevice *device) +{ + SDL_free(device->hidden); + SDL_free(device); +} + +static SDL_VideoDevice *AA_CreateDevice(int devindex) +{ + SDL_VideoDevice *device; + + /* Initialize all variables that we clean on shutdown */ + device = (SDL_VideoDevice *)SDL_malloc(sizeof(SDL_VideoDevice)); + if ( device ) { + SDL_memset(device, 0, (sizeof *device)); + device->hidden = (struct SDL_PrivateVideoData *) + SDL_malloc((sizeof *device->hidden)); + } + if ( (device == NULL) || (device->hidden == NULL) ) { + SDL_OutOfMemory(); + if ( device ) { + SDL_free(device); + } + return(0); + } + SDL_memset(device->hidden, 0, (sizeof *device->hidden)); + + /* Set the function pointers */ + device->VideoInit = AA_VideoInit; + device->ListModes = AA_ListModes; + device->SetVideoMode = AA_SetVideoMode; + device->CreateYUVOverlay = NULL; + device->SetColors = AA_SetColors; + device->UpdateRects = NULL; + device->VideoQuit = AA_VideoQuit; + device->AllocHWSurface = AA_AllocHWSurface; + device->CheckHWBlit = NULL; + device->FillHWRect = NULL; + device->SetHWColorKey = NULL; + device->SetHWAlpha = NULL; + device->LockHWSurface = AA_LockHWSurface; + device->UnlockHWSurface = AA_UnlockHWSurface; + device->FlipHWSurface = NULL; + device->FreeHWSurface = AA_FreeHWSurface; + device->SetCaption = NULL; + device->SetIcon = NULL; + device->IconifyWindow = NULL; + device->GrabInput = NULL; + device->GetWMInfo = NULL; + device->InitOSKeymap = AA_InitOSKeymap; + device->PumpEvents = AA_PumpEvents; + + device->free = AA_DeleteDevice; + + return device; +} + +VideoBootStrap AALIB_bootstrap = { + "aalib", "ASCII Art Library", + AA_Available, AA_CreateDevice +}; + +static void AA_ResizeHandler(aa_context *); + +int AA_VideoInit(_THIS, SDL_PixelFormat *vformat) +{ + int keyboard; + int i; + + /* Initialize all variables that we clean on shutdown */ + for ( i=0; i<SDL_NUMMODES; ++i ) { + SDL_modelist[i] = SDL_malloc(sizeof(SDL_Rect)); + SDL_modelist[i]->x = SDL_modelist[i]->y = 0; + } + /* Modes sorted largest to smallest */ + SDL_modelist[0]->w = 1024; SDL_modelist[0]->h = 768; + SDL_modelist[1]->w = 800; SDL_modelist[1]->h = 600; + SDL_modelist[2]->w = 640; SDL_modelist[2]->h = 480; + SDL_modelist[3]->w = 320; SDL_modelist[3]->h = 400; + SDL_modelist[4]->w = 320; SDL_modelist[4]->h = 240; + SDL_modelist[5]->w = 320; SDL_modelist[5]->h = 200; + SDL_modelist[6] = NULL; + + /* Initialize the library */ + + AA_mutex = SDL_CreateMutex(); + + aa_parseoptions (NULL, NULL, NULL, NULL); + + AA_context = aa_autoinit(&aa_defparams); + if ( ! AA_context ) { + SDL_SetError("Unable to initialize AAlib"); + return(-1); + } + + /* Enable mouse and keyboard support */ + + if ( ! aa_autoinitkbd (AA_context, AA_SENDRELEASE) ) { + SDL_SetError("Unable to initialize AAlib keyboard"); + return(-1); + } + if ( ! aa_autoinitmouse (AA_context, AA_SENDRELEASE) ) { + fprintf(stderr,"Warning: Unable to initialize AAlib mouse"); + } + AA_rparams = aa_getrenderparams(); + + local_this = this; + + aa_resizehandler(AA_context, AA_ResizeHandler); + + fprintf(stderr,"Using AAlib driver: %s (%s)\n", AA_context->driver->name, AA_context->driver->shortname); + + AA_in_x11 = (SDL_strcmp(AA_context->driver->shortname,"X11") == 0); + /* Determine the screen depth (use default 8-bit depth) */ + vformat->BitsPerPixel = 8; + vformat->BytesPerPixel = 1; + + /* We're done! */ + return(0); +} + +SDL_Rect **AA_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags) +{ + if(format->BitsPerPixel != 8) + return NULL; + + if ( flags & SDL_FULLSCREEN ) { + return SDL_modelist; + } else { + return (SDL_Rect **) -1; + } +} + +/* From aavga.c + AAlib does not give us the choice of the actual resolution, thus we have to simulate additional + resolution by scaling down manually each frame +*/ +static void fastscale (register char *b1, register char *b2, int x1, int x2, int y1, int y2) +{ + register int ex, spx = 0, ddx, ddx1; + int ddy1, ddy, spy = 0, ey; + int x; + char *bb1 = b1; + if (!x1 || !x2 || !y1 || !y2) + return; + ddx = x1 + x1; + ddx1 = x2 + x2; + if (ddx1 < ddx) + spx = ddx / ddx1, ddx %= ddx1; + ddy = y1 + y1; + ddy1 = y2 + y2; + if (ddy1 < ddy) + spy = (ddy / ddy1) * x1, ddy %= ddy1; + ey = -ddy1; + for (; y2; y2--) { + ex = -ddx1; + for (x = x2; x; x--) { + *b2 = *b1; + b2++; + b1 += spx; + ex += ddx; + if (ex > 0) { + b1++; + ex -= ddx1; + } + } + bb1 += spy; + ey += ddy; + if (ey > 0) { + bb1 += x1; + ey -= ddy1; + } + b1 = bb1; + } +} + +/* Various screen update functions available */ +static void AA_DirectUpdate(_THIS, int numrects, SDL_Rect *rects); + +SDL_Surface *AA_SetVideoMode(_THIS, SDL_Surface *current, + int width, int height, int bpp, Uint32 flags) +{ + int mode; + + if ( AA_buffer ) { + SDL_free( AA_buffer ); + } + + AA_buffer = SDL_malloc(width * height); + if ( ! AA_buffer ) { + SDL_SetError("Couldn't allocate buffer for requested mode"); + return(NULL); + } + +/* printf("Setting mode %dx%d\n", width, height); */ + + SDL_memset(aa_image(AA_context), 0, aa_imgwidth(AA_context) * aa_imgheight(AA_context)); + SDL_memset(AA_buffer, 0, width * height); + + /* Allocate the new pixel format for the screen */ + if ( ! SDL_ReallocFormat(current, 8, 0, 0, 0, 0) ) { + return(NULL); + } + + /* Set up the new mode framebuffer */ + current->flags = SDL_FULLSCREEN; + AA_w = current->w = width; + AA_h = current->h = height; + current->pitch = current->w; + current->pixels = AA_buffer; + + AA_x_ratio = ((double)aa_imgwidth(AA_context)) / ((double)width); + AA_y_ratio = ((double)aa_imgheight(AA_context)) / ((double)height); + + /* Set the blit function */ + this->UpdateRects = AA_DirectUpdate; + + /* We're done */ + return(current); +} + +static void AA_ResizeHandler(aa_context *context) +{ + aa_resize(context); + local_this->hidden->x_ratio = ((double)aa_imgwidth(context)) / ((double)local_this->screen->w); + local_this->hidden->y_ratio = ((double)aa_imgheight(context)) / ((double)local_this->screen->h); + + fastscale (local_this->hidden->buffer, aa_image(context), local_this->hidden->w, aa_imgwidth (context), local_this->hidden->h, aa_imgheight (context)); + aa_renderpalette(context, local_this->hidden->palette, local_this->hidden->rparams, 0, 0, aa_scrwidth(context), aa_scrheight(context)); + aa_flush(context); +} + +/* We don't actually allow hardware surfaces other than the main one */ +static int AA_AllocHWSurface(_THIS, SDL_Surface *surface) +{ + return(-1); +} +static void AA_FreeHWSurface(_THIS, SDL_Surface *surface) +{ + return; +} + +/* We need to wait for vertical retrace on page flipped displays */ +static int AA_LockHWSurface(_THIS, SDL_Surface *surface) +{ + /* TODO ? */ + return(0); +} +static void AA_UnlockHWSurface(_THIS, SDL_Surface *surface) +{ + return; +} + +/* FIXME: How is this done with AAlib? */ +static int AA_FlipHWSurface(_THIS, SDL_Surface *surface) +{ + SDL_mutexP(AA_mutex); + aa_flush(AA_context); + SDL_mutexV(AA_mutex); + return(0); +} + +static void AA_DirectUpdate(_THIS, int numrects, SDL_Rect *rects) +{ + int i; + SDL_Rect *rect; + + fastscale (AA_buffer, aa_image(AA_context), AA_w, aa_imgwidth (AA_context), AA_h, aa_imgheight (AA_context)); +#if 1 + aa_renderpalette(AA_context, AA_palette, AA_rparams, 0, 0, aa_scrwidth(AA_context), aa_scrheight(AA_context)); +#else + /* Render only the rectangles in the list */ + printf("Update rects : "); + for ( i=0; i < numrects; ++i ) { + rect = &rects[i]; + printf("(%d,%d-%d,%d)", rect->x, rect->y, rect->w, rect->h); + aa_renderpalette(AA_context, AA_palette, AA_rparams, rect->x * AA_x_ratio, rect->y * AA_y_ratio, rect->w * AA_x_ratio, rect->h * AA_y_ratio); + } + printf("\n"); +#endif + SDL_mutexP(AA_mutex); + aa_flush(AA_context); + SDL_mutexV(AA_mutex); + return; +} + +int AA_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors) +{ + int i; + + for ( i=0; i < ncolors; i++ ) { + aa_setpalette(AA_palette, firstcolor + i, + colors[i].r>>2, + colors[i].g>>2, + colors[i].b>>2); + } + return(1); +} + +/* Note: If we are terminated, this could be called in the middle of + another SDL video routine -- notably UpdateRects. +*/ +void AA_VideoQuit(_THIS) +{ + int i; + + aa_uninitkbd(AA_context); + aa_uninitmouse(AA_context); + + /* Free video mode lists */ + for ( i=0; i<SDL_NUMMODES; ++i ) { + if ( SDL_modelist[i] != NULL ) { + SDL_free(SDL_modelist[i]); + SDL_modelist[i] = NULL; + } + } + + aa_close(AA_context); + + SDL_DestroyMutex(AA_mutex); + + this->screen->pixels = NULL; +} diff --git a/3rdparty/SDL/src/video/aalib/SDL_aavideo.h b/3rdparty/SDL/src/video/aalib/SDL_aavideo.h new file mode 100644 index 0000000..987edc9 --- /dev/null +++ b/3rdparty/SDL/src/video/aalib/SDL_aavideo.h @@ -0,0 +1,66 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#ifndef _SDL_aavideo_h +#define _SDL_aavideo_h + +#include "SDL_mouse.h" +#include "SDL_mutex.h" +#include "../SDL_sysvideo.h" + +#include <aalib.h> + +/* Hidden "this" pointer for the video functions */ +#define _THIS SDL_VideoDevice *this + +#define SDL_NUMMODES 6 + +/* Private display data */ +struct SDL_PrivateVideoData { + SDL_Rect *SDL_modelist[SDL_NUMMODES+1]; + aa_context *context; + aa_palette palette; + aa_renderparams *rparams; + double x_ratio, y_ratio; + int w, h; + SDL_mutex *mutex; + int in_x11; + void *buffer; +}; + +/* Old variable names */ +#define SDL_modelist (this->hidden->SDL_modelist) +#define AA_context (this->hidden->context) +#define AA_palette (this->hidden->palette) +#define AA_rparams (this->hidden->rparams) +#define AA_buffer (this->hidden->buffer) + +#define AA_x_ratio (this->hidden->x_ratio) +#define AA_y_ratio (this->hidden->y_ratio) + +#define AA_mutex (this->hidden->mutex) +#define AA_in_x11 (this->hidden->in_x11) +#define AA_w (this->hidden->w) +#define AA_h (this->hidden->h) + +#endif /* _SDL_aavideo_h */ diff --git a/3rdparty/SDL/src/video/ataricommon/SDL_ataric2p.S b/3rdparty/SDL/src/video/ataricommon/SDL_ataric2p.S new file mode 100644 index 0000000..3cd1961 --- /dev/null +++ b/3rdparty/SDL/src/video/ataricommon/SDL_ataric2p.S @@ -0,0 +1,452 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ + +/* + Chunky to planar conversion routine + 1 byte/pixel -> 4 or 8 bit planes + + Patrice Mandin + Xavier Joubert + Mikael Kalms +*/ + + .globl _SDL_Atari_C2pConvert + .globl _SDL_Atari_C2pConvert8 + .globl _SDL_Atari_C2pConvert4 + .globl _SDL_Atari_C2pConvert4_pal + +/* ------------ Conversion C2P, 8 bits ------------ */ + + .text +_SDL_Atari_C2pConvert8: +#if !defined(__mcoldfire__) + movel sp@(4),c2p_source + movel sp@(8),c2p_dest + movel sp@(12),c2p_width + movel sp@(16),c2p_height + movel sp@(20),c2p_dblligne + movel sp@(24),c2p_srcpitch + movel sp@(28),c2p_dstpitch + + moveml d2-d7/a2-a6,sp@- + + movel c2p_source,c2p_cursrc + movel c2p_dest,c2p_curdst + movel #0x0f0f0f0f,d4 + movel #0x00ff00ff,d5 + movel #0x55555555,d6 + movew c2p_height+2,c2p_row + movew c2p_width+2,d0 + andw #-8,d0 + movew d0,c2p_rowlen + +SDL_Atari_C2p8_rowloop: + + movel c2p_cursrc,a0 + movel c2p_curdst,a1 + + movel a0,a2 + addw c2p_rowlen,a2 + + movel a0@+,d0 + movel a0@+,d1 + movel a0@+,d2 + movel a0@+,d3 +/* + d0 = a7a6a5a4a3a2a1a0 b7b6b5b4b3b2b1b0 c7c6c5c4c3c2c1c0 d7d6d5d4d3d2d1d0 + d1 = e7e6e5e4e3e2e1e0 f7f6f5f4f3f2f1f0 g7g6g5g4g3g2g1g0 h7h6h5h4h3h2h1h0 + d2 = i7i6i5i4i3i2i1i0 j7j6j5j4j3j2j1j0 k7k6k5k4k3k2k1k0 l7l6l5l4l3l2l1l0 + d3 = m7m6m5m4m3m2m1m0 n7n6n5n4n3n2n1n0 o7o6o5o4o3o2o1o0 p7p6p5p4p3p2p1p0 +*/ + movel d1,d7 + lsrl #4,d7 + eorl d0,d7 + andl d4,d7 + eorl d7,d0 + lsll #4,d7 + eorl d7,d1 + + movel d3,d7 + lsrl #4,d7 + eorl d2,d7 + andl d4,d7 + eorl d7,d2 + lsll #4,d7 + eorl d7,d3 + + movel d2,d7 + lsrl #8,d7 + eorl d0,d7 + andl d5,d7 + eorl d7,d0 + lsll #8,d7 + eorl d7,d2 + + movel d3,d7 + lsrl #8,d7 + eorl d1,d7 + andl d5,d7 + eorl d7,d1 + lsll #8,d7 + eorl d7,d3 +/* + d0 = a7a6a5a4e7e6e5e4 i7i6i5i4m7m6m5m4 c7c6c5c4g7g6g5g4 k7k6k5k4o7o6o5o4 + d1 = a3a2a1a0e3e2e1e0 i3i2i1i0m3m2m1m0 c3c2c1c0g3g2g1g0 k3k2k1k0o3o2o1o0 + d2 = b7b6b5b4f7f6f5f4 j7j6j5j4n7n6n5n4 d7d6d5d4h7h6h5h4 l7l6l5l4p7p6p5p4 + d3 = b3b2b1b0f3f2f1f0 j3j2j1j0n3n2n1n0 d3d2d1d0h3h2h1h0 l3l2l1l0p3p2p1p0 +*/ + bras SDL_Atari_C2p8_start + +SDL_Atari_C2p8_pix16: + + movel a0@+,d0 + movel a0@+,d1 + movel a0@+,d2 + movel a0@+,d3 +/* + d0 = a7a6a5a4a3a2a1a0 b7b6b5b4b3b2b1b0 c7c6c5c4c3c2c1c0 d7d6d5d4d3d2d1d0 + d1 = e7e6e5e4e3e2e1e0 f7f6f5f4f3f2f1f0 g7g6g5g4g3g2g1g0 h7h6h5h4h3h2h1h0 + d2 = i7i6i5i4i3i2i1i0 j7j6j5j4j3j2j1j0 k7k6k5k4k3k2k1k0 l7l6l5l4l3l2l1l0 + d3 = m7m6m5m4m3m2m1m0 n7n6n5n4n3n2n1n0 o7o6o5o4o3o2o1o0 p7p6p5p4p3p2p1p0 +*/ + movel d1,d7 + lsrl #4,d7 + movel a3,a1@+ + eorl d0,d7 + andl d4,d7 + eorl d7,d0 + lsll #4,d7 + eorl d7,d1 + + movel d3,d7 + lsrl #4,d7 + eorl d2,d7 + andl d4,d7 + eorl d7,d2 + movel a4,a1@+ + lsll #4,d7 + eorl d7,d3 + + movel d2,d7 + lsrl #8,d7 + eorl d0,d7 + andl d5,d7 + eorl d7,d0 + movel a5,a1@+ + lsll #8,d7 + eorl d7,d2 + + movel d3,d7 + lsrl #8,d7 + eorl d1,d7 + andl d5,d7 + eorl d7,d1 + movel a6,a1@+ + lsll #8,d7 + eorl d7,d3 +/* + d0 = a7a6a5a4e7e6e5e4 i7i6i5i4m7m6m5m4 c7c6c5c4g7g6g5g4 k7k6k5k4o7o6o5o4 + d1 = a3a2a1a0e3e2e1e0 i3i2i1i0m3m2m1m0 c3c2c1c0g3g2g1g0 k3k2k1k0o3o2o1o0 + d2 = b7b6b5b4f7f6f5f4 j7j6j5j4n7n6n5n4 d7d6d5d4h7h6h5h4 l7l6l5l4p7p6p5p4 + d3 = b3b2b1b0f3f2f1f0 j3j2j1j0n3n2n1n0 d3d2d1d0h3h2h1h0 l3l2l1l0p3p2p1p0 +*/ + +SDL_Atari_C2p8_start: + + movel d2,d7 + lsrl #1,d7 + eorl d0,d7 + andl d6,d7 + eorl d7,d0 + addl d7,d7 + eorl d7,d2 + + movel d3,d7 + lsrl #1,d7 + eorl d1,d7 + andl d6,d7 + eorl d7,d1 + addl d7,d7 + eorl d7,d3 +/* + d0 = a7b7a5b5e7f7e5f5 i7j7i5j5m7n7m5n5 c7d7c5d5g7h7g5h5 k7l7k5l5o7p7o5p5 + d1 = a3b3a1b1e3f3e1f1 i3j3i1j1m3n3m1n1 c3d3c1d1g3h3g1h1 k3l3k1l1o3p3o1p1 + d2 = a6b6a4b4e6f6e4f4 i6j6i4j4m6n6m4n4 c6d6c4d4g6h6g4h4 k6l6k4l4o6p6o4p4 + d3 = a2b2a0b0e2f2e0f0 i2j2i0j0m2n2m0n0 c2d2c0d0g2h2g0h0 k2l2k0l0o2p2o0p0 +*/ + movew d2,d7 + movew d0,d2 + swap d2 + movew d2,d0 + movew d7,d2 + + movew d3,d7 + movew d1,d3 + swap d3 + movew d3,d1 + movew d7,d3 +/* + d0 = a7b7a5b5e7f7e5f5 i7j7i5j5m7n7m5n5 a6b6a4b4e6f6e4f4 i6j6i4j4m6n6m4n4 + d1 = a3b3a1b1e3f3e1f1 i3j3i1j1m3n3m1n1 a2b2a0b0e2f2e0f0 i2j2i0j0m2n2m0n0 + d2 = c7d7c5d5g7h7g5h5 k7l7k5l5o7p7o5p5 c6d6c4d4g6h6g4h4 k6l6k4l4o6p6o4p4 + d3 = c3d3c1d1g3h3g1h1 k3l3k1l1o3p3o1p1 c2d2c0d0g2h2g0h0 k2l2k0l0o2p2o0p0 +*/ + movel d2,d7 + lsrl #2,d7 + eorl d0,d7 + andl #0x33333333,d7 + eorl d7,d0 + lsll #2,d7 + eorl d7,d2 + + movel d3,d7 + lsrl #2,d7 + eorl d1,d7 + andl #0x33333333,d7 + eorl d7,d1 + lsll #2,d7 + eorl d7,d3 +/* + d0 = a7b7c7d7e7f7g7h7 i7j7k7l7m7n7o7p7 a6b6c6d6e6f6g6h6 i6j6k6l6m6n6o6p6 + d1 = a3b3c3d3e3f3g3h3 i3j3k3l3m3n3o3p3 a2b2c2d2e2f2g2h2 i2j2k2l2m2n2o2p2 + d2 = a5b5c5d5e5f5g5h5 i5j5k5l5m5n5o5p5 a4b4c4d4e4f4g4h4 i4j4k4l4m4n4o4p4 + d3 = a1b1c1d1e1f1g1h1 i1j1k1l1m1n1o1p1 a0b0c0d0e0f0g0h0 i0j0k0l0m0n0o0p0 +*/ + swap d0 + swap d1 + swap d2 + swap d3 + + movel d0,a6 + movel d2,a5 + movel d1,a4 + movel d3,a3 + + cmpl a0,a2 + bgt SDL_Atari_C2p8_pix16 + + movel a3,a1@+ + movel a4,a1@+ + movel a5,a1@+ + movel a6,a1@+ + + /* Double the line ? */ + + movel c2p_srcpitch,d0 + movel c2p_dstpitch,d1 + + tstl c2p_dblligne + beqs SDL_Atari_C2p8_nodblline + + movel c2p_curdst,a0 + movel a0,a1 + addl d1,a1 + + movew c2p_width+2,d7 + lsrw #4,d7 + subql #1,d7 +SDL_Atari_C2p8_dblloop: + movel a0@+,a1@+ + movel a0@+,a1@+ + movel a0@+,a1@+ + movel a0@+,a1@+ + dbra d7,SDL_Atari_C2p8_dblloop + + addl d1,c2p_curdst + +SDL_Atari_C2p8_nodblline: + + /* Next line */ + + addl d0,c2p_cursrc + addl d1,c2p_curdst + + subqw #1,c2p_row + bne SDL_Atari_C2p8_rowloop + + moveml sp@+,d2-d7/a2-a6 +#endif + rts + +/* ------------ Conversion C2P, 4 bits ------------ */ + +_SDL_Atari_C2pConvert4: +#if !defined(__mcoldfire__) + movel sp@(4),c2p_source + movel sp@(8),c2p_dest + movel sp@(12),c2p_width + movel sp@(16),c2p_height + movel sp@(20),c2p_dblligne + movel sp@(24),c2p_srcpitch + movel sp@(28),c2p_dstpitch + + moveml d2-d7/a2-a6,sp@- + + movel c2p_source,a0 + movel c2p_dest,a1 + lea _SDL_Atari_table_c2p,a2 + movel #0x00070001,d3 +#if defined(__mc68020__) + moveq #0,d0 +#endif + + movel c2p_height,d7 + subql #1,d7 +c2p4_bcly: + movel a0,a4 | Save start address of source + movel a1,a5 | Save start address of dest + + | Conversion + + movel c2p_width,d6 + lsrw #4,d6 + subql #1,d6 +c2p4_bclx: + | Octets 0-7 + + moveq #0,d1 + moveq #7,d5 +c2p4_bcl07: +#if defined(__mc68020__) + moveb a0@+,d0 + lea a2@(0,d0:w:4),a3 +#else + moveq #0,d0 + moveb a0@+,d0 + lslw #2,d0 + lea a2@(0,d0:w),a3 +#endif + lsll #1,d1 + orl a3@,d1 + dbra d5,c2p4_bcl07 + + movepl d1,a1@(0) + addw d3,a1 + swap d3 + + | Octets 8-15 + + moveq #0,d1 + moveq #7,d5 +c2p4_bcl815: +#if defined(__mc68020__) + moveb a0@+,d0 + lea a2@(0,d0:w:4),a3 +#else + moveq #0,d0 + moveb a0@+,d0 + lslw #2,d0 + lea a2@(0,d0:w),a3 +#endif + lsll #1,d1 + orl a3@,d1 + dbra d5,c2p4_bcl815 + + movepl d1,a1@(0) + addw d3,a1 + swap d3 + + dbra d6,c2p4_bclx + + | Double line ? + + tstl c2p_dblligne + beqs c2p4_nodblligne + + movel a5,a6 | src line + movel a5,a1 | dest line + addl c2p_dstpitch,a1 + + movel c2p_width,d6 + lsrw #3,d6 + subql #1,d6 +c2p4_copydbl: + movel a6@+,a1@+ + dbra d6,c2p4_copydbl + + addl c2p_dstpitch,a5 +c2p4_nodblligne: + + | Next line + + movel a4,a0 + addl c2p_srcpitch,a0 + movel a5,a1 + addl c2p_dstpitch,a1 + + dbra d7,c2p4_bcly + + moveml sp@+,d2-d7/a2-a6 +#endif + rts + +/* ------------ Conversion of a light palette in 4 bits ------------ */ + +_SDL_Atari_C2pConvert4_pal: +#if !defined(__mcoldfire__) + /* a0 is a 256-word light palette */ + movel sp@(4),a0 + + moveml d2-d3,sp@- + + lea _SDL_Atari_table_c2p,a1 + movew #255,d3 +c2p_pal_initbcl: + movew a0@+,d0 + lsrw #4,d0 + andw #15,d0 + + moveq #3,d1 +c2p_pal_initbyte: + btst d1,d0 + sne d2 + negw d2 + moveb d2,a1@(0,d1:w) + + dbra d1,c2p_pal_initbyte + + addql #4,a1 + dbra d3,c2p_pal_initbcl + + moveml sp@+,d2-d3 +#endif + rts + +/* ------------ Buffers ------------ */ + + .bss + + .even + .comm _SDL_Atari_C2pConvert,4 + .comm _SDL_Atari_table_c2p,1024 + + .comm c2p_source,4 /* Source framebuffer */ + .comm c2p_dest,4 /* Destination framebuffer */ + .comm c2p_width,4 /* Width of zone to convert */ + .comm c2p_height,4 /* Height of zone to convert */ + .comm c2p_dblligne,4 /* Double the lines while converting ? */ + .comm c2p_srcpitch,4 /* Source pitch */ + .comm c2p_dstpitch,4 /* Destination pitch */ + .comm c2p_cursrc,4 /* Current source line */ + .comm c2p_curdst,4 /* Current destination line */ + .comm c2p_rowlen,2 /* Line length in bytes */ + .comm c2p_row,2 /* Current line number */ diff --git a/3rdparty/SDL/src/video/ataricommon/SDL_ataric2p_s.h b/3rdparty/SDL/src/video/ataricommon/SDL_ataric2p_s.h new file mode 100644 index 0000000..48bdae7 --- /dev/null +++ b/3rdparty/SDL/src/video/ataricommon/SDL_ataric2p_s.h @@ -0,0 +1,75 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#ifndef _ATARI_C2P_h +#define _ATARI_C2P_h + +#include "SDL_stdinc.h" + +/*--- Functions pointers ---*/ + +/* Convert a chunky screen to bitplane screen */ + +extern void (*SDL_Atari_C2pConvert)( + Uint8 *src, /* Source screen (one byte=one pixel) */ + Uint8 *dest, /* Destination (4/8 bits planes) */ + Uint32 width, /* Dimensions of screen to convert */ + Uint32 height, + Uint32 dblligne, /* Double the lines when converting ? */ + Uint32 srcpitch, /* Length of one source line in bytes */ + Uint32 dstpitch /* Length of one destination line in bytes */ +); + +/*--- 8 bits functions ---*/ + +/* Convert a chunky screen to bitplane screen */ + +void SDL_Atari_C2pConvert8( + Uint8 *src, /* Source screen (one byte=one pixel) */ + Uint8 *dest, /* Destination (8 bits planes) */ + Uint32 width, /* Dimensions of screen to convert */ + Uint32 height, + Uint32 dblligne, /* Double the lines when converting ? */ + Uint32 srcpitch, /* Length of one source line in bytes */ + Uint32 dstpitch /* Length of one destination line in bytes */ +); + +/*--- 4 bits functions ---*/ + +/* Convert a chunky screen to bitplane screen */ + +void SDL_Atari_C2pConvert4( + Uint8 *src, /* Source screen (one byte=one pixel) */ + Uint8 *dest, /* Destination (4 bits planes) */ + Uint32 width, /* Dimensions of screen to convert */ + Uint32 height, + Uint32 dblligne, /* Double the lines when converting ? */ + Uint32 srcpitch, /* Length of one source line in bytes */ + Uint32 dstpitch /* Length of one destination line in bytes */ +); + +/* Conversion palette */ + +void SDL_Atari_C2pConvert4_pal(Uint16 *lightpalette); + +#endif /* _ATARI_C2P_h */ diff --git a/3rdparty/SDL/src/video/ataricommon/SDL_ataridevmouse.c b/3rdparty/SDL/src/video/ataricommon/SDL_ataridevmouse.c new file mode 100644 index 0000000..0527380 --- /dev/null +++ b/3rdparty/SDL/src/video/ataricommon/SDL_ataridevmouse.c @@ -0,0 +1,159 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* + MiNT /dev/mouse driver + + Patrice Mandin +*/ + +#include <fcntl.h> +#include <unistd.h> + +#include "../../events/SDL_events_c.h" +#include "SDL_ataridevmouse_c.h" + +/* Defines */ + +#define DEVICE_NAME "/dev/mouse" + +/* Local variables */ + +static int handle = -1; +static int mouseb, prev_mouseb; + +/* Functions */ + +int SDL_AtariDevMouse_Open(void) +{ + int r; + const char *mousedev; + + /* + TODO: Fix the MiNT device driver, that locks mouse for other + applications, so this is disabled till fixed + */ + return 0; + + /* First, try SDL_MOUSEDEV device */ + mousedev = SDL_getenv("SDL_MOUSEDEV"); + if (!mousedev) { + handle = open(mousedev, 0); + } + + /* Failed, try default device */ + if (handle<0) { + handle = open(DEVICE_NAME, 0); + } + + if (handle<0) { + handle = -1; + return 0; + } + + /* Set non blocking mode */ + r = fcntl(handle, F_GETFL, 0); + if (r<0) { + close(handle); + handle = -1; + return 0; + } + + r |= O_NDELAY; + + r = fcntl(handle, F_SETFL, r); + if (r<0) { + close(handle); + handle = -1; + return 0; + } + + prev_mouseb = 7; + return 1; +} + +void SDL_AtariDevMouse_Close(void) +{ + if (handle>0) { + close(handle); + handle = -1; + } +} + +static int atari_GetButton(int button) +{ + switch(button) + { + case 0: + return SDL_BUTTON_RIGHT; + case 1: + return SDL_BUTTON_MIDDLE; + default: + break; + } + + return SDL_BUTTON_LEFT; +} + +void SDL_AtariDevMouse_PostMouseEvents(_THIS, SDL_bool buttonEvents) +{ + unsigned char buffer[3]; + int mousex, mousey; + + if (handle<0) { + return; + } + + mousex = mousey = 0; + while (read(handle, buffer, sizeof(buffer))==sizeof(buffer)) { + mouseb = buffer[0] & 7; + mousex += (char) buffer[1]; + mousey += (char) buffer[2]; + + /* Mouse button events */ + if (buttonEvents && (mouseb != prev_mouseb)) { + int i; + + for (i=0;i<3;i++) { + int curbutton, prevbutton; + + curbutton = mouseb & (1<<i); + prevbutton = prev_mouseb & (1<<i); + + if (curbutton && !prevbutton) { + SDL_PrivateMouseButton(SDL_RELEASED, atari_GetButton(i), 0, 0); + } + if (!curbutton && prevbutton) { + SDL_PrivateMouseButton(SDL_PRESSED, atari_GetButton(i), 0, 0); + } + } + + prev_mouseb = mouseb; + } + } + + /* Mouse motion event */ + if (mousex || mousey) { + SDL_PrivateMouseMotion(0, 1, mousex, -mousey); + } +} diff --git a/3rdparty/SDL/src/video/ataricommon/SDL_ataridevmouse_c.h b/3rdparty/SDL/src/video/ataricommon/SDL_ataridevmouse_c.h new file mode 100644 index 0000000..7cae022 --- /dev/null +++ b/3rdparty/SDL/src/video/ataricommon/SDL_ataridevmouse_c.h @@ -0,0 +1,42 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* + MiNT /dev/mouse driver + + Patrice Mandin +*/ + +#ifndef _SDL_ATARI_DEVMOUSE_H_ +#define _SDL_ATARI_DEVMOUSE_H_ + +#include "../SDL_sysvideo.h" + +/* Hidden "this" pointer for the video functions */ +#define _THIS SDL_VideoDevice *this + +extern int SDL_AtariDevMouse_Open(void); +extern void SDL_AtariDevMouse_Close(void); +extern void SDL_AtariDevMouse_PostMouseEvents(_THIS, SDL_bool buttonEvents); + +#endif /* _SDL_ATARI_DEVMOUSE_H_ */ diff --git a/3rdparty/SDL/src/video/ataricommon/SDL_atarieddi.S b/3rdparty/SDL/src/video/ataricommon/SDL_atarieddi.S new file mode 100644 index 0000000..d8cbf48 --- /dev/null +++ b/3rdparty/SDL/src/video/ataricommon/SDL_atarieddi.S @@ -0,0 +1,42 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ + +/* + * Read EdDI version + * + * Patrice Mandin + */ + + .text + + .globl _Atari_get_EdDI_version + +/*--- Vector installer ---*/ + +_Atari_get_EdDI_version: + movel sp@(4),a0 /* Value of EdDI cookie */ + + /* Call EdDI function #0 */ + clrw d0 + jsr (a0) + + rts diff --git a/3rdparty/SDL/src/video/ataricommon/SDL_atarieddi_s.h b/3rdparty/SDL/src/video/ataricommon/SDL_atarieddi_s.h new file mode 100644 index 0000000..cd3e524 --- /dev/null +++ b/3rdparty/SDL/src/video/ataricommon/SDL_atarieddi_s.h @@ -0,0 +1,54 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#ifndef _SDL_Atari_eddi_s_h +#define _SDL_Atari_eddi_s_h + +/*--- Defines ---*/ + +/* EdDI versions */ + +#define EDDI_10 (0x0100) +#define EDDI_11 (0x0110) + +/* Screen format */ + +enum { + VDI_FORMAT_UNKNOWN=-1, + VDI_FORMAT_INTER=0, /* Interleaved bitplanes */ + VDI_FORMAT_VDI=1, /* VDI independent */ + VDI_FORMAT_PACK=2 /* Packed pixels */ +}; + +/* CLUT types */ +enum { + VDI_CLUT_NONE=0, /* Monochrome mode */ + VDI_CLUT_HARDWARE, /* <256 colours mode */ + VDI_CLUT_SOFTWARE /* True colour mode */ +}; + +/*--- Functions ---*/ + +unsigned long Atari_get_EdDI_version(void *function_pointer); + +#endif /* _SDL_Atari_eddi_s_h */ diff --git a/3rdparty/SDL/src/video/ataricommon/SDL_atarievents.c b/3rdparty/SDL/src/video/ataricommon/SDL_atarievents.c new file mode 100644 index 0000000..8831275 --- /dev/null +++ b/3rdparty/SDL/src/video/ataricommon/SDL_atarievents.c @@ -0,0 +1,234 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* + * Atari keyboard events manager + * + * Patrice Mandin + * + * This routines choose what the final event manager will be + */ + +#include <mint/cookie.h> +#include <mint/osbind.h> + +#include "../../events/SDL_sysevents.h" +#include "../../events/SDL_events_c.h" + +#include "SDL_atarikeys.h" +#include "SDL_atarievents_c.h" +#include "SDL_biosevents_c.h" +#include "SDL_gemdosevents_c.h" +#include "SDL_ikbdevents_c.h" + +enum { + MCH_ST=0, + MCH_STE, + MCH_TT, + MCH_F30, + MCH_CLONE, + MCH_ARANYM +}; + +/* The translation tables from a console scancode to a SDL keysym */ +static SDLKey keymap[ATARIBIOS_MAXKEYS]; +static char *keytab_normal; + +void (*Atari_ShutdownEvents)(void); + +static void Atari_InitializeEvents(_THIS) +{ + const char *envr; + long cookie_mch; + + /* Test if we are on an Atari machine or not */ + if (Getcookie(C__MCH, &cookie_mch) == C_NOTFOUND) { + cookie_mch = 0; + } + cookie_mch >>= 16; + + /* Default is Ikbd, the faster except for clones */ + switch(cookie_mch) { + case MCH_ST: + case MCH_STE: + case MCH_TT: + case MCH_F30: + case MCH_ARANYM: + this->InitOSKeymap=AtariIkbd_InitOSKeymap; + this->PumpEvents=AtariIkbd_PumpEvents; + Atari_ShutdownEvents=AtariIkbd_ShutdownEvents; + break; + default: + this->InitOSKeymap=AtariGemdos_InitOSKeymap; + this->PumpEvents=AtariGemdos_PumpEvents; + Atari_ShutdownEvents=AtariGemdos_ShutdownEvents; + break; + } + + envr = SDL_getenv("SDL_ATARI_EVENTSDRIVER"); + + if (!envr) { + return; + } + + if (SDL_strcmp(envr, "ikbd") == 0) { + this->InitOSKeymap=AtariIkbd_InitOSKeymap; + this->PumpEvents=AtariIkbd_PumpEvents; + Atari_ShutdownEvents=AtariIkbd_ShutdownEvents; + } + + if (SDL_strcmp(envr, "gemdos") == 0) { + this->InitOSKeymap=AtariGemdos_InitOSKeymap; + this->PumpEvents=AtariGemdos_PumpEvents; + Atari_ShutdownEvents=AtariGemdos_ShutdownEvents; + } + + if (SDL_strcmp(envr, "bios") == 0) { + this->InitOSKeymap=AtariBios_InitOSKeymap; + this->PumpEvents=AtariBios_PumpEvents; + Atari_ShutdownEvents=AtariBios_ShutdownEvents; + } +} + +void Atari_InitOSKeymap(_THIS) +{ + Atari_InitializeEvents(this); + + SDL_Atari_InitInternalKeymap(this); + + /* Call choosen routine */ + this->InitOSKeymap(this); +} + +void SDL_Atari_InitInternalKeymap(_THIS) +{ + int i; + _KEYTAB *key_tables; + + /* Read system tables for scancode -> ascii translation */ + key_tables = (_KEYTAB *) Keytbl(KT_NOCHANGE, KT_NOCHANGE, KT_NOCHANGE); + keytab_normal = key_tables->unshift; + + /* Initialize keymap */ + for ( i=0; i<ATARIBIOS_MAXKEYS; i++ ) + keymap[i] = SDLK_UNKNOWN; + + /* Functions keys */ + for ( i = 0; i<10; i++ ) + keymap[SCANCODE_F1 + i] = SDLK_F1+i; + + /* Cursor keypad */ + keymap[SCANCODE_HELP] = SDLK_HELP; + keymap[SCANCODE_UNDO] = SDLK_UNDO; + keymap[SCANCODE_INSERT] = SDLK_INSERT; + keymap[SCANCODE_CLRHOME] = SDLK_HOME; + keymap[SCANCODE_UP] = SDLK_UP; + keymap[SCANCODE_DOWN] = SDLK_DOWN; + keymap[SCANCODE_RIGHT] = SDLK_RIGHT; + keymap[SCANCODE_LEFT] = SDLK_LEFT; + + /* Special keys */ + keymap[SCANCODE_ESCAPE] = SDLK_ESCAPE; + keymap[SCANCODE_BACKSPACE] = SDLK_BACKSPACE; + keymap[SCANCODE_TAB] = SDLK_TAB; + keymap[SCANCODE_ENTER] = SDLK_RETURN; + keymap[SCANCODE_DELETE] = SDLK_DELETE; + keymap[SCANCODE_LEFTCONTROL] = SDLK_LCTRL; + keymap[SCANCODE_LEFTSHIFT] = SDLK_LSHIFT; + keymap[SCANCODE_RIGHTSHIFT] = SDLK_RSHIFT; + keymap[SCANCODE_LEFTALT] = SDLK_LALT; + keymap[SCANCODE_CAPSLOCK] = SDLK_CAPSLOCK; +} + +void Atari_PumpEvents(_THIS) +{ + Atari_InitializeEvents(this); + + /* Call choosen routine */ + this->PumpEvents(this); +} + +/* Atari to Unicode charset translation table */ + +Uint16 SDL_AtariToUnicodeTable[256]={ + /* Standard ASCII characters from 0x00 to 0x7e */ + /* Unicode stuff from 0x7f to 0xff */ + + 0x0000,0x0001,0x0002,0x0003,0x0004,0x0005,0x0006,0x0007, + 0x0008,0x0009,0x000A,0x000B,0x000C,0x000D,0x000E,0x000F, + 0x0010,0x0011,0x0012,0x0013,0x0014,0x0015,0x0016,0x0017, + 0x0018,0x0019,0x001A,0x001B,0x001C,0x001D,0x001E,0x001F, + 0x0020,0x0021,0x0022,0x0023,0x0024,0x0025,0x0026,0x0027, + 0x0028,0x0029,0x002A,0x002B,0x002C,0x002D,0x002E,0x002F, + 0x0030,0x0031,0x0032,0x0033,0x0034,0x0035,0x0036,0x0037, + 0x0038,0x0039,0x003A,0x003B,0x003C,0x003D,0x003E,0x003F, + + 0x0040,0x0041,0x0042,0x0043,0x0044,0x0045,0x0046,0x0047, + 0x0048,0x0049,0x004A,0x004B,0x004C,0x004D,0x004E,0x004F, + 0x0050,0x0051,0x0052,0x0053,0x0054,0x0055,0x0056,0x0057, + 0x0058,0x0059,0x005A,0x005B,0x005C,0x005D,0x005E,0x005F, + 0x0060,0x0061,0x0062,0x0063,0x0064,0x0065,0x0066,0x0067, + 0x0068,0x0069,0x006A,0x006B,0x006C,0x006D,0x006E,0x006F, + 0x0070,0x0071,0x0072,0x0073,0x0074,0x0075,0x0076,0x0077, + 0x0078,0x0079,0x007A,0x007B,0x007C,0x007D,0x007E,0x0394, + + 0x00C7,0x00FC,0x00E9,0x00E2,0x00E4,0x00E0,0x00E5,0x00E7, + 0x00EA,0x00EB,0x00E8,0x00EF,0x00EE,0x00EC,0x00C4,0x00C5, + 0x00C9,0x00E6,0x00C6,0x00F4,0x00F6,0x00F2,0x00FB,0x00F9, + 0x00FF,0x00D6,0x00DC,0x00A2,0x00A3,0x00A5,0x00DF,0x0192, + 0x00E1,0x00ED,0x00F3,0x00FA,0x00F1,0x00D1,0x00AA,0x00BA, + 0x00BF,0x2310,0x00AC,0x00BD,0x00BC,0x00A1,0x00AB,0x00BB, + 0x00C3,0x00F5,0x00D8,0x00F8,0x0153,0x0152,0x00C0,0x00C3, + 0x00D5,0x00A8,0x00B4,0x2020,0x00B6,0x00A9,0x00AE,0x2122, + + 0x0133,0x0132,0x05D0,0x05D1,0x05D2,0x05D3,0x05D4,0x05D5, + 0x05D6,0x05D7,0x05D8,0x05D9,0x05DB,0x05DC,0x05DE,0x05E0, + 0x05E1,0x05E2,0x05E4,0x05E6,0x05E7,0x05E8,0x05E9,0x05EA, + 0x05DF,0x05DA,0x05DD,0x05E3,0x05E5,0x00A7,0x2038,0x221E, + 0x03B1,0x03B2,0x0393,0x03C0,0x03A3,0x03C3,0x00B5,0x03C4, + 0x03A6,0x0398,0x03A9,0x03B4,0x222E,0x03C6,0x2208,0x2229, + 0x2261,0x00B1,0x2265,0x2264,0x2320,0x2321,0x00F7,0x2248, + 0x00B0,0x2022,0x00B7,0x221A,0x207F,0x00B2,0x00B3,0x00AF +}; + +SDL_keysym *SDL_Atari_TranslateKey(int scancode, SDL_keysym *keysym, + SDL_bool pressed) +{ + int asciicode = 0; + + /* Set the keysym information */ + keysym->scancode = scancode; + keysym->mod = KMOD_NONE; + keysym->sym = keymap[scancode]; + keysym->unicode = 0; + + if (keysym->sym == SDLK_UNKNOWN) { + keysym->sym = asciicode = keytab_normal[scancode]; + } + + if (SDL_TranslateUNICODE && pressed) { + keysym->unicode = SDL_AtariToUnicodeTable[asciicode]; + } + + return(keysym); +} diff --git a/3rdparty/SDL/src/video/ataricommon/SDL_atarievents_c.h b/3rdparty/SDL/src/video/ataricommon/SDL_atarievents_c.h new file mode 100644 index 0000000..a7dd882 --- /dev/null +++ b/3rdparty/SDL/src/video/ataricommon/SDL_atarievents_c.h @@ -0,0 +1,52 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* + * Atari keyboard events manager + * + * Patrice Mandin + */ + +#ifndef _SDL_ATARI_EVENTS_H_ +#define _SDL_ATARI_EVENTS_H_ + +#include "../SDL_sysvideo.h" + +/* Hidden "this" pointer for the video functions */ +#define _THIS SDL_VideoDevice *this + +#define ATARIBIOS_MAXKEYS 128 + +extern void (*Atari_ShutdownEvents)(void); + +extern void Atari_InitOSKeymap(_THIS); +extern void Atari_PumpEvents(_THIS); + +extern void SDL_Atari_InitInternalKeymap(_THIS); + +/* Atari to Unicode charset translation table */ +extern Uint16 SDL_AtariToUnicodeTable[256]; +SDL_keysym *SDL_Atari_TranslateKey(int scancode, SDL_keysym *keysym, + SDL_bool pressed); + +#endif /* _SDL_ATARI_EVENTS_H_ */ diff --git a/3rdparty/SDL/src/video/ataricommon/SDL_atarigl.c b/3rdparty/SDL/src/video/ataricommon/SDL_atarigl.c new file mode 100644 index 0000000..1cf2689 --- /dev/null +++ b/3rdparty/SDL/src/video/ataricommon/SDL_atarigl.c @@ -0,0 +1,1086 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* Atari OSMesa.ldg implementation of SDL OpenGL support */ + +/*--- Includes ---*/ + +#if SDL_VIDEO_OPENGL +#include <GL/osmesa.h> +#endif + +#include <mint/osbind.h> + +#include "SDL_endian.h" +#include "SDL_video.h" +#include "SDL_atarigl_c.h" +#if SDL_VIDEO_OPENGL_OSMESA_DYNAMIC +#include "SDL_loadso.h" +#endif + +/*--- Defines ---*/ + +#define PATH_OSMESA_LDG "osmesa.ldg" +#define PATH_MESAGL_LDG "mesa_gl.ldg" +#define PATH_TINYGL_LDG "tiny_gl.ldg" + +#define VDI_RGB 0xf + +/*--- Functions prototypes ---*/ + +#if SDL_VIDEO_OPENGL +static void SDL_AtariGL_UnloadLibrary(_THIS); + +static void CopyShadowNull(_THIS, SDL_Surface *surface); +static void CopyShadowDirect(_THIS, SDL_Surface *surface); +static void CopyShadowRGBTo555(_THIS, SDL_Surface *surface); +static void CopyShadowRGBTo565(_THIS, SDL_Surface *surface); +static void CopyShadowRGBSwap(_THIS, SDL_Surface *surface); +static void CopyShadowRGBToARGB(_THIS, SDL_Surface *surface); +static void CopyShadowRGBToABGR(_THIS, SDL_Surface *surface); +static void CopyShadowRGBToBGRA(_THIS, SDL_Surface *surface); +static void CopyShadowRGBToRGBA(_THIS, SDL_Surface *surface); +static void CopyShadow8888To555(_THIS, SDL_Surface *surface); +static void CopyShadow8888To565(_THIS, SDL_Surface *surface); + +static void ConvertNull(_THIS, SDL_Surface *surface); +static void Convert565To555be(_THIS, SDL_Surface *surface); +static void Convert565To555le(_THIS, SDL_Surface *surface); +static void Convert565le(_THIS, SDL_Surface *surface); +static void ConvertBGRAToABGR(_THIS, SDL_Surface *surface); + +static int InitNew(_THIS, SDL_Surface *current); +static int InitOld(_THIS, SDL_Surface *current); +#endif + +/*--- Public functions ---*/ + +int SDL_AtariGL_Init(_THIS, SDL_Surface *current) +{ +#if SDL_VIDEO_OPENGL + if (gl_oldmesa) { + gl_active = InitOld(this, current); + } else { + gl_active = InitNew(this, current); + } +#endif + + return (gl_active); +} + +void SDL_AtariGL_Quit(_THIS, SDL_bool unload) +{ +#if SDL_VIDEO_OPENGL + if (gl_oldmesa) { + /* Old mesa implementations */ + if (this->gl_data->OSMesaDestroyLDG) { + this->gl_data->OSMesaDestroyLDG(); + } + if (gl_shadow) { + Mfree(gl_shadow); + gl_shadow = NULL; + } + } else { + /* New mesa implementation */ + if (gl_ctx) { + if (this->gl_data->OSMesaDestroyContext) { + this->gl_data->OSMesaDestroyContext(gl_ctx); + } + gl_ctx = NULL; + } + } + + if (unload) { + SDL_AtariGL_UnloadLibrary(this); + } + +#endif /* SDL_VIDEO_OPENGL */ + gl_active = 0; +} + +int SDL_AtariGL_LoadLibrary(_THIS, const char *path) +{ +#if SDL_VIDEO_OPENGL + +#if SDL_VIDEO_OPENGL_OSMESA_DYNAMIC + void *handle; + SDL_bool cancel_load; + + if (gl_active) { + SDL_SetError("OpenGL context already created"); + return -1; + } + + /* Unload previous driver */ + SDL_AtariGL_UnloadLibrary(this); + + /* Load library given by path */ + handle = SDL_LoadObject(path); + if (handle == NULL) { + /* Try to load another one */ + path = SDL_getenv("SDL_VIDEO_GL_DRIVER"); + if ( path != NULL ) { + handle = SDL_LoadObject(path); + } + + /* If it does not work, try some other */ + if (handle == NULL) { + path = PATH_OSMESA_LDG; + handle = SDL_LoadObject(path); + } + + if (handle == NULL) { + path = PATH_MESAGL_LDG; + handle = SDL_LoadObject(path); + } + + if (handle == NULL) { + path = PATH_TINYGL_LDG; + handle = SDL_LoadObject(path); + } + } + + if (handle == NULL) { + SDL_SetError("Could not load OpenGL library"); + return -1; + } + + this->gl_data->glGetIntegerv = SDL_LoadFunction(handle, "glGetIntegerv"); + this->gl_data->glFinish = SDL_LoadFunction(handle, "glFinish"); + this->gl_data->glFlush = SDL_LoadFunction(handle, "glFlush"); + + cancel_load = SDL_FALSE; + if (this->gl_data->glGetIntegerv == NULL) { + cancel_load = SDL_TRUE; + } else { + /* We need either glFinish (OSMesa) or glFlush (TinyGL) */ + if ((this->gl_data->glFinish == NULL) && + (this->gl_data->glFlush == NULL)) { + cancel_load = SDL_TRUE; + } + } + if (cancel_load) { + SDL_SetError("Could not retrieve OpenGL functions"); + SDL_UnloadObject(handle); + /* Restore pointers to static library */ + SDL_AtariGL_InitPointers(this); + return -1; + } + + /* Load functions pointers (osmesa.ldg) */ + this->gl_data->OSMesaCreateContextExt = SDL_LoadFunction(handle, "OSMesaCreateContextExt"); + this->gl_data->OSMesaDestroyContext = SDL_LoadFunction(handle, "OSMesaDestroyContext"); + this->gl_data->OSMesaMakeCurrent = SDL_LoadFunction(handle, "OSMesaMakeCurrent"); + this->gl_data->OSMesaPixelStore = SDL_LoadFunction(handle, "OSMesaPixelStore"); + this->gl_data->OSMesaGetProcAddress = SDL_LoadFunction(handle, "OSMesaGetProcAddress"); + + /* Load old functions pointers (mesa_gl.ldg, tiny_gl.ldg) */ + this->gl_data->OSMesaCreateLDG = SDL_LoadFunction(handle, "OSMesaCreateLDG"); + this->gl_data->OSMesaDestroyLDG = SDL_LoadFunction(handle, "OSMesaDestroyLDG"); + + gl_oldmesa = 0; + + if ( (this->gl_data->OSMesaCreateContextExt == NULL) || + (this->gl_data->OSMesaDestroyContext == NULL) || + (this->gl_data->OSMesaMakeCurrent == NULL) || + (this->gl_data->OSMesaPixelStore == NULL) || + (this->gl_data->OSMesaGetProcAddress == NULL)) { + /* Hum, maybe old library ? */ + if ( (this->gl_data->OSMesaCreateLDG == NULL) || + (this->gl_data->OSMesaDestroyLDG == NULL)) { + SDL_SetError("Could not retrieve OSMesa functions"); + SDL_UnloadObject(handle); + /* Restore pointers to static library */ + SDL_AtariGL_InitPointers(this); + return -1; + } else { + gl_oldmesa = 1; + } + } + + this->gl_config.dll_handle = handle; + if ( path ) { + SDL_strlcpy(this->gl_config.driver_path, path, + SDL_arraysize(this->gl_config.driver_path)); + } else { + *this->gl_config.driver_path = '\0'; + } + +#endif + this->gl_config.driver_loaded = 1; + + return 0; +#else + return -1; +#endif +} + +void *SDL_AtariGL_GetProcAddress(_THIS, const char *proc) +{ + void *func = NULL; +#if SDL_VIDEO_OPENGL + + if (this->gl_config.dll_handle) { + func = SDL_LoadFunction(this->gl_config.dll_handle, (void *)proc); + } else if (this->gl_data->OSMesaGetProcAddress) { + func = this->gl_data->OSMesaGetProcAddress(proc); + } + +#endif + return func; +} + +int SDL_AtariGL_GetAttribute(_THIS, SDL_GLattr attrib, int* value) +{ +#if SDL_VIDEO_OPENGL + GLenum mesa_attrib; + SDL_Surface *surface; + + if (!gl_active) { + return -1; + } + + switch(attrib) { + case SDL_GL_RED_SIZE: + mesa_attrib = GL_RED_BITS; + break; + case SDL_GL_GREEN_SIZE: + mesa_attrib = GL_GREEN_BITS; + break; + case SDL_GL_BLUE_SIZE: + mesa_attrib = GL_BLUE_BITS; + break; + case SDL_GL_ALPHA_SIZE: + mesa_attrib = GL_ALPHA_BITS; + break; + case SDL_GL_DOUBLEBUFFER: + surface = this->screen; + *value = ((surface->flags & SDL_DOUBLEBUF)==SDL_DOUBLEBUF); + return 0; + case SDL_GL_DEPTH_SIZE: + mesa_attrib = GL_DEPTH_BITS; + break; + case SDL_GL_STENCIL_SIZE: + mesa_attrib = GL_STENCIL_BITS; + break; + case SDL_GL_ACCUM_RED_SIZE: + mesa_attrib = GL_ACCUM_RED_BITS; + break; + case SDL_GL_ACCUM_GREEN_SIZE: + mesa_attrib = GL_ACCUM_GREEN_BITS; + break; + case SDL_GL_ACCUM_BLUE_SIZE: + mesa_attrib = GL_ACCUM_BLUE_BITS; + break; + case SDL_GL_ACCUM_ALPHA_SIZE: + mesa_attrib = GL_ACCUM_ALPHA_BITS; + break; + default : + return -1; + } + + this->gl_data->glGetIntegerv(mesa_attrib, value); + return 0; +#else + return -1; +#endif +} + +int SDL_AtariGL_MakeCurrent(_THIS) +{ +#if SDL_VIDEO_OPENGL + SDL_Surface *surface; + GLenum type; + + if (gl_oldmesa && gl_active) { + return 0; + } + + if (this->gl_config.dll_handle) { + if ((this->gl_data->OSMesaMakeCurrent == NULL) || + (this->gl_data->OSMesaPixelStore == NULL)) { + return -1; + } + } + + if (!gl_active) { + SDL_SetError("Invalid OpenGL context"); + return -1; + } + + surface = this->screen; + + if ((surface->format->BitsPerPixel == 15) || (surface->format->BitsPerPixel == 16)) { + type = GL_UNSIGNED_SHORT_5_6_5; + } else { + type = GL_UNSIGNED_BYTE; + } + + if (!(this->gl_data->OSMesaMakeCurrent(gl_ctx, surface->pixels, type, surface->w, surface->h))) { + SDL_SetError("Can not make OpenGL context current"); + return -1; + } + + /* OSMesa draws upside down */ + this->gl_data->OSMesaPixelStore(OSMESA_Y_UP, 0); + + return 0; +#else + return -1; +#endif +} + +void SDL_AtariGL_SwapBuffers(_THIS) +{ +#if SDL_VIDEO_OPENGL + if (gl_active) { + if (this->gl_config.dll_handle) { + if (this->gl_data->glFinish) { + this->gl_data->glFinish(); + } else if (this->gl_data->glFlush) { + this->gl_data->glFlush(); + } + } else { + this->gl_data->glFinish(); + } + gl_copyshadow(this, this->screen); + gl_convert(this, this->screen); + } +#endif +} + +void SDL_AtariGL_InitPointers(_THIS) +{ +#if SDL_VIDEO_OPENGL + this->gl_data->OSMesaCreateContextExt = OSMesaCreateContextExt; + this->gl_data->OSMesaDestroyContext = OSMesaDestroyContext; + this->gl_data->OSMesaMakeCurrent = OSMesaMakeCurrent; + this->gl_data->OSMesaPixelStore = OSMesaPixelStore; + this->gl_data->OSMesaGetProcAddress = OSMesaGetProcAddress; + + this->gl_data->glGetIntegerv = glGetIntegerv; + this->gl_data->glFinish = glFinish; + this->gl_data->glFlush = glFlush; + + this->gl_data->OSMesaCreateLDG = NULL; + this->gl_data->OSMesaDestroyLDG = NULL; +#endif +} + +/*--- Private functions ---*/ + +#if SDL_VIDEO_OPENGL +static void SDL_AtariGL_UnloadLibrary(_THIS) +{ + if (this->gl_config.dll_handle) { + SDL_UnloadObject(this->gl_config.dll_handle); + this->gl_config.dll_handle = NULL; + + /* Restore pointers to static library */ + SDL_AtariGL_InitPointers(this); + } +} + +/*--- Creation of an OpenGL context using new/old functions ---*/ + +static int InitNew(_THIS, SDL_Surface *current) +{ + GLenum osmesa_format; + SDL_PixelFormat *pixel_format; + Uint32 redmask; + int recreatecontext; + GLint newaccumsize; + + if (this->gl_config.dll_handle) { + if (this->gl_data->OSMesaCreateContextExt == NULL) { + return 0; + } + } + + /* Init OpenGL context using OSMesa */ + gl_convert = ConvertNull; + gl_copyshadow = CopyShadowNull; + gl_upsidedown = SDL_FALSE; + + pixel_format = current->format; + redmask = pixel_format->Rmask; + switch (pixel_format->BitsPerPixel) { + case 15: + /* 1555, big and little endian, unsupported */ + gl_pixelsize = 2; + osmesa_format = OSMESA_RGB_565; + if (redmask == 31<<10) { + gl_convert = Convert565To555be; + } else { + gl_convert = Convert565To555le; + } + break; + case 16: + gl_pixelsize = 2; + if (redmask == 31<<11) { + osmesa_format = OSMESA_RGB_565; + } else { + /* 565, little endian, unsupported */ + osmesa_format = OSMESA_RGB_565; + gl_convert = Convert565le; + } + break; + case 24: + gl_pixelsize = 3; + if (redmask == 255<<16) { + osmesa_format = OSMESA_RGB; + } else { + osmesa_format = OSMESA_BGR; + } + break; + case 32: + gl_pixelsize = 4; + if (redmask == 255<<16) { + osmesa_format = OSMESA_ARGB; + } else if (redmask == 255<<8) { + osmesa_format = OSMESA_BGRA; + } else if (redmask == 255<<24) { + osmesa_format = OSMESA_RGBA; + } else { + /* ABGR format unsupported */ + osmesa_format = OSMESA_BGRA; + gl_convert = ConvertBGRAToABGR; + } + break; + default: + gl_pixelsize = 1; + osmesa_format = OSMESA_COLOR_INDEX; + break; + } + + /* Try to keep current context if possible */ + newaccumsize = + this->gl_config.accum_red_size + + this->gl_config.accum_green_size + + this->gl_config.accum_blue_size + + this->gl_config.accum_alpha_size; + recreatecontext=1; + if (gl_ctx && + (gl_curformat == osmesa_format) && + (gl_curdepth == this->gl_config.depth_size) && + (gl_curstencil == this->gl_config.stencil_size) && + (gl_curaccum == newaccumsize)) { + recreatecontext = 0; + } + if (recreatecontext) { + SDL_AtariGL_Quit(this, SDL_FALSE); + + gl_ctx = this->gl_data->OSMesaCreateContextExt( + osmesa_format, this->gl_config.depth_size, + this->gl_config.stencil_size, newaccumsize, NULL ); + + if (gl_ctx) { + gl_curformat = osmesa_format; + gl_curdepth = this->gl_config.depth_size; + gl_curstencil = this->gl_config.stencil_size; + gl_curaccum = newaccumsize; + } else { + gl_curformat = 0; + gl_curdepth = 0; + gl_curstencil = 0; + gl_curaccum = 0; + } + } + + return (gl_ctx != NULL); +} + + +static int InitOld(_THIS, SDL_Surface *current) +{ + GLenum osmesa_format; + SDL_PixelFormat *pixel_format; + Uint32 redmask; + int recreatecontext, tinygl_present; + + if (this->gl_config.dll_handle) { + if (this->gl_data->OSMesaCreateLDG == NULL) { + return 0; + } + } + + /* TinyGL only supports VDI_RGB (OSMESA_RGB) */ + tinygl_present=0; + if (this->gl_config.dll_handle) { + if (this->gl_data->glFinish == NULL) { + tinygl_present=1; + } + } + + /* Init OpenGL context using OSMesa */ + gl_convert = ConvertNull; + gl_copyshadow = CopyShadowNull; + gl_upsidedown = SDL_FALSE; + + pixel_format = current->format; + redmask = pixel_format->Rmask; + switch (pixel_format->BitsPerPixel) { + case 15: + /* 15 bits unsupported */ + if (tinygl_present) { + gl_pixelsize = 3; + osmesa_format = VDI_RGB; + if (redmask == 31<<10) { + gl_copyshadow = CopyShadowRGBTo555; + } else { + gl_copyshadow = CopyShadowRGBTo565; + gl_convert = Convert565To555le; + } + } else { + gl_pixelsize = 4; + gl_upsidedown = SDL_TRUE; + osmesa_format = OSMESA_ARGB; + if (redmask == 31<<10) { + gl_copyshadow = CopyShadow8888To555; + } else { + gl_copyshadow = CopyShadow8888To565; + gl_convert = Convert565To555le; + } + } + break; + case 16: + /* 16 bits unsupported */ + if (tinygl_present) { + gl_pixelsize = 3; + osmesa_format = VDI_RGB; + gl_copyshadow = CopyShadowRGBTo565; + if (redmask != 31<<11) { + /* 565, little endian, unsupported */ + gl_convert = Convert565le; + } + } else { + gl_pixelsize = 4; + gl_upsidedown = SDL_TRUE; + osmesa_format = OSMESA_ARGB; + gl_copyshadow = CopyShadow8888To565; + if (redmask != 31<<11) { + /* 565, little endian, unsupported */ + gl_convert = Convert565le; + } + } + break; + case 24: + gl_pixelsize = 3; + if (tinygl_present) { + osmesa_format = VDI_RGB; + gl_copyshadow = CopyShadowDirect; + if (redmask != 255<<16) { + gl_copyshadow = CopyShadowRGBSwap; + } + } else { + gl_copyshadow = CopyShadowDirect; + gl_upsidedown = SDL_TRUE; + if (redmask == 255<<16) { + osmesa_format = OSMESA_RGB; + } else { + osmesa_format = OSMESA_BGR; + } + } + break; + case 32: + if (tinygl_present) { + gl_pixelsize = 3; + osmesa_format = VDI_RGB; + gl_copyshadow = CopyShadowRGBToARGB; + if (redmask == 255) { + gl_convert = CopyShadowRGBToABGR; + } else if (redmask == 255<<8) { + gl_convert = CopyShadowRGBToBGRA; + } else if (redmask == 255<<24) { + gl_convert = CopyShadowRGBToRGBA; + } + } else { + gl_pixelsize = 4; + gl_upsidedown = SDL_TRUE; + gl_copyshadow = CopyShadowDirect; + if (redmask == 255<<16) { + osmesa_format = OSMESA_ARGB; + } else if (redmask == 255<<8) { + osmesa_format = OSMESA_BGRA; + } else if (redmask == 255<<24) { + osmesa_format = OSMESA_RGBA; + } else { + /* ABGR format unsupported */ + osmesa_format = OSMESA_BGRA; + gl_convert = ConvertBGRAToABGR; + } + } + break; + default: + if (tinygl_present) { + SDL_AtariGL_Quit(this, SDL_FALSE); + return 0; + } + gl_pixelsize = 1; + gl_copyshadow = CopyShadowDirect; + osmesa_format = OSMESA_COLOR_INDEX; + break; + } + + /* Try to keep current context if possible */ + recreatecontext=1; + if (gl_shadow && + (gl_curformat == osmesa_format) && + (gl_curwidth == current->w) && + (gl_curheight == current->h)) { + recreatecontext = 0; + } + if (recreatecontext) { + SDL_AtariGL_Quit(this, SDL_FALSE); + + gl_shadow = this->gl_data->OSMesaCreateLDG( + osmesa_format, GL_UNSIGNED_BYTE, current->w, current->h + ); + + if (gl_shadow) { + gl_curformat = osmesa_format; + gl_curwidth = current->w; + gl_curheight = current->h; + } else { + gl_curformat = 0; + gl_curwidth = 0; + gl_curheight = 0; + } + } + + return (gl_shadow != NULL); +} + +/*--- Conversions routines from shadow buffer to the screen ---*/ + +static void CopyShadowNull(_THIS, SDL_Surface *surface) +{ +} + +static void CopyShadowDirect(_THIS, SDL_Surface *surface) +{ + int y, srcpitch, dstpitch; + Uint8 *srcline, *dstline; + + srcline = gl_shadow; + srcpitch = surface->w * gl_pixelsize; + dstline = surface->pixels; + dstpitch = surface->pitch; + if (gl_upsidedown) { + srcline += (surface->h-1)*srcpitch; + srcpitch = -srcpitch; + } + + for (y=0; y<surface->h; y++) { + SDL_memcpy(dstline, srcline, srcpitch); + + srcline += srcpitch; + dstline += dstpitch; + } +} + +static void CopyShadowRGBTo555(_THIS, SDL_Surface *surface) +{ + int x,y, srcpitch, dstpitch; + Uint16 *dstline, *dstcol; + Uint8 *srcline, *srccol; + + srcline = (Uint8 *)gl_shadow; + srcpitch = surface->w * gl_pixelsize; + dstline = surface->pixels; + dstpitch = surface->pitch >>1; + if (gl_upsidedown) { + srcline += (surface->h-1)*srcpitch; + srcpitch = -srcpitch; + } + + for (y=0; y<surface->h; y++) { + srccol = srcline; + dstcol = dstline; + for (x=0; x<surface->w; x++) { + Uint16 dstcolor; + + dstcolor = ((*srccol++)<<7) & (31<<10); + dstcolor |= ((*srccol++)<<2) & (31<<5); + dstcolor |= ((*srccol++)>>3) & 31; + *dstcol++ = dstcolor; + } + + srcline += srcpitch; + dstline += dstpitch; + } +} + +static void CopyShadowRGBTo565(_THIS, SDL_Surface *surface) +{ + int x,y, srcpitch, dstpitch; + Uint16 *dstline, *dstcol; + Uint8 *srcline, *srccol; + + srcline = (Uint8 *)gl_shadow; + srcpitch = surface->w * gl_pixelsize; + dstline = surface->pixels; + dstpitch = surface->pitch >>1; + if (gl_upsidedown) { + srcline += (surface->h-1)*srcpitch; + srcpitch = -srcpitch; + } + + for (y=0; y<surface->h; y++) { + srccol = srcline; + dstcol = dstline; + + for (x=0; x<surface->w; x++) { + Uint16 dstcolor; + + dstcolor = ((*srccol++)<<8) & (31<<11); + dstcolor |= ((*srccol++)<<3) & (63<<5); + dstcolor |= ((*srccol++)>>3) & 31; + *dstcol++ = dstcolor; + } + + srcline += srcpitch; + dstline += dstpitch; + } +} + +static void CopyShadowRGBSwap(_THIS, SDL_Surface *surface) +{ + int x,y, srcpitch, dstpitch; + Uint8 *dstline, *dstcol; + Uint8 *srcline, *srccol; + + srcline = (Uint8 *)gl_shadow; + srcpitch = surface->w * gl_pixelsize; + dstline = surface->pixels; + dstpitch = surface->pitch; + if (gl_upsidedown) { + srcline += (surface->h-1)*srcpitch; + srcpitch = -srcpitch; + } + + for (y=0; y<surface->h; y++) { + srccol = srcline; + dstcol = dstline; + + for (x=0; x<surface->w; x++) { + *dstcol++ = srccol[2]; + *dstcol++ = srccol[1]; + *dstcol++ = srccol[0]; + srccol += 3; + } + + srcline += srcpitch; + dstline += dstpitch; + } +} + +static void CopyShadowRGBToARGB(_THIS, SDL_Surface *surface) +{ + int x,y, srcpitch, dstpitch; + Uint32 *dstline, *dstcol; + Uint8 *srcline, *srccol; + + srcline = (Uint8 *)gl_shadow; + srcpitch = surface->w * gl_pixelsize; + dstline = surface->pixels; + dstpitch = surface->pitch >>2; + if (gl_upsidedown) { + srcline += (surface->h-1)*srcpitch; + srcpitch = -srcpitch; + } + + for (y=0; y<surface->h; y++) { + srccol = srcline; + dstcol = dstline; + + for (x=0; x<surface->w; x++) { + Uint32 dstcolor; + + dstcolor = (*srccol++)<<16; + dstcolor |= (*srccol++)<<8; + dstcolor |= *srccol++; + + *dstcol++ = dstcolor; + } + + srcline += srcpitch; + dstline += dstpitch; + } +} + +static void CopyShadowRGBToABGR(_THIS, SDL_Surface *surface) +{ + int x,y, srcpitch, dstpitch; + Uint32 *dstline, *dstcol; + Uint8 *srcline, *srccol; + + srcline = (Uint8 *)gl_shadow; + srcpitch = surface->w * gl_pixelsize; + dstline = surface->pixels; + dstpitch = surface->pitch >>2; + if (gl_upsidedown) { + srcline += (surface->h-1)*srcpitch; + srcpitch = -srcpitch; + } + + for (y=0; y<surface->h; y++) { + srccol = srcline; + dstcol = dstline; + + for (x=0; x<surface->w; x++) { + Uint32 dstcolor; + + dstcolor = *srccol++; + dstcolor |= (*srccol++)<<8; + dstcolor |= (*srccol++)<<16; + + *dstcol++ = dstcolor; + } + + srcline += srcpitch; + dstline += dstpitch; + } +} + +static void CopyShadowRGBToBGRA(_THIS, SDL_Surface *surface) +{ + int x,y, srcpitch, dstpitch; + Uint32 *dstline, *dstcol; + Uint8 *srcline, *srccol; + + srcline = (Uint8 *)gl_shadow; + srcpitch = surface->w * gl_pixelsize; + dstline = surface->pixels; + dstpitch = surface->pitch >>2; + if (gl_upsidedown) { + srcline += (surface->h-1)*srcpitch; + srcpitch = -srcpitch; + } + + for (y=0; y<surface->h; y++) { + srccol = srcline; + dstcol = dstline; + + for (x=0; x<surface->w; x++) { + Uint32 dstcolor; + + dstcolor = (*srccol++)<<8; + dstcolor |= (*srccol++)<<16; + dstcolor |= (*srccol++)<<24; + + *dstcol++ = dstcolor; + } + + srcline += srcpitch; + dstline += dstpitch; + } +} + +static void CopyShadowRGBToRGBA(_THIS, SDL_Surface *surface) +{ + int x,y, srcpitch, dstpitch; + Uint32 *dstline, *dstcol; + Uint8 *srcline, *srccol; + + srcline = (Uint8 *)gl_shadow; + srcpitch = surface->w * gl_pixelsize; + dstline = surface->pixels; + dstpitch = surface->pitch >>2; + if (gl_upsidedown) { + srcline += (surface->h-1)*srcpitch; + srcpitch = -srcpitch; + } + + for (y=0; y<surface->h; y++) { + srccol = srcline; + dstcol = dstline; + + for (x=0; x<surface->w; x++) { + Uint32 dstcolor; + + dstcolor = (*srccol++)<<24; + dstcolor |= (*srccol++)<<16; + dstcolor |= (*srccol++)<<8; + + *dstcol++ = dstcolor; + } + + srcline += srcpitch; + dstline += dstpitch; + } +} + +static void CopyShadow8888To555(_THIS, SDL_Surface *surface) +{ + int x,y, srcpitch, dstpitch; + Uint16 *dstline, *dstcol; + Uint32 *srcline, *srccol; + + srcline = (Uint32 *)gl_shadow; + srcpitch = (surface->w * gl_pixelsize) >>2; + dstline = surface->pixels; + dstpitch = surface->pitch >>1; + if (gl_upsidedown) { + srcline += (surface->h-1)*srcpitch; + srcpitch = -srcpitch; + } + + for (y=0; y<surface->h; y++) { + srccol = srcline; + dstcol = dstline; + for (x=0; x<surface->w; x++) { + Uint32 srccolor; + Uint16 dstcolor; + + srccolor = *srccol++; + dstcolor = (srccolor>>9) & (31<<10); + dstcolor |= (srccolor>>6) & (31<<5); + dstcolor |= (srccolor>>3) & 31; + *dstcol++ = dstcolor; + } + + srcline += srcpitch; + dstline += dstpitch; + } +} + +static void CopyShadow8888To565(_THIS, SDL_Surface *surface) +{ + int x,y, srcpitch, dstpitch; + Uint16 *dstline, *dstcol; + Uint32 *srcline, *srccol; + + srcline = (Uint32 *)gl_shadow; + srcpitch = (surface->w * gl_pixelsize) >> 2; + dstline = surface->pixels; + dstpitch = surface->pitch >>1; + if (gl_upsidedown) { + srcline += (surface->h-1)*srcpitch; + srcpitch = -srcpitch; + } + + for (y=0; y<surface->h; y++) { + srccol = srcline; + dstcol = dstline; + + for (x=0; x<surface->w; x++) { + Uint32 srccolor; + Uint16 dstcolor; + + srccolor = *srccol++; + dstcolor = (srccolor>>8) & (31<<11); + dstcolor |= (srccolor>>5) & (63<<5); + dstcolor |= (srccolor>>3) & 31; + *dstcol++ = dstcolor; + } + + srcline += srcpitch; + dstline += dstpitch; + } +} + +/*--- Conversions routines in the screen ---*/ + +static void ConvertNull(_THIS, SDL_Surface *surface) +{ +} + +static void Convert565To555be(_THIS, SDL_Surface *surface) +{ + int x,y, pitch; + unsigned short *line, *pixel; + + line = surface->pixels; + pitch = surface->pitch >> 1; + for (y=0; y<surface->h; y++) { + pixel = line; + for (x=0; x<surface->w; x++) { + unsigned short color = *pixel; + + *pixel++ = (color & 0x1f)|((color>>1) & 0xffe0); + } + + line += pitch; + } +} + +static void Convert565To555le(_THIS, SDL_Surface *surface) +{ + int x,y, pitch; + unsigned short *line, *pixel; + + line = surface->pixels; + pitch = surface->pitch >>1; + for (y=0; y<surface->h; y++) { + pixel = line; + for (x=0; x<surface->w; x++) { + unsigned short color = *pixel; + + color = (color & 0x1f)|((color>>1) & 0xffe0); + *pixel++ = SDL_Swap16(color); + } + + line += pitch; + } +} + +static void Convert565le(_THIS, SDL_Surface *surface) +{ + int x,y, pitch; + unsigned short *line, *pixel; + + line = surface->pixels; + pitch = surface->pitch >>1; + for (y=0; y<surface->h; y++) { + pixel = line; + for (x=0; x<surface->w; x++) { + unsigned short color = *pixel; + + *pixel++ = SDL_Swap16(color); + } + + line += pitch; + } +} + +static void ConvertBGRAToABGR(_THIS, SDL_Surface *surface) +{ + int x,y, pitch; + unsigned long *line, *pixel; + + line = surface->pixels; + pitch = surface->pitch >>2; + for (y=0; y<surface->h; y++) { + pixel = line; + for (x=0; x<surface->w; x++) { + unsigned long color = *pixel; + + *pixel++ = (color<<24)|(color>>8); + } + + line += pitch; + } +} + +#endif /* SDL_VIDEO_OPENGL */ diff --git a/3rdparty/SDL/src/video/ataricommon/SDL_atarigl_c.h b/3rdparty/SDL/src/video/ataricommon/SDL_atarigl_c.h new file mode 100644 index 0000000..5adcf2a --- /dev/null +++ b/3rdparty/SDL/src/video/ataricommon/SDL_atarigl_c.h @@ -0,0 +1,109 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* Atari OSMesa.ldg implementation of SDL OpenGL support */ + +#ifndef _SDL_ATARIGL_H_ +#define _SDL_ATARIGL_H_ + +#if SDL_VIDEO_OPENGL +#include <GL/osmesa.h> +#endif + +#include "../SDL_sysvideo.h" + +/* Hidden "this" pointer for the video functions */ +#define _THIS SDL_VideoDevice *this + +struct SDL_PrivateGLData { + + int gl_active; /* to stop switching drivers while we have a valid context */ + + int gl_oldmesa; /* Old OpenGL support ? */ + + int gl_pixelsize; /* for CopyShadow functions */ + + SDL_bool gl_upsidedown; /* Some implementations draw upside down */ + + Uint8 *gl_shadow; /* Shadow buffer for old implementations */ + + /* for unsupported OSMesa buffer formats */ + void (*ConvertSurface)(_THIS, SDL_Surface *surface); + + /* to convert the shadow buffer to the screen format */ + void (*CopyShadow)(_THIS, SDL_Surface *surface); + +#if SDL_VIDEO_OPENGL + OSMesaContext ctx; + + /* OpenGL functions */ + void (*glGetIntegerv)( GLenum pname, GLint *value ); + void (*glFinish)(void); + void (*glFlush)(void); + + /* osmesa.ldg */ + OSMesaContext (*OSMesaCreateContextExt)( GLenum format, GLint depthBits, GLint stencilBits, GLint accumBits, OSMesaContext sharelist); + void (*OSMesaDestroyContext)( OSMesaContext ctx ); + GLboolean (*OSMesaMakeCurrent)( OSMesaContext ctx, void *buffer, GLenum type, GLsizei width, GLsizei height ); + void (*OSMesaPixelStore)( GLint pname, GLint value ); + void * (*OSMesaGetProcAddress)( const char *funcName ); + + /* mesa_gl.ldg, tiny_gl.ldg */ + void *(*OSMesaCreateLDG)( long format, long type, long width, long height ); + void (*OSMesaDestroyLDG)(void); + + /* Info needed to compare existing context with new asked one */ + int width, height; + GLenum format; + GLint depth,stencil,accum; +#endif +}; + +/* Variable names */ +#define gl_active (this->gl_data->gl_active) +#define gl_ctx (this->gl_data->ctx) +#define gl_oldmesa (this->gl_data->gl_oldmesa) +#define gl_pixelsize (this->gl_data->gl_pixelsize) +#define gl_upsidedown (this->gl_data->gl_upsidedown) +#define gl_shadow (this->gl_data->gl_shadow) +#define gl_convert (this->gl_data->ConvertSurface) +#define gl_copyshadow (this->gl_data->CopyShadow) +#define gl_curformat (this->gl_data->format) +#define gl_curdepth (this->gl_data->depth) +#define gl_curstencil (this->gl_data->stencil) +#define gl_curaccum (this->gl_data->accum) +#define gl_curwidth (this->gl_data->width) +#define gl_curheight (this->gl_data->height) + +/* OpenGL functions */ +extern int SDL_AtariGL_Init(_THIS, SDL_Surface *current); +extern void SDL_AtariGL_Quit(_THIS, SDL_bool unload); +extern void SDL_AtariGL_InitPointers(_THIS); + +extern int SDL_AtariGL_LoadLibrary(_THIS, const char *path); +extern void *SDL_AtariGL_GetProcAddress(_THIS, const char *proc); +extern int SDL_AtariGL_GetAttribute(_THIS, SDL_GLattr attrib, int* value); +extern int SDL_AtariGL_MakeCurrent(_THIS); +extern void SDL_AtariGL_SwapBuffers(_THIS); + +#endif /* _SDL_ATARIGL_H_ */ diff --git a/3rdparty/SDL/src/video/ataricommon/SDL_atarikeys.h b/3rdparty/SDL/src/video/ataricommon/SDL_atarikeys.h new file mode 100644 index 0000000..a9f7cfd --- /dev/null +++ b/3rdparty/SDL/src/video/ataricommon/SDL_atarikeys.h @@ -0,0 +1,140 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ + +/* + * Atari Scancode definitions + * + * Patrice Mandin + */ + +#ifndef _SDL_ATARIKEYS_H_ +#define _SDL_ATARIKEYS_H_ + +/* --- Keyboard scancodes --- */ +/* taken from svgalib/vgakeyboard.h */ + +#define SCANCODE_ESCAPE 0x01 +#define SCANCODE_1 0x02 +#define SCANCODE_2 0x03 +#define SCANCODE_3 0x04 +#define SCANCODE_4 0x05 +#define SCANCODE_5 0x06 +#define SCANCODE_6 0x07 +#define SCANCODE_7 0x08 +#define SCANCODE_8 0x09 +#define SCANCODE_9 0x0a +#define SCANCODE_0 0x0b +#define SCANCODE_MINUS 0x0c +#define SCANCODE_EQUAL 0x0d +#define SCANCODE_BACKSPACE 0x0e + +#define SCANCODE_TAB 0x0f +#define SCANCODE_Q 0x10 +#define SCANCODE_W 0x11 +#define SCANCODE_E 0x12 +#define SCANCODE_R 0x13 +#define SCANCODE_T 0x14 +#define SCANCODE_Y 0x15 +#define SCANCODE_U 0x16 +#define SCANCODE_I 0x17 +#define SCANCODE_O 0x18 +#define SCANCODE_P 0x19 +#define SCANCODE_BRACKET_LEFT 0x1a +#define SCANCODE_BRACKET_RIGHT 0x1b +#define SCANCODE_ENTER 0x1c +#define SCANCODE_DELETE 0x53 + +#define SCANCODE_LEFTCONTROL 0x1d +#define SCANCODE_A 0x1e +#define SCANCODE_S 0x1f +#define SCANCODE_D 0x20 +#define SCANCODE_F 0x21 +#define SCANCODE_G 0x22 +#define SCANCODE_H 0x23 +#define SCANCODE_J 0x24 +#define SCANCODE_K 0x25 +#define SCANCODE_L 0x26 +#define SCANCODE_SEMICOLON 0x27 +#define SCANCODE_APOSTROPHE 0x28 +#define SCANCODE_GRAVE 0x29 + +#define SCANCODE_LEFTSHIFT 0x2a +#define SCANCODE_BACKSLASH 0x2b +#define SCANCODE_Z 0x2c +#define SCANCODE_X 0x2d +#define SCANCODE_C 0x2e +#define SCANCODE_V 0x2f +#define SCANCODE_B 0x30 +#define SCANCODE_N 0x31 +#define SCANCODE_M 0x32 +#define SCANCODE_COMMA 0x33 +#define SCANCODE_PERIOD 0x34 +#define SCANCODE_SLASH 0x35 +#define SCANCODE_RIGHTSHIFT 0x36 + +#define SCANCODE_LEFTALT 0x38 +#define SCANCODE_SPACE 0x39 +#define SCANCODE_CAPSLOCK 0x3a + +/* Functions keys */ +#define SCANCODE_F1 0x3b +#define SCANCODE_F2 0x3c +#define SCANCODE_F3 0x3d +#define SCANCODE_F4 0x3e +#define SCANCODE_F5 0x3f +#define SCANCODE_F6 0x40 +#define SCANCODE_F7 0x41 +#define SCANCODE_F8 0x42 +#define SCANCODE_F9 0x43 +#define SCANCODE_F10 0x44 + +/* Numeric keypad */ +#define SCANCODE_KP0 0x70 +#define SCANCODE_KP1 0x6d +#define SCANCODE_KP2 0x6e +#define SCANCODE_KP3 0x6f +#define SCANCODE_KP4 0x6a +#define SCANCODE_KP5 0x6b +#define SCANCODE_KP6 0x6c +#define SCANCODE_KP7 0x67 +#define SCANCODE_KP8 0x68 +#define SCANCODE_KP9 0x69 +#define SCANCODE_KP_PERIOD 0x71 +#define SCANCODE_KP_DIVIDE 0x65 +#define SCANCODE_KP_MULTIPLY 0x66 +#define SCANCODE_KP_MINUS 0x4a +#define SCANCODE_KP_PLUS 0x4e +#define SCANCODE_KP_ENTER 0x72 +#define SCANCODE_KP_LEFTPAREN 0x63 +#define SCANCODE_KP_RIGHTPAREN 0x64 + +/* Cursor keypad */ +#define SCANCODE_HELP 0x62 +#define SCANCODE_UNDO 0x61 +#define SCANCODE_INSERT 0x52 +#define SCANCODE_CLRHOME 0x47 +#define SCANCODE_UP 0x48 +#define SCANCODE_DOWN 0x50 +#define SCANCODE_RIGHT 0x4d +#define SCANCODE_LEFT 0x4b + +#endif /* _SDL_ATARIKEYS_H_ */ diff --git a/3rdparty/SDL/src/video/ataricommon/SDL_atarimxalloc.c b/3rdparty/SDL/src/video/ataricommon/SDL_atarimxalloc.c new file mode 100644 index 0000000..224baef --- /dev/null +++ b/3rdparty/SDL/src/video/ataricommon/SDL_atarimxalloc.c @@ -0,0 +1,52 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* + * Memory allocation + * + * Patrice Mandin + */ + +#include <mint/osbind.h> + +#include "SDL_stdinc.h" + +/*--- Variables ---*/ + +static int atari_mxalloc_avail=-1; + +/*--- Functions ---*/ + +void *Atari_SysMalloc(Uint32 size, Uint16 alloc_type) +{ + /* Test if Mxalloc() available */ + if (atari_mxalloc_avail<0) { + atari_mxalloc_avail = ((Sversion()&0xFF)>=0x01) | (Sversion()>=0x1900); + } + + if (atari_mxalloc_avail) { + return (void *) Mxalloc(size, alloc_type); + } else { + return (void *) Malloc(size); + } +} diff --git a/3rdparty/SDL/src/video/ataricommon/SDL_atarimxalloc_c.h b/3rdparty/SDL/src/video/ataricommon/SDL_atarimxalloc_c.h new file mode 100644 index 0000000..937408d --- /dev/null +++ b/3rdparty/SDL/src/video/ataricommon/SDL_atarimxalloc_c.h @@ -0,0 +1,37 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* + * Memory allocation + * + * Patrice Mandin + */ + +#ifndef _SDL_ATARI_MXALLOC_H_ +#define _SDL_ATARI_MXALLOC_H_ + +/*--- Functions ---*/ + +extern void *Atari_SysMalloc(Uint32 size, Uint16 alloc_type); + +#endif /* _SDL_ATARI_MXALLOC_H_ */ diff --git a/3rdparty/SDL/src/video/ataricommon/SDL_atarisuper.h b/3rdparty/SDL/src/video/ataricommon/SDL_atarisuper.h new file mode 100644 index 0000000..8f25c7e --- /dev/null +++ b/3rdparty/SDL/src/video/ataricommon/SDL_atarisuper.h @@ -0,0 +1,61 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#ifndef _ATARI_SUPER_h +#define _ATARI_SUPER_h + +#include "SDL_stdinc.h" + +#ifndef SuperToUser + +/* + * Safe binding to switch back from supervisor to user mode. + * On TOS or EmuTOS, if the stack pointer has changed between Super(0) + * and Super(oldssp), the resulting user stack pointer is wrong. + * This bug does not occur with FreeMiNT. + * So the safe way to return from supervisor to user mode is to backup + * the stack pointer then restore it after the trap. + * Sometimes, GCC optimizes the stack usage, so this matters. + */ +#define SuperToUser(ptr) \ +(void)__extension__ \ +({ \ + register long retvalue __asm__("d0"); \ + register long sp_backup; \ + \ + __asm__ volatile \ + ( \ + "movl sp,%1\n\t" \ + "movl %2,sp@-\n\t" \ + "movw #0x20,sp@-\n\t" \ + "trap #1\n\t" \ + "movl %1,sp\n\t" \ + : "=r"(retvalue), "=&r"(sp_backup) /* outputs */ \ + : "g"((long)(ptr)) /* inputs */ \ + : "d1", "d2", "a0", "a1", "a2" \ + ); \ +}) + +#endif /* SuperToUser */ + +#endif /* _ATARI_SUPER_h */ diff --git a/3rdparty/SDL/src/video/ataricommon/SDL_biosevents.c b/3rdparty/SDL/src/video/ataricommon/SDL_biosevents.c new file mode 100644 index 0000000..3d36b2b --- /dev/null +++ b/3rdparty/SDL/src/video/ataricommon/SDL_biosevents.c @@ -0,0 +1,131 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* + * Atari keyboard events manager, using BIOS + * + * Patrice Mandin + */ + +/* Mint includes */ +#include <mint/osbind.h> +#include <mint/cookie.h> + +#include "../../events/SDL_sysevents.h" +#include "../../events/SDL_events_c.h" + +#include "SDL_atarikeys.h" +#include "SDL_atarievents_c.h" +#include "SDL_xbiosevents_c.h" +#include "SDL_ataridevmouse_c.h" + +static unsigned char bios_currentkeyboard[ATARIBIOS_MAXKEYS]; +static unsigned char bios_previouskeyboard[ATARIBIOS_MAXKEYS]; +static SDL_bool use_dev_mouse = SDL_FALSE; + +static void UpdateSpecialKeys(int special_keys_state); + +void AtariBios_InitOSKeymap(_THIS) +{ + int vectors_mask; +/* unsigned long dummy;*/ + + SDL_memset(bios_currentkeyboard, 0, sizeof(bios_currentkeyboard)); + SDL_memset(bios_previouskeyboard, 0, sizeof(bios_previouskeyboard)); + + use_dev_mouse = (SDL_AtariDevMouse_Open()!=0) ? SDL_TRUE : SDL_FALSE; + + vectors_mask = ATARI_XBIOS_JOYSTICKEVENTS; /* XBIOS joystick events */ + if (!use_dev_mouse) { + vectors_mask |= ATARI_XBIOS_MOUSEEVENTS; /* XBIOS mouse events */ + } +/* if (Getcookie(C_MiNT, &dummy)==C_FOUND) { + vectors_mask = 0; + }*/ + + SDL_AtariXbios_InstallVectors(vectors_mask); +} + +void AtariBios_PumpEvents(_THIS) +{ + int i; + SDL_keysym keysym; + + /* Update pressed keys */ + SDL_memset(bios_currentkeyboard, 0, ATARIBIOS_MAXKEYS); + + while (Bconstat(_CON)) { + unsigned long key_pressed; + key_pressed=Bconin(_CON); + bios_currentkeyboard[(key_pressed>>16)&(ATARIBIOS_MAXKEYS-1)]=0xFF; + } + + /* Read special keys */ + UpdateSpecialKeys(Kbshift(-1)); + + /* Now generate events */ + for (i=0; i<ATARIBIOS_MAXKEYS; i++) { + /* Key pressed ? */ + if (bios_currentkeyboard[i] && !bios_previouskeyboard[i]) + SDL_PrivateKeyboard(SDL_PRESSED, + SDL_Atari_TranslateKey(i, &keysym, SDL_TRUE)); + + /* Key unpressed ? */ + if (bios_previouskeyboard[i] && !bios_currentkeyboard[i]) + SDL_PrivateKeyboard(SDL_RELEASED, + SDL_Atari_TranslateKey(i, &keysym, SDL_FALSE)); + } + + if (use_dev_mouse) { + SDL_AtariDevMouse_PostMouseEvents(this, SDL_TRUE); + } else { + SDL_AtariXbios_PostMouseEvents(this, SDL_TRUE); + } + + /* Will be previous table */ + SDL_memcpy(bios_previouskeyboard, bios_currentkeyboard, sizeof(bios_previouskeyboard)); +} + +static void UpdateSpecialKeys(int special_keys_state) +{ +#define UPDATE_SPECIAL_KEYS(numbit,scancode) \ + { \ + if (special_keys_state & (1<<(numbit))) { \ + bios_currentkeyboard[scancode]=0xFF; \ + } \ + } + + UPDATE_SPECIAL_KEYS(K_RSHIFT, SCANCODE_RIGHTSHIFT); + UPDATE_SPECIAL_KEYS(K_LSHIFT, SCANCODE_LEFTSHIFT); + UPDATE_SPECIAL_KEYS(K_CTRL, SCANCODE_LEFTCONTROL); + UPDATE_SPECIAL_KEYS(K_ALT, SCANCODE_LEFTALT); + UPDATE_SPECIAL_KEYS(K_CAPSLOCK, SCANCODE_CAPSLOCK); +} + +void AtariBios_ShutdownEvents(void) +{ + SDL_AtariXbios_RestoreVectors(); + if (use_dev_mouse) { + SDL_AtariDevMouse_Close(); + } +} diff --git a/3rdparty/SDL/src/video/ataricommon/SDL_biosevents_c.h b/3rdparty/SDL/src/video/ataricommon/SDL_biosevents_c.h new file mode 100644 index 0000000..f016e6a --- /dev/null +++ b/3rdparty/SDL/src/video/ataricommon/SDL_biosevents_c.h @@ -0,0 +1,42 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* + * Atari keyboard events manager, using BIOS + * + * Patrice Mandin + */ + +#ifndef _SDL_ATARI_BIOSEVENTS_H_ +#define _SDL_ATARI_BIOSEVENTS_H_ + +#include "../SDL_sysvideo.h" + +/* Hidden "this" pointer for the video functions */ +#define _THIS SDL_VideoDevice *this + +extern void AtariBios_InitOSKeymap(_THIS); +extern void AtariBios_PumpEvents(_THIS); +extern void AtariBios_ShutdownEvents(void); + +#endif /* _SDL_ATARI_BIOSEVENTS_H_ */ diff --git a/3rdparty/SDL/src/video/ataricommon/SDL_gemdosevents.c b/3rdparty/SDL/src/video/ataricommon/SDL_gemdosevents.c new file mode 100644 index 0000000..e1ebaa6 --- /dev/null +++ b/3rdparty/SDL/src/video/ataricommon/SDL_gemdosevents.c @@ -0,0 +1,132 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* + * Atari keyboard events manager, using Gemdos + * + * Patrice Mandin + */ + +/* Mint includes */ +#include <mint/osbind.h> +#include <mint/cookie.h> + +#include "../../events/SDL_sysevents.h" +#include "../../events/SDL_events_c.h" + +#include "SDL_atarikeys.h" +#include "SDL_atarievents_c.h" +#include "SDL_xbiosevents_c.h" +#include "SDL_ataridevmouse_c.h" + +/* To save state of keyboard */ + +static unsigned char gemdos_currentkeyboard[ATARIBIOS_MAXKEYS]; +static unsigned char gemdos_previouskeyboard[ATARIBIOS_MAXKEYS]; +static SDL_bool use_dev_mouse = SDL_FALSE; + +static void UpdateSpecialKeys(int special_keys_state); + +void AtariGemdos_InitOSKeymap(_THIS) +{ + int vectors_mask; +/* unsigned long dummy;*/ + + SDL_memset(gemdos_currentkeyboard, 0, sizeof(gemdos_currentkeyboard)); + SDL_memset(gemdos_previouskeyboard, 0, sizeof(gemdos_previouskeyboard)); + + use_dev_mouse = (SDL_AtariDevMouse_Open()!=0) ? SDL_TRUE : SDL_FALSE; + + vectors_mask = ATARI_XBIOS_JOYSTICKEVENTS; /* XBIOS joystick events */ + if (!use_dev_mouse) { + vectors_mask |= ATARI_XBIOS_MOUSEEVENTS; /* XBIOS mouse events */ + } +/* if (Getcookie(C_MiNT, &dummy)==C_FOUND) { + vectors_mask = 0; + }*/ + SDL_AtariXbios_InstallVectors(vectors_mask); +} + +void AtariGemdos_PumpEvents(_THIS) +{ + int i; + SDL_keysym keysym; + + /* Update pressed keys */ + SDL_memset(gemdos_currentkeyboard, 0, ATARIBIOS_MAXKEYS); + + while (Cconis()!=DEV_BUSY) { + unsigned long key_pressed; + key_pressed=Cnecin(); + gemdos_currentkeyboard[(key_pressed>>16)&(ATARIBIOS_MAXKEYS-1)]=0xFF; + } + + /* Read special keys */ + UpdateSpecialKeys(Kbshift(-1)); + + /* Now generate events */ + for (i=0; i<ATARIBIOS_MAXKEYS; i++) { + /* Key pressed ? */ + if (gemdos_currentkeyboard[i] && !gemdos_previouskeyboard[i]) + SDL_PrivateKeyboard(SDL_PRESSED, + SDL_Atari_TranslateKey(i, &keysym, SDL_TRUE)); + + /* Key unpressed ? */ + if (gemdos_previouskeyboard[i] && !gemdos_currentkeyboard[i]) + SDL_PrivateKeyboard(SDL_RELEASED, + SDL_Atari_TranslateKey(i, &keysym, SDL_FALSE)); + } + + if (use_dev_mouse) { + SDL_AtariDevMouse_PostMouseEvents(this, SDL_TRUE); + } else { + SDL_AtariXbios_PostMouseEvents(this, SDL_TRUE); + } + + /* Will be previous table */ + SDL_memcpy(gemdos_previouskeyboard, gemdos_currentkeyboard, sizeof(gemdos_previouskeyboard)); +} + +static void UpdateSpecialKeys(int special_keys_state) +{ +#define UPDATE_SPECIAL_KEYS(numbit,scancode) \ + { \ + if (special_keys_state & (1<<(numbit))) { \ + gemdos_currentkeyboard[scancode]=0xFF; \ + } \ + } + + UPDATE_SPECIAL_KEYS(K_RSHIFT, SCANCODE_RIGHTSHIFT); + UPDATE_SPECIAL_KEYS(K_LSHIFT, SCANCODE_LEFTSHIFT); + UPDATE_SPECIAL_KEYS(K_CTRL, SCANCODE_LEFTCONTROL); + UPDATE_SPECIAL_KEYS(K_ALT, SCANCODE_LEFTALT); + UPDATE_SPECIAL_KEYS(K_CAPSLOCK, SCANCODE_CAPSLOCK); +} + +void AtariGemdos_ShutdownEvents(void) +{ + SDL_AtariXbios_RestoreVectors(); + if (use_dev_mouse) { + SDL_AtariDevMouse_Close(); + } +} diff --git a/3rdparty/SDL/src/video/ataricommon/SDL_gemdosevents_c.h b/3rdparty/SDL/src/video/ataricommon/SDL_gemdosevents_c.h new file mode 100644 index 0000000..b9924e6 --- /dev/null +++ b/3rdparty/SDL/src/video/ataricommon/SDL_gemdosevents_c.h @@ -0,0 +1,42 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* + * Atari keyboard events manager, using Gemdos + * + * Patrice Mandin + */ + +#ifndef _SDL_ATARI_GEMDOSEVENTS_H_ +#define _SDL_ATARI_GEMDOSEVENTS_H_ + +#include "../SDL_sysvideo.h" + +/* Hidden "this" pointer for the video functions */ +#define _THIS SDL_VideoDevice *this + +extern void AtariGemdos_InitOSKeymap(_THIS); +extern void AtariGemdos_PumpEvents(_THIS); +extern void AtariGemdos_ShutdownEvents(void); + +#endif /* _SDL_ATARI_GEMDOSEVENTS_H_ */ diff --git a/3rdparty/SDL/src/video/ataricommon/SDL_ikbdevents.c b/3rdparty/SDL/src/video/ataricommon/SDL_ikbdevents.c new file mode 100644 index 0000000..35fc5cb --- /dev/null +++ b/3rdparty/SDL/src/video/ataricommon/SDL_ikbdevents.c @@ -0,0 +1,124 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* + * Atari keyboard events manager, using hardware IKBD + * + * Patrice Mandin + */ + +/* Mint includes */ +#include <mint/osbind.h> + +#include "../../events/SDL_sysevents.h" +#include "../../events/SDL_events_c.h" + +#include "SDL_atarikeys.h" +#include "SDL_atarievents_c.h" +#include "SDL_ikbdinterrupt_s.h" + +#define KEY_PRESSED 0xff +#define KEY_UNDEFINED 0x80 +#define KEY_RELEASED 0x00 + +static Uint16 atari_prevmouseb; /* save state of mouse buttons */ + +void AtariIkbd_InitOSKeymap(_THIS) +{ + SDL_memset((void *) SDL_AtariIkbd_keyboard, KEY_UNDEFINED, sizeof(SDL_AtariIkbd_keyboard)); + + /* Now install our handler */ + SDL_AtariIkbd_mouseb = SDL_AtariIkbd_mousex = SDL_AtariIkbd_mousey = 0; + atari_prevmouseb = 0; + + Supexec(SDL_AtariIkbdInstall); +} + +static int atari_GetButton(int button) +{ + switch(button) + { + case 0: + return SDL_BUTTON_RIGHT; + break; + case 1: + default: + return SDL_BUTTON_LEFT; + break; + } +} + +void AtariIkbd_PumpEvents(_THIS) +{ + int i; + SDL_keysym keysym; + + /*--- Send keyboard events ---*/ + + for (i=0; i<ATARIBIOS_MAXKEYS; i++) { + /* Key pressed ? */ + if (SDL_AtariIkbd_keyboard[i]==KEY_PRESSED) { + SDL_PrivateKeyboard(SDL_PRESSED, + SDL_Atari_TranslateKey(i, &keysym, SDL_TRUE)); + SDL_AtariIkbd_keyboard[i]=KEY_UNDEFINED; + } + + /* Key released ? */ + if (SDL_AtariIkbd_keyboard[i]==KEY_RELEASED) { + SDL_PrivateKeyboard(SDL_RELEASED, + SDL_Atari_TranslateKey(i, &keysym, SDL_FALSE)); + SDL_AtariIkbd_keyboard[i]=KEY_UNDEFINED; + } + } + + /*--- Send mouse events ---*/ + + /* Mouse motion ? */ + if (SDL_AtariIkbd_mousex || SDL_AtariIkbd_mousey) { + SDL_PrivateMouseMotion(0, 1, SDL_AtariIkbd_mousex, SDL_AtariIkbd_mousey); + SDL_AtariIkbd_mousex = SDL_AtariIkbd_mousey = 0; + } + + /* Mouse button ? */ + if (SDL_AtariIkbd_mouseb != atari_prevmouseb) { + for (i=0;i<2;i++) { + int curbutton, prevbutton; + + curbutton = SDL_AtariIkbd_mouseb & (1<<i); + prevbutton = atari_prevmouseb & (1<<i); + + if (curbutton && !prevbutton) { + SDL_PrivateMouseButton(SDL_PRESSED, atari_GetButton(i), 0, 0); + } + if (!curbutton && prevbutton) { + SDL_PrivateMouseButton(SDL_RELEASED, atari_GetButton(i), 0, 0); + } + } + atari_prevmouseb = SDL_AtariIkbd_mouseb; + } +} + +void AtariIkbd_ShutdownEvents(void) +{ + Supexec(SDL_AtariIkbdUninstall); +} diff --git a/3rdparty/SDL/src/video/ataricommon/SDL_ikbdevents_c.h b/3rdparty/SDL/src/video/ataricommon/SDL_ikbdevents_c.h new file mode 100644 index 0000000..753e777 --- /dev/null +++ b/3rdparty/SDL/src/video/ataricommon/SDL_ikbdevents_c.h @@ -0,0 +1,42 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* + * Atari keyboard events manager, using hardware IKBD + * + * Patrice Mandin + */ + +#ifndef _SDL_ATARI_IKBDEVENTS_H_ +#define _SDL_ATARI_IKBDEVENTS_H_ + +#include "../SDL_sysvideo.h" + +/* Hidden "this" pointer for the video functions */ +#define _THIS SDL_VideoDevice *this + +extern void AtariIkbd_InitOSKeymap(_THIS); +extern void AtariIkbd_PumpEvents(_THIS); +extern void AtariIkbd_ShutdownEvents(void); + +#endif /* _SDL_ATARI_IKBDEVENTS_H_ */ diff --git a/3rdparty/SDL/src/video/ataricommon/SDL_ikbdinterrupt.S b/3rdparty/SDL/src/video/ataricommon/SDL_ikbdinterrupt.S new file mode 100644 index 0000000..21facc8 --- /dev/null +++ b/3rdparty/SDL/src/video/ataricommon/SDL_ikbdinterrupt.S @@ -0,0 +1,404 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ + +/* + * IKBD 6301 interrupt routine + * + * Patrice Mandin + */ + + .text + + .globl _SDL_AtariIkbdInstall + .globl _SDL_AtariIkbdUninstall + + .globl _SDL_AtariIkbd_keyboard + .globl _SDL_AtariIkbd_mouseb + .globl _SDL_AtariIkbd_mousex + .globl _SDL_AtariIkbd_mousey + .globl _SDL_AtariIkbd_joystick + + .globl _SDL_AtariIkbd_enabled + +/*--- Install our IKBD vector ---*/ + +_SDL_AtariIkbdInstall: +#if defined(__mcoldfire__) + lea sp@(-16),sp + moveml d0-d1/a0-a1,sp@ +#else + moveml d0-d1/a0-a1,sp@- +#endif + + | Disable interrupts + + movew #0x2700,sr + + | Save MFP registers used for keyboard + + lea 0xfffffa00:w,a0 + btst #6,a0@(0x09) +#if defined(__mcoldfire__) + sne d0 + move.b d0,ikbd_ierb +#else + sne ikbd_ierb +#endif + btst #6,a0@(0x15) +#if defined(__mcoldfire__) + sne d0 + move.b d0,ikbd_imrb +#else + sne ikbd_imrb +#endif + + | Set our routine + +#if defined(__mcoldfire__) + movel 0x118:w,d0 + movel d0,old_ikbd + lea ikbd,a0 + movel a0,0x118:w + moveql #6,d0 + bset d0,0xfffffa09:w | IERB + bset d0,0xfffffa15:w | IMRB +#else + movel 0x118:w,old_ikbd + movel #ikbd,0x118:w + bset #6,0xfffffa09:w | IERB + bset #6,0xfffffa15:w | IMRB +#endif + + | Set mouse relative mode + +#if defined(__mcoldfire__) + moveql #8,d0 + moveb d0,0xfffffc02:w +#else + moveb #8,0xfffffc02:w +#endif + + | Reenable interrupts + + movew #0x2300,sr + + | Interrupts done + +#if defined(__mcoldfire__) + movel #0xffff,d0 + movew d0,_SDL_AtariIkbd_enabled + + moveml sp@,d0-d1/a0-a1 + lea sp@(16),sp +#else + movew #0xffff,_SDL_AtariIkbd_enabled + + moveml sp@+,d0-d1/a0-a1 +#endif + rts + +/*--- Uninstall our IKBD vector ---*/ + +_SDL_AtariIkbdUninstall: + movel a0,sp@- + + | Disable interrupts + + movew #0x2700,sr + + | Restore previous MFP registers + + lea 0xfffffa00:w,a0 + + bclr #6,a0@(0x09) + tstb ikbd_ierb + beqs ikbd_restoreierb + bset #6,a0@(0x09) +ikbd_restoreierb: + + bclr #6,a0@(0x15) + tstb ikbd_imrb + beqs ikbd_restoreimrb + bset #6,a0@(0x15) +ikbd_restoreimrb: + +#if defined(__mcoldfire__) + movel old_ikbd,a0 + movel a0,0x118:w +#else + movel old_ikbd,0x118:w +#endif + + | Clear keyboard buffer + + lea 0xfffffc00:w,a0 +ikbd_videbuffer: + btst #0,a0@ + beqs ikbd_finbuffer + tstb a0@(0x02) + bras ikbd_videbuffer +ikbd_finbuffer: + + | Reenable interrupts + + movew #0x2300,sr + + movel sp@+,a0 + rts + + .bss + + .even + .comm ikbd_ierb,1 + .comm ikbd_imrb,1 + +/*--- Our custom IKBD vector ---*/ + + .text + .even + .ascii "XBRA" + .ascii "LSDL" + .comm old_ikbd,4*1 +ikbd: +#if defined(__mcoldfire__) + lea sp@(-12),sp + moveml d0-d1/a0,sp@ +#else + moveml d0-d1/a0,sp@- +#endif + + | Check if source is IKBD or MIDI +#if defined(__mcoldfire__) + moveql #0,d0 + btst d0,0xfffffc00.w +#else + btst #0,0xfffffc00.w +#endif + beqs ikbd_oldmidi + + moveb 0xfffffc02:w,d0 + + | Joystick packet ? + + cmpb #0xff,d0 + beqs ikbd_yes_joystick + + | Mouse packet ? + + cmpb #0xf8,d0 + bmis ikbd_no_mouse + cmpb #0xfc,d0 + bpls ikbd_no_mouse + + | Mouse packet, byte #1 + +ikbd_yes_mouse: +#if defined(__mcoldfire__) + andl #3,d0 +#else + andw #3,d0 +#endif + movew d0,_SDL_AtariIkbd_mouseb + +#if defined(__mcoldfire__) + movel #ikbd_mousex,d0 + movel d0,0x118:w +#else + movel #ikbd_mousex,0x118:w +#endif + bras ikbd_endit_stack + + | Joystick packet, byte #1 + +ikbd_yes_joystick: +#if defined(__mcoldfire__) + movel #ikbd_joystick,d0 + movel d0,0x118:w +#else + movel #ikbd_joystick,0x118:w +#endif + bras ikbd_endit_stack + + | Keyboard press/release + +ikbd_no_mouse: + moveb d0,d1 + lea _SDL_AtariIkbd_keyboard,a0 +#if defined(__mcoldfire__) + andl #0x7f,d1 + btst #7,d0 + spl d0 + moveb d0,a0@(0,d1:l) +#else + andw #0x7f,d1 + tas d0 + spl a0@(0,d1:w) +#endif + + | End of interrupt + +ikbd_endit_stack: +#if defined(__mcoldfire__) + moveql #6,d0 + bclr d0,0xfffffa11:w + + moveml sp@,d0-d1/a0 + lea sp@(12),sp +#else + moveml sp@+,d0-d1/a0 + + bclr #6,0xfffffa11:w +#endif + rte + + | Call old MIDI interrupt + +ikbd_oldmidi: +#if defined(__mcoldfire__) + moveml sp@,d0-d1/a0 + lea sp@(12),sp +#else + moveml sp@+,d0-d1/a0 +#endif + + movel old_ikbd,sp@- + rts + + | Mouse packet, byte #2 + +ikbd_mousex: +#if defined(__mcoldfire__) + lea sp@(-12),sp + moveml d0-d1/a0,sp@ +#else + moveml d0-d1/a0,sp@- +#endif + + | Check if source is IKBD or MIDI +#if defined(__mcoldfire__) + moveql #0,d0 + btst d0,0xfffffc00.w +#else + btst #0,0xfffffc00.w +#endif + beqs ikbd_oldmidi + + moveb 0xfffffc02:w,d0 + extw d0 +#if defined(__mcoldfire__) + movew _SDL_AtariIkbd_mousex,d1 + addl d1,d0 + movew d0,_SDL_AtariIkbd_mousex + + movel #ikbd_mousey,d0 + movel d0,0x118:w +#else + addw d0,_SDL_AtariIkbd_mousex + + movel #ikbd_mousey,0x118:w +#endif + bras ikbd_endit_stack + + | Mouse packet, byte #3 + +ikbd_mousey: +#if defined(__mcoldfire__) + lea sp@(-12),sp + moveml d0-d1/a0,sp@ +#else + moveml d0-d1/a0,sp@- +#endif + + | Check if source is IKBD or MIDI +#if defined(__mcoldfire__) + moveql #0,d0 + btst d0,0xfffffc00.w +#else + btst #0,0xfffffc00.w +#endif + beqs ikbd_oldmidi + + moveb 0xfffffc02:w,d0 + extw d0 +#if defined(__mcoldfire__) + movew _SDL_AtariIkbd_mousey,d1 + addl d1,d0 + movew d0,_SDL_AtariIkbd_mousey + + movel #ikbd,d0 + movel d0,0x118:w +#else + addw d0,_SDL_AtariIkbd_mousey + + movel #ikbd,0x118:w +#endif + bras ikbd_endit_stack + + | Joystick packet, byte #2 + +ikbd_joystick: +#if defined(__mcoldfire__) + lea sp@(-12),sp + moveml d0-d1/a0,sp@ +#else + moveml d0-d1/a0,sp@- +#endif + + | Check if source is IKBD or MIDI +#if defined(__mcoldfire__) + moveql #0,d0 + btst d0,0xfffffc00.w +#else + btst #0,0xfffffc00.w +#endif + beqs ikbd_oldmidi + +#if defined(__mcoldfire__) + moveb 0xfffffc02:w,d0 + moveb d0,_SDL_AtariIkbd_joystick+1 + + movel #ikbd,d0 + movel d0,0x118:w + + bra ikbd_endit_stack +#else + moveb 0xfffffc02:w,_SDL_AtariIkbd_joystick+1 + + movel #ikbd,0x118:w + + bras ikbd_endit_stack +#endif + + .data + + .even +_SDL_AtariIkbd_enabled: + .word 0 + + .bss + + .even + .comm _SDL_AtariIkbd_keyboard,128 + .comm _SDL_AtariIkbd_mousex,2 + .comm _SDL_AtariIkbd_mousey,2 + .comm _SDL_AtariIkbd_mouseb,2 + .comm _SDL_AtariIkbd_joystick,2 diff --git a/3rdparty/SDL/src/video/ataricommon/SDL_ikbdinterrupt_s.h b/3rdparty/SDL/src/video/ataricommon/SDL_ikbdinterrupt_s.h new file mode 100644 index 0000000..ea544bc --- /dev/null +++ b/3rdparty/SDL/src/video/ataricommon/SDL_ikbdinterrupt_s.h @@ -0,0 +1,61 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* + * Mouse vector + * + * Patrice Mandin + */ + +#ifndef _SDL_IKBDINTERRUPT_S_H_ +#define _SDL_IKBDINTERRUPT_S_H_ + +#include <mint/osbind.h> + +#include "SDL_stdinc.h" + +/* Const */ + +#define IKBD_JOY_UP (1<<0) +#define IKBD_JOY_DOWN (1<<1) +#define IKBD_JOY_LEFT (1<<2) +#define IKBD_JOY_RIGHT (1<<3) +#define IKBD_JOY_FIRE (1<<7) + +/* Variables */ + +extern volatile Uint8 SDL_AtariIkbd_keyboard[128]; /* Keyboard table */ +extern volatile Uint16 SDL_AtariIkbd_mouseb; /* Mouse on port 0, buttons */ +extern volatile Sint16 SDL_AtariIkbd_mousex; /* Mouse X relative motion */ +extern volatile Sint16 SDL_AtariIkbd_mousey; /* Mouse Y relative motion */ +extern volatile Uint16 SDL_AtariIkbd_joystick; /* Joystick on port 1 */ + +/* For joystick driver to know if this is usable */ +extern Uint16 SDL_AtariIkbd_enabled; + +/* Functions */ + +extern void SDL_AtariIkbdInstall(void); +extern void SDL_AtariIkbdUninstall(void); + +#endif /* _SDL_IKBDINTERRUPT_S_H_ */ diff --git a/3rdparty/SDL/src/video/ataricommon/SDL_xbiosevents.c b/3rdparty/SDL/src/video/ataricommon/SDL_xbiosevents.c new file mode 100644 index 0000000..232500f --- /dev/null +++ b/3rdparty/SDL/src/video/ataricommon/SDL_xbiosevents.c @@ -0,0 +1,155 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* + * XBIOS mouse & joystick vectors + * + * Patrice Mandin + */ + +#include <mint/osbind.h> + +#include "../../events/SDL_events_c.h" +#include "SDL_atarisuper.h" +#include "SDL_xbiosevents_c.h" +#include "SDL_xbiosinterrupt_s.h" + +/* Variables */ + +int SDL_AtariXbios_enabled=0; + +/* Local variables */ + +static _KBDVECS *kbdvecs; /* Pointer to access system vectors */ +static Uint16 atari_prevmouseb; /* buttons */ + +/* Functions */ + +void SDL_AtariXbios_InstallVectors(int vectors_mask) +{ + void *oldpile; + + /* Clear variables */ + SDL_AtariXbios_mouselock = + SDL_AtariXbios_mouseb = + SDL_AtariXbios_mousex = + SDL_AtariXbios_mousey = + SDL_AtariXbios_joystick = + atari_prevmouseb = 0; + + if (vectors_mask==0) { + SDL_AtariXbios_enabled=0; + return; + } + + /* Read IKBD vectors base */ + kbdvecs=Kbdvbase(); + + /* Go to supervisor mode */ + oldpile=(void *)Super(0); + + /* Install our vectors */ + SDL_AtariXbios_Install( + kbdvecs, + (vectors_mask & ATARI_XBIOS_MOUSEEVENTS) ? SDL_AtariXbios_MouseVector : NULL, + (vectors_mask & ATARI_XBIOS_JOYSTICKEVENTS) ? SDL_AtariXbios_JoystickVector : NULL + ); + + /* Back to user mode */ + SuperToUser(oldpile); + + SDL_AtariXbios_enabled=1; +} + +void SDL_AtariXbios_RestoreVectors(void) +{ + void *oldpile; + + if (SDL_AtariXbios_enabled==0) { + return; + } + + /* Read IKBD vectors base */ + kbdvecs=Kbdvbase(); + + /* Go to supervisor mode */ + oldpile=(void *)Super(NULL); + + /* Reinstall system vector */ + SDL_AtariXbios_Restore(kbdvecs); + + /* Back to user mode */ + SuperToUser(oldpile); +} + +static int atari_GetButton(int button) +{ + switch(button) + { + case 0: + return SDL_BUTTON_RIGHT; + break; + case 1: + default: + return SDL_BUTTON_LEFT; + break; + } +} + +void SDL_AtariXbios_PostMouseEvents(_THIS, SDL_bool buttonEvents) +{ + if (SDL_AtariXbios_enabled==0) { + return; + } + + /* Mouse motion ? */ + if (SDL_AtariXbios_mousex || SDL_AtariXbios_mousey) { + SDL_PrivateMouseMotion(0, 1, SDL_AtariXbios_mousex, SDL_AtariXbios_mousey); + SDL_AtariXbios_mousex = SDL_AtariXbios_mousey = 0; + } + + /* Mouse button ? */ + if (buttonEvents && (SDL_AtariXbios_mouseb != atari_prevmouseb)) { + int i; + + for (i=0;i<2;i++) { + int curbutton, prevbutton; + + curbutton = SDL_AtariXbios_mouseb & (1<<i); + prevbutton = atari_prevmouseb & (1<<i); + + if (curbutton && !prevbutton) { + SDL_PrivateMouseButton(SDL_PRESSED, atari_GetButton(i), 0, 0); + } + if (!curbutton && prevbutton) { + SDL_PrivateMouseButton(SDL_RELEASED, atari_GetButton(i), 0, 0); + } + } + atari_prevmouseb = SDL_AtariXbios_mouseb; + } +} + +void SDL_AtariXbios_LockMousePosition(SDL_bool lockPosition) +{ + SDL_AtariXbios_mouselock = lockPosition; +} diff --git a/3rdparty/SDL/src/video/ataricommon/SDL_xbiosevents_c.h b/3rdparty/SDL/src/video/ataricommon/SDL_xbiosevents_c.h new file mode 100644 index 0000000..374b062 --- /dev/null +++ b/3rdparty/SDL/src/video/ataricommon/SDL_xbiosevents_c.h @@ -0,0 +1,48 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* + * Xbios mouse & joystick vectors + * + * Patrice Mandin + */ + +#ifndef _SDL_ATARI_XBIOSEVENTS_H_ +#define _SDL_ATARI_XBIOSEVENTS_H_ + +#include "../SDL_sysvideo.h" + +/* Hidden "this" pointer for the video functions */ +#define _THIS SDL_VideoDevice *this + +#define ATARI_XBIOS_MOUSEEVENTS (1<<0) +#define ATARI_XBIOS_JOYSTICKEVENTS (1<<1) + +extern int SDL_AtariXbios_enabled; + +extern void SDL_AtariXbios_InstallVectors(int vectors_mask); +extern void SDL_AtariXbios_RestoreVectors(void); +extern void SDL_AtariXbios_PostMouseEvents(_THIS, SDL_bool buttonEvents); +extern void SDL_AtariXbios_LockMousePosition(SDL_bool lockPosition); + +#endif /* _SDL_XBIOSEVENTS_H_ */ diff --git a/3rdparty/SDL/src/video/ataricommon/SDL_xbiosinterrupt.S b/3rdparty/SDL/src/video/ataricommon/SDL_xbiosinterrupt.S new file mode 100644 index 0000000..3fc1a60 --- /dev/null +++ b/3rdparty/SDL/src/video/ataricommon/SDL_xbiosinterrupt.S @@ -0,0 +1,212 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ + +/* + * XBIOS mouse & joystick vectors + * + * Patrice Mandin + */ + + .text + + .globl _SDL_AtariXbios_Install + .globl _SDL_AtariXbios_Restore + .globl _SDL_AtariXbios_MouseVector + .globl _SDL_AtariXbios_JoystickVector + + .globl _SDL_AtariXbios_mouselock + .globl _SDL_AtariXbios_mouseb + .globl _SDL_AtariXbios_mousex + .globl _SDL_AtariXbios_mousey + .globl _SDL_AtariXbios_joystick + +/*--- Vector installer ---*/ + +_SDL_AtariXbios_Install: + movel sp@(4),a0 + + /* Stop interrupts */ + + movew #0x2700,sr + + /* Save old mouse vector, set our routine */ + + clrl oldmousevector + movel sp@(8),d0 + beqs no_new_mouse_vector +#if defined(__mcoldfire__) + movel a0@(16),d1 + movel d1,oldmousevector +#else + movel a0@(16),oldmousevector +#endif + movel d0,a0@(16) +no_new_mouse_vector: + + /* Save old joystick vector, set our routine */ + + clrl oldjoystickvector + movel sp@(12),d0 + beqs no_new_joystick_vector +#if defined(__mcoldfire__) + movel a0@(24),d1 + movel d1,oldjoystickvector +#else + movel a0@(24),oldjoystickvector +#endif + movel d0,a0@(24) +no_new_joystick_vector: + + /* Restart interrupts */ + + movew #0x2300,sr + + rts + +/*--- Vector restorer ---*/ + +_SDL_AtariXbios_Restore: + movel sp@(4),a0 + + /* Stop interrupts */ + + movew #0x2700,sr + + /* Restore mouse vector */ + + movel oldmousevector,d0 + beqs no_restore_mouse + movel d0,a0@(16) +no_restore_mouse: + + /* Restore joystick vector */ + + movel oldjoystickvector,d0 + beqs no_restore_joystick + movel d0,a0@(24) +no_restore_joystick: + + /* Restart interrupts */ + + movew #0x2300,sr + + rts + +/*--- Our mouse vector ---*/ + + .text + .even + .ascii "XBRA" + .ascii "LSDL" + .comm oldmousevector,4*1 +_SDL_AtariXbios_MouseVector: +#if defined(__mcoldfire__) + lea sp@(-8),sp + moveml d0-d1,sp@ +#else + movel d0,sp@- +#endif + + /* Mouse buttons */ + moveb (a0),d0 +#if defined(__mcoldfire__) + andl #3,d0 +#else + andw #3,d0 +#endif + movew d0,_SDL_AtariXbios_mouseb + + /* X movement */ + moveb a0@(1),d0 + extw d0 +#if defined(__mcoldfire__) + movew _SDL_AtariXbios_mousex,d1 + addl d1,d0 + movew d0,_SDL_AtariXbios_mousex +#else + addw d0,_SDL_AtariXbios_mousex +#endif + + /* Y movement */ + moveb a0@(2),d0 + extw d0 +#if defined(__mcoldfire__) + movew _SDL_AtariXbios_mousey,d1 + addl d1,d0 + movew d0,_SDL_AtariXbios_mousey +#else + addw d0,_SDL_AtariXbios_mousey +#endif + + /* Lock mouse position ? */ + tstw _SDL_AtariXbios_mouselock + beq.s no_mouse_lock + clrb a0@(1) + clrb a0@(2) +no_mouse_lock: + + /* Jump through old vector */ +#if defined(__mcoldfire__) + moveml sp@,d0-d1 + lea sp@(8),sp +#else + movel sp@+,d0 +#endif + + movel oldmousevector,sp@- + rts + + .data + .even + .comm _SDL_AtariXbios_mouselock,2*1 + .comm _SDL_AtariXbios_mousex,2*1 + .comm _SDL_AtariXbios_mousey,2*1 + .comm _SDL_AtariXbios_mouseb,2*1 + +/*--- Our joystick vector ---*/ + + .text + .even + .ascii "XBRA" + .ascii "LSDL" + .comm oldjoystickvector,4*1 +_SDL_AtariXbios_JoystickVector: + movel d0,sp@- + + /* New joystick state */ + moveb a0@(2),d0 +#if defined(__mcoldfire__) + andl #0x8f,d0 +#else + andw #0x8f,d0 +#endif + movew d0,_SDL_AtariXbios_joystick + + /* Jump through old vector */ + movel sp@+,d0 + + movel oldjoystickvector,sp@- + rts + + .data + .even + .comm _SDL_AtariXbios_joystick,2*1 diff --git a/3rdparty/SDL/src/video/ataricommon/SDL_xbiosinterrupt_s.h b/3rdparty/SDL/src/video/ataricommon/SDL_xbiosinterrupt_s.h new file mode 100644 index 0000000..dfb31c2 --- /dev/null +++ b/3rdparty/SDL/src/video/ataricommon/SDL_xbiosinterrupt_s.h @@ -0,0 +1,52 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* + * Mouse vector + * + * Patrice Mandin + */ + +#ifndef _SDL_XBIOSINTERRUPT_S_H_ +#define _SDL_XBIOSINTERRUPT_S_H_ + +#include <mint/osbind.h> + +#include "SDL_stdinc.h" + +/* Variables */ + +extern volatile Uint16 SDL_AtariXbios_mouselock; /* mouse lock position */ +extern volatile Uint16 SDL_AtariXbios_mouseb; /* buttons */ +extern volatile Sint16 SDL_AtariXbios_mousex; /* X relative motion */ +extern volatile Sint16 SDL_AtariXbios_mousey; /* Y relative motion */ +extern volatile Uint16 SDL_AtariXbios_joystick; /* Joystick */ + +/* Functions */ + +extern void SDL_AtariXbios_Install(_KBDVECS *kbdvecs,void *newmousevector,void *newjoystickvector); +extern void SDL_AtariXbios_Restore(_KBDVECS *kbdvecs); +extern void SDL_AtariXbios_MouseVector(void *buf); +extern void SDL_AtariXbios_JoystickVector(void *buf); + +#endif /* _SDL_XBIOSINTERRUPT_S_H_ */ diff --git a/3rdparty/SDL/src/video/blank_cursor.h b/3rdparty/SDL/src/video/blank_cursor.h new file mode 100644 index 0000000..db69601 --- /dev/null +++ b/3rdparty/SDL/src/video/blank_cursor.h @@ -0,0 +1,33 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ + +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * A default blank 8x8 cursor */ + +#define BLANK_CWIDTH 8 +#define BLANK_CHEIGHT 8 +#define BLANK_CHOTX 0 +#define BLANK_CHOTY 0 + +static unsigned char blank_cdata[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; +static unsigned char blank_cmask[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; + diff --git a/3rdparty/SDL/src/video/bwindow/SDL_BView.h b/3rdparty/SDL/src/video/bwindow/SDL_BView.h new file mode 100644 index 0000000..bfa2c89 --- /dev/null +++ b/3rdparty/SDL/src/video/bwindow/SDL_BView.h @@ -0,0 +1,116 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#ifndef _SDL_BView_h +#define _SDL_BView_h + +/* This is the event handling and graphics update portion of SDL_BWin */ + +extern "C" { +#include "../../events/SDL_events_c.h" +}; + +class SDL_BView : public BView +{ +public: + SDL_BView(BRect frame) : + BView(frame, "SDL View", B_FOLLOW_ALL_SIDES, + (B_WILL_DRAW|B_FRAME_EVENTS)) { + image = NULL; + xoff = yoff = 0; + SetViewColor(0,0,0,0); + SetHighColor(0,0,0,0); + } + virtual ~SDL_BView() { + SetBitmap(NULL); + } + /* Set drawing offsets for fullscreen mode */ + virtual void SetXYOffset(int x, int y) { + xoff = x; + yoff = y; + } + virtual void GetXYOffset(int &x, int &y) { + x = xoff; + y = yoff; + } + virtual void GetXYOffset(float &x, float &y) { + x = (float)xoff; + y = (float)yoff; + } + /* The view changed size. If it means we're in fullscreen, we + * draw a nice black box in the entire view to get black borders. + */ + virtual void FrameResized(float width, float height) { + BRect bounds; + bounds.top = bounds.left = 0; + bounds.right = width; + bounds.bottom = height; + /* Fill the entire view with black */ + FillRect(bounds, B_SOLID_HIGH); + /* And if there's an image, redraw it. */ + if( image ) { + bounds = image->Bounds(); + Draw(bounds); + } + } + + /* Drawing portion of this complete breakfast. :) */ + virtual void SetBitmap(BBitmap *bitmap) { + if ( image ) { + delete image; + } + image = bitmap; + } + virtual void Draw(BRect updateRect) { + if ( image ) { + if(xoff || yoff) { + BRect dest; + dest.top = updateRect.top + yoff; + dest.left = updateRect.left + xoff; + dest.bottom = updateRect.bottom + yoff; + dest.right = updateRect.right + xoff; + DrawBitmap(image, updateRect, dest); + } else { + DrawBitmap(image, updateRect, updateRect); + } + } + } + virtual void DrawAsync(BRect updateRect) { + if(xoff || yoff) { + BRect dest; + dest.top = updateRect.top + yoff; + dest.left = updateRect.left + xoff; + dest.bottom = updateRect.bottom + yoff; + dest.right = updateRect.right + xoff;; + DrawBitmapAsync(image, updateRect, dest); + } else { + DrawBitmapAsync(image, updateRect, updateRect); + } + } + +private: + BBitmap *image; + int xoff, yoff; +}; + +#endif /* _SDL_BView_h */ diff --git a/3rdparty/SDL/src/video/bwindow/SDL_BWin.h b/3rdparty/SDL/src/video/bwindow/SDL_BWin.h new file mode 100644 index 0000000..f2b19a2 --- /dev/null +++ b/3rdparty/SDL/src/video/bwindow/SDL_BWin.h @@ -0,0 +1,290 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ + +#ifndef _SDL_BWin_h +#define _SDL_BWin_h + +#include "SDL_config.h" + +#include <stdio.h> +#include <AppKit.h> +#include <InterfaceKit.h> +#include <be/game/DirectWindow.h> +#if SDL_VIDEO_OPENGL +#include "SDL_opengl.h" +#include <be/opengl/GLView.h> +#endif +#include <support/UTF8.h> + +#include "../../main/beos/SDL_BeApp.h" +#include "SDL_events.h" +#include "SDL_BView.h" + +extern "C" { +#include "../../events/SDL_events_c.h" + +extern int mouse_relative; +}; + +class SDL_BWin : public BDirectWindow +{ +public: + SDL_BWin(BRect bounds) : + BDirectWindow(bounds, "Untitled", B_TITLED_WINDOW, 0) { + last_buttons = 0; + the_view = NULL; +#if SDL_VIDEO_OPENGL + SDL_GLView = NULL; +#endif + SDL_View = NULL; + Unlock(); + shown = false; + inhibit_resize = false; + } + + virtual ~SDL_BWin() { + Lock(); + if ( the_view ) { +#if SDL_VIDEO_OPENGL + if ( the_view == SDL_GLView ) { + SDL_GLView->UnlockGL(); + } +#endif + RemoveChild(the_view); + the_view = NULL; + } + Unlock(); +#if SDL_VIDEO_OPENGL + if ( SDL_GLView ) { + delete SDL_GLView; + } +#endif + if ( SDL_View ) { + delete SDL_View; + } + } + + + /* Override the Show() method so we can tell when we've been shown */ + virtual void Show(void) { + BWindow::Show(); + shown = true; + } + virtual bool Shown(void) { + return (shown); + } + /* If called, the next resize event will not be forwarded to SDL. */ + virtual void InhibitResize(void) { + inhibit_resize=true; + } + /* Handle resizing of the window */ + virtual void FrameResized(float width, float height) { + if(inhibit_resize) + inhibit_resize = false; + else + SDL_PrivateResize((int)width, (int)height); + } + virtual int CreateView(Uint32 flags, Uint32 gl_flags) { + int retval; + + retval = 0; + Lock(); + if ( flags & SDL_OPENGL ) { +#if SDL_VIDEO_OPENGL + if ( SDL_GLView == NULL ) { + SDL_GLView = new BGLView(Bounds(), "SDL GLView", + B_FOLLOW_ALL_SIDES, (B_WILL_DRAW|B_FRAME_EVENTS), + gl_flags|BGL_DOUBLE); + SDL_GLView->EnableDirectMode(true); + } + if ( the_view != SDL_GLView ) { + if ( the_view ) { + RemoveChild(the_view); + } + AddChild(SDL_GLView); + SDL_GLView->LockGL(); + the_view = SDL_GLView; + } +#else + SDL_SetError("OpenGL support not enabled"); + retval = -1; +#endif + } else { + if ( SDL_View == NULL ) { + SDL_View = new SDL_BView(Bounds()); + } + if ( the_view != SDL_View ) { + if ( the_view ) { + RemoveChild(the_view); + } + AddChild(SDL_View); + the_view = SDL_View; + } + } +#if SDL_VIDEO_OPENGL + if ( the_view == SDL_GLView ) { + SDL_GLView->UnlockGL(); + } +#endif + Unlock(); + return(retval); + } + virtual void SetBitmap(BBitmap *bitmap) { + SDL_View->SetBitmap(bitmap); + } + virtual void SetXYOffset(int x, int y) { +#if SDL_VIDEO_OPENGL + if ( the_view == SDL_GLView ) { + return; + } +#endif + SDL_View->SetXYOffset(x, y); + } + virtual void GetXYOffset(int &x, int &y) { +#if SDL_VIDEO_OPENGL + if ( the_view == SDL_GLView ) { + x = 0; + y = 0; + return; + } +#endif + SDL_View->GetXYOffset(x, y); + } + virtual void GetXYOffset(float &x, float &y) { +#if SDL_VIDEO_OPENGL + if ( the_view == SDL_GLView ) { + x = 0.0f; + y = 0.0f; + return; + } +#endif + SDL_View->GetXYOffset(x, y); + } + virtual bool BeginDraw(void) { + return(Lock()); + } + virtual void DrawAsync(BRect updateRect) { + SDL_View->DrawAsync(updateRect); + } + virtual void EndDraw(void) { + SDL_View->Sync(); + Unlock(); + } +#if SDL_VIDEO_OPENGL + virtual void SwapBuffers(void) { + SDL_GLView->UnlockGL(); + SDL_GLView->SwapBuffers(); + SDL_GLView->LockGL(); + } +#endif + virtual BView *View(void) { + return(the_view); + } + + /* Hook functions -- overridden */ + virtual void Minimize(bool minimize) { + /* This is only called when mimimized, not when restored */ + //SDL_PrivateAppActive(minimize, SDL_APPACTIVE); + BWindow::Minimize(minimize); + } + virtual void WindowActivated(bool active) { + SDL_PrivateAppActive(active, SDL_APPINPUTFOCUS); + } + virtual bool QuitRequested(void) { + if ( SDL_BeAppActive > 0 ) { + SDL_PrivateQuit(); + /* We don't ever actually close the window here because + the application should respond to the quit request, + or ignore it as desired. + */ +#if SDL_VIDEO_OPENGL + if ( SDL_GLView != NULL ) { + SDL_GLView->EnableDirectMode(false); + } +#endif + return(false); + } + return(true); /* Close the app window */ + } + virtual void Quit() { + if (!IsLocked()) + Lock(); + BDirectWindow::Quit(); + } + + virtual int16 Translate2Unicode(const char *buf) { + int32 state, srclen, dstlen; + unsigned char destbuf[2]; + Uint16 unicode = 0; + + if ((uchar)buf[0] > 127) { + state = 0; + srclen = SDL_strlen(buf); + dstlen = sizeof(destbuf); + convert_from_utf8(B_UNICODE_CONVERSION, buf, &srclen, (char *)destbuf, &dstlen, &state); + unicode = destbuf[0]; + unicode <<= 8; + unicode |= destbuf[1]; + } else + unicode = buf[0]; + + /* For some reason function keys map to control characters */ +# define CTRL(X) ((X)-'@') + switch (unicode) { + case CTRL('A'): + case CTRL('B'): + case CTRL('C'): + case CTRL('D'): + case CTRL('E'): + case CTRL('K'): + case CTRL('L'): + case CTRL('P'): + if ( ! (SDL_GetModState() & KMOD_CTRL) ) + unicode = 0; + break; + /* Keyboard input maps newline to carriage return */ + case '\n': + unicode = '\r'; + break; + default: + break; + } + + return unicode; + } + + virtual void DispatchMessage(BMessage *msg, BHandler *target); + + virtual void DirectConnected(direct_buffer_info *info); + +private: +#if SDL_VIDEO_OPENGL + BGLView *SDL_GLView; +#endif + SDL_BView *SDL_View; + BView *the_view; + bool shown; + bool inhibit_resize; + int32 last_buttons; +}; + +#endif /* _SDL_BWin_h */ diff --git a/3rdparty/SDL/src/video/bwindow/SDL_lowvideo.h b/3rdparty/SDL/src/video/bwindow/SDL_lowvideo.h new file mode 100644 index 0000000..0513b2d --- /dev/null +++ b/3rdparty/SDL/src/video/bwindow/SDL_lowvideo.h @@ -0,0 +1,58 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#ifndef _SDL_lowvideo_h +#define _SDL_lowvideo_h + +#include "SDL_BWin.h" +#include "SDL_mouse.h" +#include "../SDL_sysvideo.h" + +/* Hidden "this" pointer for the video functions */ +#define _THIS SDL_VideoDevice *_this + +/* Private display data */ +struct SDL_PrivateVideoData { + /* The main window */ + SDL_BWin *SDL_Win; + + /* The fullscreen mode list */ + display_mode saved_mode; +#define NUM_MODELISTS 4 /* 8, 16, 24, and 32 bits-per-pixel */ + int SDL_nummodes[NUM_MODELISTS]; + SDL_Rect **SDL_modelist[NUM_MODELISTS]; + + /* A completely clear cursor */ + WMcursor *BlankCursor; + + SDL_Overlay *overlay; +}; +/* Old variable names */ +#define SDL_Win (_this->hidden->SDL_Win) +#define saved_mode (_this->hidden->saved_mode) +#define SDL_nummodes (_this->hidden->SDL_nummodes) +#define SDL_modelist (_this->hidden->SDL_modelist) +#define SDL_BlankCursor (_this->hidden->BlankCursor) +#define current_overlay (_this->hidden->overlay) + +#endif /* _SDL_lowvideo_h */ diff --git a/3rdparty/SDL/src/video/bwindow/SDL_sysevents.cc b/3rdparty/SDL/src/video/bwindow/SDL_sysevents.cc new file mode 100644 index 0000000..9e12750 --- /dev/null +++ b/3rdparty/SDL/src/video/bwindow/SDL_sysevents.cc @@ -0,0 +1,415 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#include <support/UTF8.h> +#include <stdio.h> +#include <string.h> +#include "SDL_error.h" +#include "SDL_events.h" +#include "SDL_BWin.h" +#include "SDL_lowvideo.h" + +static SDLKey keymap[128]; +int mouse_relative = 0; +extern "C" { + +#include "../../events/SDL_sysevents.h" +#include "../../events/SDL_events_c.h" +#include "SDL_sysevents_c.h" +#include "../SDL_cursor_c.h" + +void BE_PumpEvents(_THIS) +{ +} + +void BE_InitOSKeymap(_THIS) +{ + for ( uint i=0; i<SDL_TABLESIZE(keymap); ++i ) + keymap[i] = SDLK_UNKNOWN; + + keymap[0x01] = SDLK_ESCAPE; + keymap[B_F1_KEY] = SDLK_F1; + keymap[B_F2_KEY] = SDLK_F2; + keymap[B_F3_KEY] = SDLK_F3; + keymap[B_F4_KEY] = SDLK_F4; + keymap[B_F5_KEY] = SDLK_F5; + keymap[B_F6_KEY] = SDLK_F6; + keymap[B_F7_KEY] = SDLK_F7; + keymap[B_F8_KEY] = SDLK_F8; + keymap[B_F9_KEY] = SDLK_F9; + keymap[B_F10_KEY] = SDLK_F10; + keymap[B_F11_KEY] = SDLK_F11; + keymap[B_F12_KEY] = SDLK_F12; + keymap[B_PRINT_KEY] = SDLK_PRINT; + keymap[B_SCROLL_KEY] = SDLK_SCROLLOCK; + keymap[B_PAUSE_KEY] = SDLK_PAUSE; + keymap[0x11] = SDLK_BACKQUOTE; + keymap[0x12] = SDLK_1; + keymap[0x13] = SDLK_2; + keymap[0x14] = SDLK_3; + keymap[0x15] = SDLK_4; + keymap[0x16] = SDLK_5; + keymap[0x17] = SDLK_6; + keymap[0x18] = SDLK_7; + keymap[0x19] = SDLK_8; + keymap[0x1a] = SDLK_9; + keymap[0x1b] = SDLK_0; + keymap[0x1c] = SDLK_MINUS; + keymap[0x1d] = SDLK_EQUALS; + keymap[0x1e] = SDLK_BACKSPACE; + keymap[0x1f] = SDLK_INSERT; + keymap[0x20] = SDLK_HOME; + keymap[0x21] = SDLK_PAGEUP; + keymap[0x22] = SDLK_NUMLOCK; + keymap[0x23] = SDLK_KP_DIVIDE; + keymap[0x24] = SDLK_KP_MULTIPLY; + keymap[0x25] = SDLK_KP_MINUS; + keymap[0x26] = SDLK_TAB; + keymap[0x27] = SDLK_q; + keymap[0x28] = SDLK_w; + keymap[0x29] = SDLK_e; + keymap[0x2a] = SDLK_r; + keymap[0x2b] = SDLK_t; + keymap[0x2c] = SDLK_y; + keymap[0x2d] = SDLK_u; + keymap[0x2e] = SDLK_i; + keymap[0x2f] = SDLK_o; + keymap[0x30] = SDLK_p; + keymap[0x31] = SDLK_LEFTBRACKET; + keymap[0x32] = SDLK_RIGHTBRACKET; + keymap[0x33] = SDLK_BACKSLASH; + keymap[0x34] = SDLK_DELETE; + keymap[0x35] = SDLK_END; + keymap[0x36] = SDLK_PAGEDOWN; + keymap[0x37] = SDLK_KP7; + keymap[0x38] = SDLK_KP8; + keymap[0x39] = SDLK_KP9; + keymap[0x3a] = SDLK_KP_PLUS; + keymap[0x3b] = SDLK_CAPSLOCK; + keymap[0x3c] = SDLK_a; + keymap[0x3d] = SDLK_s; + keymap[0x3e] = SDLK_d; + keymap[0x3f] = SDLK_f; + keymap[0x40] = SDLK_g; + keymap[0x41] = SDLK_h; + keymap[0x42] = SDLK_j; + keymap[0x43] = SDLK_k; + keymap[0x44] = SDLK_l; + keymap[0x45] = SDLK_SEMICOLON; + keymap[0x46] = SDLK_QUOTE; + keymap[0x47] = SDLK_RETURN; + keymap[0x48] = SDLK_KP4; + keymap[0x49] = SDLK_KP5; + keymap[0x4a] = SDLK_KP6; + keymap[0x4b] = SDLK_LSHIFT; + keymap[0x4c] = SDLK_z; + keymap[0x4d] = SDLK_x; + keymap[0x4e] = SDLK_c; + keymap[0x4f] = SDLK_v; + keymap[0x50] = SDLK_b; + keymap[0x51] = SDLK_n; + keymap[0x52] = SDLK_m; + keymap[0x53] = SDLK_COMMA; + keymap[0x54] = SDLK_PERIOD; + keymap[0x55] = SDLK_SLASH; + keymap[0x56] = SDLK_RSHIFT; + keymap[0x57] = SDLK_UP; + keymap[0x58] = SDLK_KP1; + keymap[0x59] = SDLK_KP2; + keymap[0x5a] = SDLK_KP3; + keymap[0x5b] = SDLK_KP_ENTER; + keymap[0x5c] = SDLK_LCTRL; + keymap[0x5d] = SDLK_LALT; + keymap[0x5e] = SDLK_SPACE; + keymap[0x5f] = SDLK_RALT; + keymap[0x60] = SDLK_RCTRL; + keymap[0x61] = SDLK_LEFT; + keymap[0x62] = SDLK_DOWN; + keymap[0x63] = SDLK_RIGHT; + keymap[0x64] = SDLK_KP0; + keymap[0x65] = SDLK_KP_PERIOD; + keymap[0x66] = SDLK_LMETA; + keymap[0x67] = SDLK_RMETA; + keymap[0x68] = SDLK_MENU; + keymap[0x69] = SDLK_EURO; + keymap[0x6a] = SDLK_KP_EQUALS; + keymap[0x6b] = SDLK_POWER; +} + +}; /* Extern C */ + +void SDL_BWin::DispatchMessage(BMessage *msg, BHandler *target) +{ + switch (msg->what) { + case B_MOUSE_MOVED: + { + SDL_VideoDevice *view = current_video; + BPoint where; + int32 transit; + if (msg->FindPoint("where", &where) == B_OK && msg->FindInt32("be:transit", &transit) == B_OK) { + int x, y; + + GetXYOffset(x, y); + x = (int)where.x - x; + y = (int)where.y - y; + + //BeSman: I need another method for cursor catching !!! + if (view->input_grab != SDL_GRAB_OFF) + { + bool clipped = false; + if ( x < 0 ) { + x = 0; + clipped = true; + } else if ( x >= SDL_VideoSurface->w ) { + x = (SDL_VideoSurface->w-1); + clipped = true; + } + if ( y < 0 ) { + y = 0; + clipped = true; + } else if ( y >= SDL_VideoSurface->h ) { + y = (SDL_VideoSurface->h-1); + clipped = true; + } + if ( clipped ) { + BPoint edge; + GetXYOffset(edge.x, edge.y); + edge.x += x; + edge.y += y; + ConvertToScreen(&edge); + set_mouse_position((int)edge.x, (int)edge.y); + } + transit = B_INSIDE_VIEW; + } + if (transit == B_EXITED_VIEW) { + if ( SDL_GetAppState() & SDL_APPMOUSEFOCUS ) { + SDL_PrivateAppActive(0, SDL_APPMOUSEFOCUS); +#if SDL_VIDEO_OPENGL + // for some reason, SDL_EraseCursor fails for OpenGL + if (this->the_view != this->SDL_GLView) +#endif + SDL_EraseCursor(SDL_VideoSurface); + be_app->SetCursor(B_HAND_CURSOR); + } + } else { + if ( !(SDL_GetAppState() & SDL_APPMOUSEFOCUS) ) { + SDL_PrivateAppActive(1, SDL_APPMOUSEFOCUS); +#if SDL_VIDEO_OPENGL + // for some reason, SDL_EraseCursor fails for OpenGL + if (this->the_view != this->SDL_GLView) +#endif + SDL_EraseCursor(SDL_VideoSurface); + SDL_SetCursor(NULL); + } + + if ( mouse_relative ) { + int half_w = (SDL_VideoSurface->w/2); + int half_h = (SDL_VideoSurface->h/2); + x -= half_w; + y -= half_h; + if ( x || y ) { + BPoint center; + GetXYOffset(center.x, center.y); + center.x += half_w; + center.y += half_h; + ConvertToScreen(¢er); + set_mouse_position((int)center.x, (int)center.y); + SDL_PrivateMouseMotion(0, 1, x, y); + } + } else { + SDL_PrivateMouseMotion(0, 0, x, y); + } + } + } + break; + } + + case B_MOUSE_DOWN: + { + /* it looks like mouse down is send only for first clicked + button, each next is not send while last one is holded */ + int32 buttons; + int sdl_buttons = 0; + if (msg->FindInt32("buttons", &buttons) == B_OK) { + /* Add any mouse button events */ + if (buttons & B_PRIMARY_MOUSE_BUTTON) { + sdl_buttons |= SDL_BUTTON_LEFT; + } + if (buttons & B_SECONDARY_MOUSE_BUTTON) { + sdl_buttons |= SDL_BUTTON_RIGHT; + } + if (buttons & B_TERTIARY_MOUSE_BUTTON) { + sdl_buttons |= SDL_BUTTON_MIDDLE; + } + SDL_PrivateMouseButton(SDL_PRESSED, sdl_buttons, 0, 0); + + last_buttons = buttons; + } + break; + } + + case B_MOUSE_UP: + { + /* mouse up doesn't give which button was released, + only state of buttons (after release, so it's always = 0), + which is not what we need ;] + So we need to store button in mouse down, and restore + in mouse up :( + mouse up is (similarly to mouse down) send only for + first button down (ie. it's no send if we click another button + without releasing previous one first) - but that's probably + because of how drivers are written?, not BeOS itself. */ + int32 buttons; + int sdl_buttons = 0; + if (msg->FindInt32("buttons", &buttons) == B_OK) { + /* Add any mouse button events */ + if ((buttons ^ B_PRIMARY_MOUSE_BUTTON) & last_buttons) { + sdl_buttons |= SDL_BUTTON_LEFT; + } + if ((buttons ^ B_SECONDARY_MOUSE_BUTTON) & last_buttons) { + sdl_buttons |= SDL_BUTTON_RIGHT; + } + if ((buttons ^ B_TERTIARY_MOUSE_BUTTON) & last_buttons) { + sdl_buttons |= SDL_BUTTON_MIDDLE; + } + SDL_PrivateMouseButton(SDL_RELEASED, sdl_buttons, 0, 0); + + last_buttons = buttons; + } + break; + } + + case B_MOUSE_WHEEL_CHANGED: + { + float x, y; + x = y = 0; + if (msg->FindFloat("be:wheel_delta_x", &x) == B_OK && msg->FindFloat("be:wheel_delta_y", &y) == B_OK) { + if (x < 0 || y < 0) { + SDL_PrivateMouseButton(SDL_PRESSED, SDL_BUTTON_WHEELDOWN, 0, 0); + SDL_PrivateMouseButton(SDL_RELEASED, SDL_BUTTON_WHEELDOWN, 0, 0); + } else if (x > 0 || y > 0) { + SDL_PrivateMouseButton(SDL_PRESSED, SDL_BUTTON_WHEELUP, 0, 0); + SDL_PrivateMouseButton(SDL_RELEASED, SDL_BUTTON_WHEELUP, 0, 0); + } + } + break; + } + + case B_KEY_DOWN: + case B_UNMAPPED_KEY_DOWN: /* modifier keys are unmapped */ + { + int32 key; + int32 modifiers; + int32 key_repeat; + /* Workaround for SDL message queue being filled too fast because of BeOS own key-repeat mechanism */ + if (msg->FindInt32("be:key_repeat", &key_repeat) == B_OK && key_repeat > 0) + break; + + if (msg->FindInt32("key", &key) == B_OK && msg->FindInt32("modifiers", &modifiers) == B_OK) { + SDL_keysym keysym; + keysym.scancode = key; + if (key < 128) { + keysym.sym = keymap[key]; + } else { + keysym.sym = SDLK_UNKNOWN; + } + /* FIX THIS? + it seems SDL_PrivateKeyboard() changes mod value + anyway, and doesn't care about what we setup here */ + keysym.mod = KMOD_NONE; + keysym.unicode = 0; + if (SDL_TranslateUNICODE) { + const char *bytes; + if (msg->FindString("bytes", &bytes) == B_OK) { + /* FIX THIS? + this cares only about first "letter", + so if someone maps some key to print + "BeOS rulez!" only "B" will be used. */ + keysym.unicode = Translate2Unicode(bytes); + } + } + SDL_PrivateKeyboard(SDL_PRESSED, &keysym); + } + break; + } + + case B_KEY_UP: + case B_UNMAPPED_KEY_UP: /* modifier keys are unmapped */ + { + int32 key; + int32 modifiers; + if (msg->FindInt32("key", &key) == B_OK && msg->FindInt32("modifiers", &modifiers) == B_OK) { + SDL_keysym keysym; + keysym.scancode = key; + if (key < 128) { + keysym.sym = keymap[key]; + } else { + keysym.sym = SDLK_UNKNOWN; + } + keysym.mod = KMOD_NONE; /* FIX THIS? */ + keysym.unicode = 0; + if (SDL_TranslateUNICODE) { + const char *bytes; + if (msg->FindString("bytes", &bytes) == B_OK) { + keysym.unicode = Translate2Unicode(bytes); + } + } + SDL_PrivateKeyboard(SDL_RELEASED, &keysym); + } + break; + } + + default: + /* move it after switch{} so it's always handled + that way we keep BeOS feautures like: + - CTRL+Q to close window (and other shortcuts) + - PrintScreen to make screenshot into /boot/home + - etc.. */ + //BDirectWindow::DispatchMessage(msg, target); + break; + } + BDirectWindow::DispatchMessage(msg, target); +} + +void SDL_BWin::DirectConnected(direct_buffer_info *info) { + switch (info->buffer_state & B_DIRECT_MODE_MASK) { + case B_DIRECT_START: + case B_DIRECT_MODIFY: + { + int32 width = info->window_bounds.right - + info->window_bounds.left; + int32 height = info->window_bounds.bottom - + info->window_bounds.top; + SDL_PrivateResize(width, height); + break; + } + default: + break; + } +#if SDL_VIDEO_OPENGL + // If it is a BGLView, it is apparently required to + // call DirectConnected() on it as well + if (this->the_view == this->SDL_GLView) + this->SDL_GLView->DirectConnected(info); +#endif +} diff --git a/3rdparty/SDL/src/video/bwindow/SDL_sysevents_c.h b/3rdparty/SDL/src/video/bwindow/SDL_sysevents_c.h new file mode 100644 index 0000000..70c5535 --- /dev/null +++ b/3rdparty/SDL/src/video/bwindow/SDL_sysevents_c.h @@ -0,0 +1,31 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#include "SDL_lowvideo.h" + +/* Variables and functions exported by SDL_sysevents.c to other parts + of the native video subsystem (SDL_sysvideo.c) +*/ + +extern void BE_InitOSKeymap(_THIS); +extern void BE_PumpEvents(_THIS); diff --git a/3rdparty/SDL/src/video/bwindow/SDL_sysmouse.cc b/3rdparty/SDL/src/video/bwindow/SDL_sysmouse.cc new file mode 100644 index 0000000..9a557d6 --- /dev/null +++ b/3rdparty/SDL/src/video/bwindow/SDL_sysmouse.cc @@ -0,0 +1,153 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#include <AppKit.h> +#include <GameKit.h> + +#include "SDL_BWin.h" + +extern "C" { +#include "../SDL_cursor_c.h" +#include "SDL_sysmouse_c.h" + +/* Convert bits to padded bytes */ +#define PADDED_BITS(bits) ((bits+7)/8) + +/* The implementation dependent data for the window manager cursor */ +struct WMcursor { + char *bits; +}; + +/* Can this be done in the BeOS? */ +WMcursor *BE_CreateWMCursor(_THIS, + Uint8 *data, Uint8 *mask, int w, int h, int hot_x, int hot_y) +{ + WMcursor *cursor; + int allowed_x; + int allowed_y; + int run, pad, i; + char *cptr; + + allowed_x = 16; /* BeOS limitation */ + allowed_y = 16; /* BeOS limitation */ + if ( (w > allowed_x) || (h > allowed_y) ) { + SDL_SetError("Only cursors of dimension (%dx%d) are allowed", + allowed_x, allowed_y); + return(NULL); + } + + /* Allocate the cursor */ + cursor = (WMcursor *)SDL_malloc(sizeof(WMcursor)); + if ( cursor == NULL ) { + SDL_OutOfMemory(); + return(NULL); + } + cursor->bits = (char *)SDL_malloc(4+2*((allowed_x/8)*allowed_y)); + if ( cursor->bits == NULL ) { + SDL_free(cursor); + SDL_OutOfMemory(); + return(NULL); + } + cursor->bits[0] = allowed_y; /* Size of the cursor */ + cursor->bits[1] = 1; /* Bit depth of cursor */ + cursor->bits[2] = hot_y; + cursor->bits[3] = hot_x; + cptr = &cursor->bits[4]; + + /* Pad out to the normal cursor size */ + run = PADDED_BITS(w); + pad = PADDED_BITS(allowed_x)-run; + for ( i=0; i<h; ++i ) { + SDL_memcpy(cptr, data, run); + SDL_memset(cptr+run, 0, pad); + data += run; + cptr += (run+pad); + } + for ( ; i<allowed_y; ++i ) { + SDL_memset(cptr, 0, run+pad); + cptr += (run+pad); + } + for ( i=0; i<h; ++i ) { + /* FIXME: The mask should be OR'd with the data to turn + inverted color pixels black, since inverted color pixels + aren't supported under BeOS. + */ + SDL_memcpy(cptr, mask, run); + SDL_memset(cptr+run, 0, pad); + mask += run; + cptr += (run+pad); + } + for ( ; i<allowed_y; ++i ) { + SDL_memset(cptr, 0, run+pad); + cptr += (run+pad); + } + return(cursor); +} + +int BE_ShowWMCursor(_THIS, WMcursor *cursor) +{ + if ( be_app->Lock() ) { + if ( cursor == NULL ) { + if ( SDL_BlankCursor != NULL ) { + be_app->SetCursor(SDL_BlankCursor->bits); + } + } else { + be_app->SetCursor(cursor->bits); + } + be_app->Unlock(); + } + return(1); +} + +void BE_FreeWMCursor(_THIS, WMcursor *cursor) +{ + SDL_free(cursor->bits); + SDL_free(cursor); +} + +/* Implementation by Christian Bauer <cbauer@student.physik.uni-mainz.de> */ +void BE_WarpWMCursor(_THIS, Uint16 x, Uint16 y) +{ + BPoint pt; + SDL_Win->GetXYOffset(pt.x, pt.y); + pt.x += x; + pt.y += y; + SDL_Win->Lock(); + SDL_Win->ConvertToScreen(&pt); + SDL_Win->Unlock(); + set_mouse_position((int32)pt.x, (int32)pt.y); +} + +/* Check to see if we need to enter or leave mouse relative mode */ +void BE_CheckMouseMode(_THIS) +{ + /* If the mouse is hidden and input is grabbed, we use relative mode */ + if ( !(SDL_cursorstate & CURSOR_VISIBLE) && + (_this->input_grab != SDL_GRAB_OFF) ) { + mouse_relative = 1; + } else { + mouse_relative = 0; + } +} + +}; /* Extern C */ diff --git a/3rdparty/SDL/src/video/bwindow/SDL_sysmouse_c.h b/3rdparty/SDL/src/video/bwindow/SDL_sysmouse_c.h new file mode 100644 index 0000000..70b3b2a --- /dev/null +++ b/3rdparty/SDL/src/video/bwindow/SDL_sysmouse_c.h @@ -0,0 +1,33 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#include "SDL_lowvideo.h" + +/* Functions to be exported */ +extern void BE_FreeWMCursor(_THIS, WMcursor *cursor); +extern WMcursor *BE_CreateWMCursor(_THIS, + Uint8 *data, Uint8 *mask, int w, int h, int hot_x, int hot_y); +extern int BE_ShowWMCursor(_THIS, WMcursor *cursor); +extern void BE_WarpWMCursor(_THIS, Uint16 x, Uint16 y); +extern void BE_CheckMouseMode(_THIS); + diff --git a/3rdparty/SDL/src/video/bwindow/SDL_sysvideo.cc b/3rdparty/SDL/src/video/bwindow/SDL_sysvideo.cc new file mode 100644 index 0000000..c32b661 --- /dev/null +++ b/3rdparty/SDL/src/video/bwindow/SDL_sysvideo.cc @@ -0,0 +1,841 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* BWindow based framebuffer implementation */ + +#include <unistd.h> + +#include "SDL_BWin.h" +#include "SDL_timer.h" + +extern "C" { + +#include "../SDL_sysvideo.h" +#include "../../events/SDL_events_c.h" +#include "SDL_sysevents_c.h" +#include "SDL_sysmouse_c.h" +#include "SDL_syswm_c.h" +#include "SDL_lowvideo.h" +#include "../SDL_yuvfuncs.h" +#include "SDL_sysyuv.h" +#include "../blank_cursor.h" + +#define BEOS_HIDDEN_SIZE 32 /* starting hidden window size */ + +/* Initialization/Query functions */ +static int BE_VideoInit(_THIS, SDL_PixelFormat *vformat); +static SDL_Rect **BE_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags); +static SDL_Surface *BE_SetVideoMode(_THIS, SDL_Surface *current, int width, int height, int bpp, Uint32 flags); +static void BE_UpdateMouse(_THIS); +static int BE_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors); +static void BE_VideoQuit(_THIS); + +/* Hardware surface functions */ +static int BE_AllocHWSurface(_THIS, SDL_Surface *surface); +static int BE_LockHWSurface(_THIS, SDL_Surface *surface); +static void BE_UnlockHWSurface(_THIS, SDL_Surface *surface); +static void BE_FreeHWSurface(_THIS, SDL_Surface *surface); + +static int BE_ToggleFullScreen(_THIS, int fullscreen); + +/* OpenGL functions */ +#if SDL_VIDEO_OPENGL +static int BE_GL_LoadLibrary(_THIS, const char *path); +static void* BE_GL_GetProcAddress(_THIS, const char *proc); +static int BE_GL_GetAttribute(_THIS, SDL_GLattr attrib, int* value); +static int BE_GL_MakeCurrent(_THIS); +static void BE_GL_SwapBuffers(_THIS); +#endif + +/* FB driver bootstrap functions */ + +static int BE_Available(void) +{ + return(1); +} + +static void BE_DeleteDevice(SDL_VideoDevice *device) +{ + SDL_free(device->hidden); + SDL_free(device); +} + +static SDL_VideoDevice *BE_CreateDevice(int devindex) +{ + SDL_VideoDevice *device; + + /* Initialize all variables that we clean on shutdown */ + device = (SDL_VideoDevice *)SDL_malloc(sizeof(SDL_VideoDevice)); + if ( device ) { + SDL_memset(device, 0, (sizeof *device)); + device->hidden = (struct SDL_PrivateVideoData *) + SDL_malloc((sizeof *device->hidden)); + } + if ( (device == NULL) || (device->hidden == NULL) ) { + SDL_OutOfMemory(); + if ( device ) { + SDL_free(device); + } + return(0); + } + SDL_memset(device->hidden, 0, (sizeof *device->hidden)); + + /* Set the function pointers */ + /* Initialization/Query functions */ + device->VideoInit = BE_VideoInit; + device->ListModes = BE_ListModes; + device->SetVideoMode = BE_SetVideoMode; + device->ToggleFullScreen = BE_ToggleFullScreen; + device->UpdateMouse = BE_UpdateMouse; + device->CreateYUVOverlay = BE_CreateYUVOverlay; + device->SetColors = BE_SetColors; + device->UpdateRects = NULL; + device->VideoQuit = BE_VideoQuit; + /* Hardware acceleration functions */ + device->AllocHWSurface = BE_AllocHWSurface; + device->CheckHWBlit = NULL; + device->FillHWRect = NULL; + device->SetHWColorKey = NULL; + device->SetHWAlpha = NULL; + device->LockHWSurface = BE_LockHWSurface; + device->UnlockHWSurface = BE_UnlockHWSurface; + device->FlipHWSurface = NULL; + device->FreeHWSurface = BE_FreeHWSurface; + /* Gamma support */ +#if SDL_VIDEO_OPENGL + /* OpenGL support */ + device->GL_LoadLibrary = BE_GL_LoadLibrary; + device->GL_GetProcAddress = BE_GL_GetProcAddress; + device->GL_GetAttribute = BE_GL_GetAttribute; + device->GL_MakeCurrent = BE_GL_MakeCurrent; + device->GL_SwapBuffers = BE_GL_SwapBuffers; +#endif + /* Window manager functions */ + device->SetCaption = BE_SetWMCaption; + device->SetIcon = NULL; + device->IconifyWindow = BE_IconifyWindow; + device->GrabInput = BE_GrabInput; + device->GetWMInfo = BE_GetWMInfo; + /* Cursor manager functions */ + device->FreeWMCursor = BE_FreeWMCursor; + device->CreateWMCursor = BE_CreateWMCursor; + device->ShowWMCursor = BE_ShowWMCursor; + device->WarpWMCursor = BE_WarpWMCursor; + device->MoveWMCursor = NULL; + device->CheckMouseMode = BE_CheckMouseMode; + /* Event manager functions */ + device->InitOSKeymap = BE_InitOSKeymap; + device->PumpEvents = BE_PumpEvents; + + device->free = BE_DeleteDevice; + + /* Set the driver flags */ + device->handles_any_size = 1; + + return device; +} + +VideoBootStrap BWINDOW_bootstrap = { + "bwindow", "BDirectWindow graphics", + BE_Available, BE_CreateDevice +}; + +static inline int ColorSpaceToBitsPerPixel(uint32 colorspace) +{ + int bitsperpixel; + + bitsperpixel = 0; + switch (colorspace) { + case B_CMAP8: + bitsperpixel = 8; + break; + case B_RGB15: + case B_RGBA15: + case B_RGB15_BIG: + case B_RGBA15_BIG: + bitsperpixel = 15; + break; + case B_RGB16: + case B_RGB16_BIG: + bitsperpixel = 16; + break; + case B_RGB32: + case B_RGBA32: + case B_RGB32_BIG: + case B_RGBA32_BIG: + bitsperpixel = 32; + break; + default: + break; + } + return(bitsperpixel); +} + +/* Function to sort the display_list in bscreen */ +static int CompareModes(const void *A, const void *B) +{ + const display_mode *a = (display_mode *)A; + const display_mode *b = (display_mode *)B; + + if ( a->space == b->space ) { + return((b->virtual_width*b->virtual_height)- + (a->virtual_width*a->virtual_height)); + } else { + return(ColorSpaceToBitsPerPixel(b->space)- + ColorSpaceToBitsPerPixel(a->space)); + } +} + +/* Yes, this isn't the fastest it could be, but it works nicely */ +static int BE_AddMode(_THIS, int index, unsigned int w, unsigned int h) +{ + SDL_Rect *mode; + int i; + int next_mode; + + /* Check to see if we already have this mode */ + if ( SDL_nummodes[index] > 0 ) { + for ( i=SDL_nummodes[index]-1; i >= 0; --i ) { + mode = SDL_modelist[index][i]; + if ( (mode->w == w) && (mode->h == h) ) { +#ifdef BWINDOW_DEBUG + fprintf(stderr, "We already have mode %dx%d at %d bytes per pixel\n", w, h, index+1); +#endif + return(0); + } + } + } + + /* Set up the new video mode rectangle */ + mode = (SDL_Rect *)SDL_malloc(sizeof *mode); + if ( mode == NULL ) { + SDL_OutOfMemory(); + return(-1); + } + mode->x = 0; + mode->y = 0; + mode->w = w; + mode->h = h; +#ifdef BWINDOW_DEBUG + fprintf(stderr, "Adding mode %dx%d at %d bytes per pixel\n", w, h, index+1); +#endif + + /* Allocate the new list of modes, and fill in the new mode */ + next_mode = SDL_nummodes[index]; + SDL_modelist[index] = (SDL_Rect **) + SDL_realloc(SDL_modelist[index], (1+next_mode+1)*sizeof(SDL_Rect *)); + if ( SDL_modelist[index] == NULL ) { + SDL_OutOfMemory(); + SDL_nummodes[index] = 0; + SDL_free(mode); + return(-1); + } + SDL_modelist[index][next_mode] = mode; + SDL_modelist[index][next_mode+1] = NULL; + SDL_nummodes[index]++; + + return(0); +} + +int BE_VideoInit(_THIS, SDL_PixelFormat *vformat) +{ + display_mode *modes; + uint32 i, nmodes; + int bpp; + BRect bounds; + + /* Initialize the Be Application for appserver interaction */ + if ( SDL_InitBeApp() < 0 ) { + return(-1); + } + + /* It is important that this be created after SDL_InitBeApp() */ + BScreen bscreen; + + /* Save the current display mode */ + bscreen.GetMode(&saved_mode); + _this->info.current_w = saved_mode.virtual_width; + _this->info.current_h = saved_mode.virtual_height; + + /* Determine the screen depth */ + vformat->BitsPerPixel = ColorSpaceToBitsPerPixel(bscreen.ColorSpace()); + if ( vformat->BitsPerPixel == 0 ) { + SDL_SetError("Unknown BScreen colorspace: 0x%x", + bscreen.ColorSpace()); + return(-1); + } + + /* Get the video modes we can switch to in fullscreen mode */ + bscreen.GetModeList(&modes, &nmodes); + SDL_qsort(modes, nmodes, sizeof *modes, CompareModes); + for ( i=0; i<nmodes; ++i ) { + bpp = ColorSpaceToBitsPerPixel(modes[i].space); + //if ( bpp != 0 ) { // There are bugs in changing colorspace + if ( modes[i].space == saved_mode.space ) { + BE_AddMode(_this, ((bpp+7)/8)-1, + modes[i].virtual_width, + modes[i].virtual_height); + } + } + + /* Create the window and view */ + bounds.top = 0; bounds.left = 0; + bounds.right = BEOS_HIDDEN_SIZE; + bounds.bottom = BEOS_HIDDEN_SIZE; + SDL_Win = new SDL_BWin(bounds); + +#if SDL_VIDEO_OPENGL + /* testgl application doesn't load library, just tries to load symbols */ + /* is it correct? if so we have to load library here */ + BE_GL_LoadLibrary(_this, NULL); +#endif + + /* Create the clear cursor */ + SDL_BlankCursor = BE_CreateWMCursor(_this, blank_cdata, blank_cmask, + BLANK_CWIDTH, BLANK_CHEIGHT, BLANK_CHOTX, BLANK_CHOTY); + + /* Fill in some window manager capabilities */ + _this->info.wm_available = 1; + + /* We're done! */ + return(0); +} + +/* We support any dimension at our bit-depth */ +SDL_Rect **BE_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags) +{ + SDL_Rect **modes; + + modes = ((SDL_Rect **)0); + if ( (flags & SDL_FULLSCREEN) == SDL_FULLSCREEN ) { + modes = SDL_modelist[((format->BitsPerPixel+7)/8)-1]; + } else { + if ( format->BitsPerPixel == + _this->screen->format->BitsPerPixel ) { + modes = ((SDL_Rect **)-1); + } + } + return(modes); +} + +/* Various screen update functions available */ +static void BE_NormalUpdate(_THIS, int numrects, SDL_Rect *rects); + + +/* Find the closest display mode for fullscreen */ +static bool BE_FindClosestFSMode(_THIS, int width, int height, int bpp, + display_mode *mode) +{ + BScreen bscreen; + uint32 i, nmodes; + SDL_Rect **modes; + display_mode *dmodes; + display_mode current; + float current_refresh; + bscreen.GetMode(¤t); + current_refresh = (1000 * current.timing.pixel_clock) / + (current.timing.h_total * current.timing.v_total); + + modes = SDL_modelist[((bpp+7)/8)-1]; + + // find end of list (lowest-resolution mode; modes are ordered + // highest-to-lowest). + i = 0; while(modes[i]) i++; + if (!i) return false; // what? no modes at all? + + // find first mode with resolution >= requested in both dimensions + for (--i; i >= 0; --i) + { + if (modes[i]->w >= width && modes[i]->h >= height) + break; + } + + // unable to find any mode with that high a resolution! + if (i < 0) + return false; + + width = modes[i]->w; + height = modes[i]->h; + + bscreen.GetModeList(&dmodes, &nmodes); + for ( i = 0; i < nmodes; ++i ) { + if ( (bpp == ColorSpaceToBitsPerPixel(dmodes[i].space)) && + (width == dmodes[i].virtual_width) && + (height == dmodes[i].virtual_height) ) { + break; + } + } + if ( i != nmodes ) { + *mode = dmodes[i]; + if ((mode->virtual_width <= current.virtual_width) && + (mode->virtual_height <= current.virtual_height)) { + float new_refresh = (1000 * mode->timing.pixel_clock) / + (mode->timing.h_total * mode->timing.v_total); + if (new_refresh < current_refresh) { + mode->timing.pixel_clock = (uint32)((mode->timing.h_total * mode->timing.v_total) + * current_refresh / 1000); + } + } + return true; + } else { + return false; + } +} + +static int BE_SetFullScreen(_THIS, SDL_Surface *screen, int fullscreen) +{ + // printf("SetFullScreen(%d)\n", fullscreen); + BScreen bscreen; + + // SetFullSscreen() does not work as expected if called in a window + // that was never shown. This is probably a bug in the Haiku Game Kit that needs + // to be investigated. + if (SDL_Win->Lock()) { + // Show our window. + SDL_Win->Show(); + } + + if (SDL_Win->IsLocked()) { + // Unlock the window if it was locked. This is needed as only the + // first call to Show() unlocks the looper. All other calls to it + // will not. + SDL_Win->Unlock(); + } + + int width = screen->w; + int height = screen->h; + + if (fullscreen) { + // Set resolution to the closest available one that matches the + // current SDL resolution. + display_mode mode; + bscreen.GetMode(&mode); + + int bpp = screen->format->BitsPerPixel; + if (bpp != ColorSpaceToBitsPerPixel(mode.space) || + width != mode.virtual_width || height != mode.virtual_height) { + if(BE_FindClosestFSMode(_this, width, height, bpp, &mode)) { + bscreen.SetMode(&mode); + } else { + // printf("Could not set new mode.\n"); + return(0); + } + } + } else { + // Reset to the previous known resolution as we are now in window + // mode. + bscreen.SetMode(&saved_mode); + } + + // Effectivelly set/reset full screen mode. If we are already in + // full screen mode, we reset back to windowed mode first so the + // window can resize when going fullscreen. + // if (fullscreen) + // printf("Going fullscreen\n"); + // else + // printf("Going windowed\n"); + SDL_Win->SetFullScreen(fullscreen); + + // Calculate offsets for centering the window (in window mode) and for + // dentering the bitmap (in full screen mode). + BRect bounds = bscreen.Frame(); + bounds.PrintToStream(); + int32 cx = (bounds.IntegerWidth() - width)/2; + int32 cy = (bounds.IntegerHeight() - height)/2; + + // printf ("cx = %d, cy = %d\n", cx, cy); + if (!SDL_Win->IsFullScreen()) { + // printf("Doing not fullscreen stuff.\n"); + // We are not in full screen mode, so we want to change the window + // size to match the resolution in SDL. + SDL_Win->ResizeTo(width, height); + + // And also center the window and reset the drawing offset. + SDL_Win->MoveTo(cx, cy); + SDL_Win->SetXYOffset(0, 0); + } else { + // printf("Doing fullscreen stuff."); + // Center the bitmap whenever we are in full screen mode. + SDL_Win->SetXYOffset(cx, cy); + } + + // Set relevant internal SDL screen flags. + if (SDL_Win->IsFullScreen()) { + screen->flags |= SDL_FULLSCREEN; + } else { + screen->flags &= ~SDL_FULLSCREEN; + } + + return(1); +} + +static int BE_ToggleFullScreen(_THIS, int fullscreen) +{ + return BE_SetFullScreen(_this, _this->screen, fullscreen); +} + +/* FIXME: check return values and cleanup here */ +SDL_Surface *BE_SetVideoMode(_THIS, SDL_Surface *current, + int width, int height, int bpp, Uint32 flags) +{ + BScreen bscreen; + BBitmap *bbitmap; + BRect bounds; + Uint32 gl_flags = 0; + + /* Only RGB works on r5 currently */ + gl_flags = BGL_RGB; + if (_this->gl_config.double_buffer) + gl_flags |= BGL_DOUBLE; + else + gl_flags |= BGL_SINGLE; + if (_this->gl_config.alpha_size > 0 || bpp == 32) + gl_flags |= BGL_ALPHA; + if (_this->gl_config.depth_size > 0) + gl_flags |= BGL_DEPTH; + if (_this->gl_config.stencil_size > 0) + gl_flags |= BGL_STENCIL; + if (_this->gl_config.accum_red_size > 0 + || _this->gl_config.accum_green_size > 0 + || _this->gl_config.accum_blue_size > 0 + || _this->gl_config.accum_alpha_size > 0) + gl_flags |= BGL_ACCUM; + + /* Create the view for this window, using found flags */ + if ( SDL_Win->CreateView(flags, gl_flags) < 0 ) { + return(NULL); + } + + current->flags = 0; /* Clear flags */ + current->w = width; + current->h = height; + SDL_Win->SetType(B_TITLED_WINDOW); + if ( flags & SDL_NOFRAME ) { + current->flags |= SDL_NOFRAME; + SDL_Win->SetLook(B_NO_BORDER_WINDOW_LOOK); + } else { + if ( (flags & SDL_RESIZABLE) && !(flags & SDL_OPENGL) ) { + current->flags |= SDL_RESIZABLE; + /* We don't want opaque resizing (TM). :-) */ + SDL_Win->SetFlags(B_OUTLINE_RESIZE); + } else { + SDL_Win->SetFlags(B_NOT_RESIZABLE|B_NOT_ZOOMABLE); + } + } + + if ( flags & SDL_OPENGL ) { + current->flags |= SDL_OPENGL; + current->pitch = 0; + current->pixels = NULL; + _this->UpdateRects = NULL; + } else { + /* Create the BBitmap framebuffer */ + bounds.top = 0; bounds.left = 0; + bounds.right = width-1; + bounds.bottom = height-1; + bbitmap = new BBitmap(bounds, bscreen.ColorSpace()); + if ( ! bbitmap->IsValid() ) { + SDL_SetError("Couldn't create screen bitmap"); + delete bbitmap; + return(NULL); + } + current->pitch = bbitmap->BytesPerRow(); + current->pixels = (void *)bbitmap->Bits(); + SDL_Win->SetBitmap(bbitmap); + _this->UpdateRects = BE_NormalUpdate; + } + + /* Set the correct fullscreen mode */ + BE_SetFullScreen(_this, current, flags & SDL_FULLSCREEN ? 1 : 0); + + /* We're done */ + return(current); +} + +/* Update the current mouse state and position */ +void BE_UpdateMouse(_THIS) +{ + BPoint point; + uint32 buttons; + + if ( SDL_Win->Lock() ) { + /* Get new input state, if still active */ + if ( SDL_Win->IsActive() ) { + (SDL_Win->View())->GetMouse(&point, &buttons, true); + } else { + point.x = -1; + point.y = -1; + } + SDL_Win->Unlock(); + + if ( (point.x >= 0) && (point.x < SDL_VideoSurface->w) && + (point.y >= 0) && (point.y < SDL_VideoSurface->h) ) { + SDL_PrivateAppActive(1, SDL_APPMOUSEFOCUS); + SDL_PrivateMouseMotion(0, 0, + (Sint16)point.x, (Sint16)point.y); + } else { + SDL_PrivateAppActive(0, SDL_APPMOUSEFOCUS); + } + } +} + +/* We don't actually allow hardware surfaces other than the main one */ +static int BE_AllocHWSurface(_THIS, SDL_Surface *surface) +{ + return(-1); +} +static void BE_FreeHWSurface(_THIS, SDL_Surface *surface) +{ + return; +} +static int BE_LockHWSurface(_THIS, SDL_Surface *surface) +{ + return(0); +} +static void BE_UnlockHWSurface(_THIS, SDL_Surface *surface) +{ + return; +} + +static void BE_NormalUpdate(_THIS, int numrects, SDL_Rect *rects) +{ + if ( SDL_Win->BeginDraw() ) { + int i; + + for ( i=0; i<numrects; ++i ) { + BRect rect; + + rect.top = rects[i].y; + rect.left = rects[i].x; + rect.bottom = rect.top+rects[i].h-1; + rect.right = rect.left+rects[i].w-1; + SDL_Win->DrawAsync(rect); + } + SDL_Win->EndDraw(); + } +} + +#if SDL_VIDEO_OPENGL +/* Passing a NULL path means load pointers from the application */ +int BE_GL_LoadLibrary(_THIS, const char *path) +{ + if (path == NULL) { + if (_this->gl_config.dll_handle == NULL) { + image_info info; + int32 cookie = 0; + while (get_next_image_info(0,&cookie,&info) == B_OK) { + void *location = NULL; +#ifdef __HAIKU__ + if (get_image_symbol(info.id,"glBegin",B_SYMBOL_TYPE_ANY,&location) == B_OK) { // This is how it actually works in Haiku +#else + if (get_image_symbol((image_id)cookie,"glBegin",B_SYMBOL_TYPE_ANY,&location) == B_OK) { // I don't know if that *did* work in BeOS +#endif + _this->gl_config.dll_handle = (void*)info.id; + _this->gl_config.driver_loaded = 1; + SDL_strlcpy(_this->gl_config.driver_path, "libGL.so", SDL_arraysize(_this->gl_config.driver_path)); + } + } + } + } else { + /* + FIXME None of BeOS libGL.so implementations have exported functions + to load BGLView, which should be reloaded from new lib. + So for now just "load" linked libGL.so :( + */ + if (_this->gl_config.dll_handle == NULL) { + return BE_GL_LoadLibrary(_this, NULL); + } + + /* Unload old first */ + /*if (_this->gl_config.dll_handle != NULL) {*/ + /* Do not try to unload application itself (if LoadLibrary was called before with NULL ;) */ + /* image_info info; + if (get_image_info((image_id)_this->gl_config.dll_handle, &info) == B_OK) { + if (info.type != B_APP_IMAGE) { + unload_add_on((image_id)_this->gl_config.dll_handle); + } + } + + } + + if ((_this->gl_config.dll_handle = (void*)load_add_on(path)) != (void*)B_ERROR) { + _this->gl_config.driver_loaded = 1; + SDL_strlcpy(_this->gl_config.driver_path, path, SDL_arraysize(_this->gl_config.driver_path)); + }*/ + } + + if (_this->gl_config.dll_handle != NULL) { + return 0; + } else { + _this->gl_config.dll_handle = NULL; + _this->gl_config.driver_loaded = 0; + *_this->gl_config.driver_path = '\0'; + return -1; + } +} + +void* BE_GL_GetProcAddress(_THIS, const char *proc) +{ + if (_this->gl_config.dll_handle != NULL) { + void *location = NULL; + status_t err; + if ((err = get_image_symbol((image_id)_this->gl_config.dll_handle, proc, B_SYMBOL_TYPE_ANY, &location)) == B_OK) { + return location; + } else { + SDL_SetError("Couldn't find OpenGL symbol"); + return NULL; + } + } else { + SDL_SetError("OpenGL library not loaded"); + return NULL; + } +} + +int BE_GL_GetAttribute(_THIS, SDL_GLattr attrib, int* value) +{ + /* + FIXME? Right now BE_GL_GetAttribute shouldn't be called between glBegin() and glEnd() - it doesn't use "cached" values + */ + switch (attrib) + { + case SDL_GL_RED_SIZE: + glGetIntegerv(GL_RED_BITS, (GLint*)value); + break; + case SDL_GL_GREEN_SIZE: + glGetIntegerv(GL_GREEN_BITS, (GLint*)value); + break; + case SDL_GL_BLUE_SIZE: + glGetIntegerv(GL_BLUE_BITS, (GLint*)value); + break; + case SDL_GL_ALPHA_SIZE: + glGetIntegerv(GL_ALPHA_BITS, (GLint*)value); + break; + case SDL_GL_DOUBLEBUFFER: + glGetBooleanv(GL_DOUBLEBUFFER, (GLboolean*)value); + break; + case SDL_GL_BUFFER_SIZE: + int v; + glGetIntegerv(GL_RED_BITS, (GLint*)&v); + *value = v; + glGetIntegerv(GL_GREEN_BITS, (GLint*)&v); + *value += v; + glGetIntegerv(GL_BLUE_BITS, (GLint*)&v); + *value += v; + glGetIntegerv(GL_ALPHA_BITS, (GLint*)&v); + *value += v; + break; + case SDL_GL_DEPTH_SIZE: + glGetIntegerv(GL_DEPTH_BITS, (GLint*)value); /* Mesa creates 16 only? r5 always 32 */ + break; + case SDL_GL_STENCIL_SIZE: + glGetIntegerv(GL_STENCIL_BITS, (GLint*)value); + break; + case SDL_GL_ACCUM_RED_SIZE: + glGetIntegerv(GL_ACCUM_RED_BITS, (GLint*)value); + break; + case SDL_GL_ACCUM_GREEN_SIZE: + glGetIntegerv(GL_ACCUM_GREEN_BITS, (GLint*)value); + break; + case SDL_GL_ACCUM_BLUE_SIZE: + glGetIntegerv(GL_ACCUM_BLUE_BITS, (GLint*)value); + break; + case SDL_GL_ACCUM_ALPHA_SIZE: + glGetIntegerv(GL_ACCUM_ALPHA_BITS, (GLint*)value); + break; + case SDL_GL_STEREO: + case SDL_GL_MULTISAMPLEBUFFERS: + case SDL_GL_MULTISAMPLESAMPLES: + default: + *value=0; + return(-1); + } + return 0; +} + +int BE_GL_MakeCurrent(_THIS) +{ + /* FIXME: should we glview->unlock and then glview->lock()? */ + return 0; +} + +void BE_GL_SwapBuffers(_THIS) +{ + SDL_Win->SwapBuffers(); +} +#endif + +/* Is the system palette settable? */ +int BE_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors) +{ + int i; + SDL_Palette *palette; + const color_map *cmap = BScreen().ColorMap(); + + /* Get the screen colormap */ + palette = _this->screen->format->palette; + for ( i=0; i<256; ++i ) { + palette->colors[i].r = cmap->color_list[i].red; + palette->colors[i].g = cmap->color_list[i].green; + palette->colors[i].b = cmap->color_list[i].blue; + } + return(0); +} + +void BE_VideoQuit(_THIS) +{ + int i, j; + + SDL_Win->Quit(); + SDL_Win = NULL; + + if ( SDL_BlankCursor != NULL ) { + BE_FreeWMCursor(_this, SDL_BlankCursor); + SDL_BlankCursor = NULL; + } + for ( i=0; i<NUM_MODELISTS; ++i ) { + if ( SDL_modelist[i] ) { + for ( j=0; SDL_modelist[i][j]; ++j ) { + SDL_free(SDL_modelist[i][j]); + } + SDL_free(SDL_modelist[i]); + SDL_modelist[i] = NULL; + } + } + /* Restore the original video mode */ + if ( _this->screen ) { + if ( (_this->screen->flags&SDL_FULLSCREEN) == SDL_FULLSCREEN ) { + BScreen bscreen; + bscreen.SetMode(&saved_mode); + } + _this->screen->pixels = NULL; + } + +#if SDL_VIDEO_OPENGL + if (_this->gl_config.dll_handle != NULL) + unload_add_on((image_id)_this->gl_config.dll_handle); +#endif + + SDL_QuitBeApp(); +} + +}; /* Extern C */ diff --git a/3rdparty/SDL/src/video/bwindow/SDL_syswm.cc b/3rdparty/SDL/src/video/bwindow/SDL_syswm.cc new file mode 100644 index 0000000..df80100 --- /dev/null +++ b/3rdparty/SDL/src/video/bwindow/SDL_syswm.cc @@ -0,0 +1,92 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#include "SDL_BWin.h" + +extern "C" { +#include "SDL_syswm_c.h" +#include "SDL_error.h" +#include "../SDL_cursor_c.h" + +void BE_SetWMCaption(_THIS, const char *title, const char *icon) +{ + SDL_Win->SetTitle(title); +} + +int BE_IconifyWindow(_THIS) +{ + SDL_Win->Minimize(true); + return 1; +} + +SDL_GrabMode BE_GrabInput(_THIS, SDL_GrabMode mode) +{ + if ( mode == SDL_GRAB_OFF ) { +// be_app->ShowCursor(); + if ( !(SDL_cursorstate & CURSOR_VISIBLE) ) { + /* BeSman: Jan 2, 2006 + must be leaving relative mode, move mouse from + center of window to where it belongs ... */ + BPoint pt; + int x, y; + SDL_GetMouseState(&x,&y); + pt.x = x; + pt.y = y; + SDL_Win->Lock(); + SDL_Win->ConvertToScreen(&pt); + SDL_Win->Unlock(); + set_mouse_position((int)pt.x, (int)pt.y); + } + } else { +// be_app->HideCursor(); + if ( !(SDL_cursorstate & CURSOR_VISIBLE) ) { + /* BeSman: Jan 2, 2006 + must be entering relative mode, get ready by + moving mouse to center of window ... */ + BPoint pt; + pt.x = (SDL_VideoSurface->w/2); + pt.y = (SDL_VideoSurface->h/2); + SDL_Win->Lock(); + SDL_Win->ConvertToScreen(&pt); + SDL_Win->Unlock(); + set_mouse_position((int)pt.x, (int)pt.y); + } + } + return(mode); +} + +int BE_GetWMInfo(_THIS, SDL_SysWMinfo *info) +{ + if (info->version.major <= SDL_MAJOR_VERSION) + { + return 1; + } + else + { + SDL_SetError("Application not compiled with SDL %d.%d\n", + SDL_MAJOR_VERSION, SDL_MINOR_VERSION); + return -1; + } +} + +}; /* Extern C */ diff --git a/3rdparty/SDL/src/video/bwindow/SDL_syswm_c.h b/3rdparty/SDL/src/video/bwindow/SDL_syswm_c.h new file mode 100644 index 0000000..c1285c8 --- /dev/null +++ b/3rdparty/SDL/src/video/bwindow/SDL_syswm_c.h @@ -0,0 +1,32 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#include "SDL_syswm.h" +#include "SDL_lowvideo.h" + + +/* Functions to be exported */ +extern void BE_SetWMCaption(_THIS, const char *title, const char *icon); +extern int BE_IconifyWindow(_THIS); +extern int BE_GetWMInfo(_THIS, SDL_SysWMinfo *info); +extern SDL_GrabMode BE_GrabInput(_THIS, SDL_GrabMode mode); diff --git a/3rdparty/SDL/src/video/bwindow/SDL_sysyuv.cc b/3rdparty/SDL/src/video/bwindow/SDL_sysyuv.cc new file mode 100644 index 0000000..7c71b00 --- /dev/null +++ b/3rdparty/SDL/src/video/bwindow/SDL_sysyuv.cc @@ -0,0 +1,314 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* This is the BeOS version of SDL YUV video overlays */ + +#include "SDL_video.h" +#include "SDL_sysyuv.h" +#include "../SDL_yuvfuncs.h" + +extern "C" { + +/* The functions used to manipulate software video overlays */ +static struct private_yuvhwfuncs be_yuvfuncs = +{ + BE_LockYUVOverlay, + BE_UnlockYUVOverlay, + BE_DisplayYUVOverlay, + BE_FreeYUVOverlay +}; + +BBitmap * BE_GetOverlayBitmap(BRect bounds, color_space cs) { + BBitmap *bbitmap; + bbitmap = new BBitmap(bounds,B_BITMAP_WILL_OVERLAY,cs); + if (!bbitmap || bbitmap->InitCheck() != B_OK) { + delete bbitmap; + return 0; + } + overlay_restrictions r; + bbitmap->GetOverlayRestrictions(&r); + uint32 width = bounds.IntegerWidth() + 1; + uint32 height = bounds.IntegerHeight() + 1; + uint32 width_padding = 0; + uint32 height_padding = 0; + if ((r.source.horizontal_alignment != 0) || + (r.source.vertical_alignment != 0)) { + delete bbitmap; + return 0; + } + if (r.source.width_alignment != 0) { + uint32 aligned_width = r.source.width_alignment + 1; + if (width % aligned_width > 0) { + width_padding = aligned_width - width % aligned_width; + } + } + if (r.source.height_alignment != 0) { + uint32 aligned_height = r.source.height_alignment + 1; + if (height % aligned_height > 0) { + fprintf(stderr,"GetOverlayBitmap failed height alignment\n"); + fprintf(stderr,"- height = %lu, aligned_height = %lu\n",height,aligned_height); + delete bbitmap; + return 0; + } + } + if ((r.source.min_width > width) || + (r.source.min_height > height) || + (r.source.max_width < width) || + (r.source.max_height < height)) { + fprintf(stderr,"GetOverlayBitmap failed bounds tests\n"); + delete bbitmap; + return 0; + } + if ((width_padding != 0) || (height_padding != 0)) { + delete bbitmap; + bounds.Set(bounds.left,bounds.top,bounds.right+width_padding,bounds.bottom+height_padding); + bbitmap = new BBitmap(bounds,B_BITMAP_WILL_OVERLAY,cs); + if (!bbitmap || bbitmap->InitCheck() != B_OK) { + fprintf(stderr,"GetOverlayBitmap failed late\n"); + delete bbitmap; + return 0; + } + } + return bbitmap; +} + +// See <GraphicsDefs.h> [btw: Cb=U, Cr=V] +// See also http://www.fourcc.org/indexyuv.htm +color_space convert_color_space(Uint32 format) { + switch (format) { + case SDL_YV12_OVERLAY: + return B_YUV9; + case SDL_IYUV_OVERLAY: + return B_YUV12; + case SDL_YUY2_OVERLAY: + return B_YCbCr422; + case SDL_UYVY_OVERLAY: + return B_YUV422; + case SDL_YVYU_OVERLAY: // not supported on beos? + return B_NO_COLOR_SPACE; + default: + return B_NO_COLOR_SPACE; + } +} + +// See SDL_video.h +int count_planes(Uint32 format) { + switch (format) { + case SDL_YV12_OVERLAY: + case SDL_IYUV_OVERLAY: + return 3; + case SDL_YUY2_OVERLAY: + case SDL_UYVY_OVERLAY: + case SDL_YVYU_OVERLAY: + return 1; + default: + return 0; + } +} + +SDL_Overlay *BE_CreateYUVOverlay(_THIS, int width, int height, Uint32 format, SDL_Surface *display) { + SDL_Overlay* overlay; + struct private_yuvhwdata* hwdata; + BBitmap *bbitmap; + int planes; + BRect bounds; + color_space cs; + + /* find the appropriate BeOS colorspace descriptor */ + cs = convert_color_space(format); + if (cs == B_NO_COLOR_SPACE) + { + return NULL; + } + + /* count planes */ + planes = count_planes(format); + if (planes == 0) + { + return NULL; + } + /* TODO: figure out planar modes, if anyone cares */ + if (planes == 3) + { + return NULL; + } + + /* Create the overlay structure */ + overlay = (SDL_Overlay*)SDL_calloc(1, sizeof(SDL_Overlay)); + + if (overlay == NULL) + { + SDL_OutOfMemory(); + return NULL; + } + + /* Fill in the basic members */ + overlay->format = format; + overlay->w = width; + overlay->h = height; + overlay->hwdata = NULL; + + /* Set up the YUV surface function structure */ + overlay->hwfuncs = &be_yuvfuncs; + + /* Create the pixel data and lookup tables */ + hwdata = (struct private_yuvhwdata*)SDL_calloc(1, sizeof(struct private_yuvhwdata)); + + if (hwdata == NULL) + { + SDL_OutOfMemory(); + SDL_FreeYUVOverlay(overlay); + return NULL; + } + + overlay->hwdata = hwdata; + overlay->hwdata->display = display; + overlay->hwdata->bview = NULL; + overlay->hwdata->bbitmap = NULL; + overlay->hwdata->locked = 0; + + /* Create the BBitmap framebuffer */ + bounds.top = 0; bounds.left = 0; + bounds.right = width-1; + bounds.bottom = height-1; + + BView * bview = new BView(bounds,"overlay",B_FOLLOW_NONE,B_WILL_DRAW); + if (!bview) { + SDL_OutOfMemory(); + SDL_FreeYUVOverlay(overlay); + return NULL; + } + overlay->hwdata->bview = bview; + overlay->hwdata->first_display = true; + bview->Hide(); + + bbitmap = BE_GetOverlayBitmap(bounds,cs); + if (!bbitmap) { + overlay->hwdata->bbitmap = NULL; + SDL_FreeYUVOverlay(overlay); + return NULL; + } + overlay->hwdata->bbitmap = bbitmap; + + overlay->planes = planes; + overlay->pitches = (Uint16*)SDL_calloc(overlay->planes, sizeof(Uint16)); + overlay->pixels = (Uint8**)SDL_calloc(overlay->planes, sizeof(Uint8*)); + if (!overlay->pitches || !overlay->pixels) + { + SDL_OutOfMemory(); + SDL_FreeYUVOverlay(overlay); + return(NULL); + } + + overlay->pitches[0] = bbitmap->BytesPerRow(); + overlay->pixels[0] = (Uint8 *)bbitmap->Bits(); + overlay->hw_overlay = 1; + + if (SDL_Win->LockWithTimeout(1000000) != B_OK) { + SDL_FreeYUVOverlay(overlay); + return(NULL); + } + BView * view = SDL_Win->View(); + view->AddChild(bview); + rgb_color key; + bview->SetViewOverlay(bbitmap,bounds,bview->Bounds(),&key,B_FOLLOW_ALL, + B_OVERLAY_FILTER_HORIZONTAL|B_OVERLAY_FILTER_VERTICAL); + bview->SetViewColor(key); + bview->Flush(); + SDL_Win->Unlock(); + + current_overlay=overlay; + + return overlay; +} + +int BE_LockYUVOverlay(_THIS, SDL_Overlay* overlay) +{ + if (overlay == NULL) + { + return 0; + } + + overlay->hwdata->locked = 1; + return 0; +} + +void BE_UnlockYUVOverlay(_THIS, SDL_Overlay* overlay) +{ + if (overlay == NULL) + { + return; + } + + overlay->hwdata->locked = 0; +} + +int BE_DisplayYUVOverlay(_THIS, SDL_Overlay* overlay, SDL_Rect* src, SDL_Rect *dst) +{ + if ((overlay == NULL) || (overlay->hwdata==NULL) + || (overlay->hwdata->bview==NULL) || (SDL_Win->View() == NULL)) + { + return -1; + } + if (SDL_Win->LockWithTimeout(50000) != B_OK) { + return 0; + } + BView * bview = overlay->hwdata->bview; + if (SDL_Win->IsFullScreen()) { + int left,top; + SDL_Win->GetXYOffset(left,top); + bview->MoveTo(left+dst->x,top+dst->y); + } else { + bview->MoveTo(dst->x,dst->y); + } + bview->ResizeTo(dst->w,dst->h); + bview->Flush(); + if (overlay->hwdata->first_display) { + bview->Show(); + overlay->hwdata->first_display = false; + } + SDL_Win->Unlock(); + + return 0; +} + +void BE_FreeYUVOverlay(_THIS, SDL_Overlay *overlay) +{ + if (overlay == NULL) + { + return; + } + + if (overlay->hwdata == NULL) + { + return; + } + + current_overlay=NULL; + + delete overlay->hwdata->bbitmap; + + SDL_free(overlay->hwdata); +} + +}; // extern "C" diff --git a/3rdparty/SDL/src/video/bwindow/SDL_sysyuv.h b/3rdparty/SDL/src/video/bwindow/SDL_sysyuv.h new file mode 100644 index 0000000..fb5961c --- /dev/null +++ b/3rdparty/SDL/src/video/bwindow/SDL_sysyuv.h @@ -0,0 +1,73 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + + +#ifndef __SDL_SYS_YUV_H__ +#define __SDL_SYS_YUV_H__ + +/* This is the BeOS implementation of YUV video overlays */ + +#include "SDL_video.h" +#include "SDL_lowvideo.h" + +extern "C" { + +struct private_yuvhwdata +{ +/* FRAMEDATA* CurrentFrameData; + FRAMEDATA* FrameData0; + FRAMEDATA* FrameData1; + PgScalerProps_t props; + PgScalerCaps_t caps; + PgVideoChannel_t* channel; + PhArea_t CurrentViewPort; + PhPoint_t CurrentWindowPos; + long format; + int scaler_on; + int current; + long YStride; + long VStride; + long UStride; + int ischromakey; + long chromakey; + int forcedredraw; + unsigned long State; + long flags; +*/ + SDL_Surface *display; + BView *bview; + bool first_display; + BBitmap *bbitmap; + int locked; +}; + +extern BBitmap * BE_GetOverlayBitmap(BRect bounds, color_space cs); +extern SDL_Overlay* BE_CreateYUVOverlay(_THIS, int width, int height, Uint32 format, SDL_Surface* display); +extern int BE_LockYUVOverlay(_THIS, SDL_Overlay* overlay); +extern void BE_UnlockYUVOverlay(_THIS, SDL_Overlay* overlay); +extern int BE_DisplayYUVOverlay(_THIS, SDL_Overlay* overlay, SDL_Rect* src, SDL_Rect* dst); +extern void BE_FreeYUVOverlay(_THIS, SDL_Overlay* overlay); + +}; + +#endif /* __SDL_PH_YUV_H__ */ diff --git a/3rdparty/SDL/src/video/caca/SDL_cacaevents.c b/3rdparty/SDL/src/video/caca/SDL_cacaevents.c new file mode 100644 index 0000000..723b1dd --- /dev/null +++ b/3rdparty/SDL/src/video/caca/SDL_cacaevents.c @@ -0,0 +1,101 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ + +#ifdef SAVE_RCSID +static char rcsid = + "@(#) $Id: libsdl-1.2.11-libcaca.patch,v 1.1 2006/09/18 16:06:06 mr_bones_ Exp $"; +#endif + +#include <stdio.h> + +#include <caca.h> +#ifdef CACA_API_VERSION_1 +#include <caca0.h> +#endif + +#include "SDL.h" +#include "../../events/SDL_sysevents.h" +#include "../../events/SDL_events_c.h" +#include "SDL_cacavideo.h" +#include "SDL_cacaevents_c.h" + +void Caca_PumpEvents(_THIS) +{ + int posted = 0; + int event; + SDL_keysym keysym; + + if( ! this->screen ) /* Wait till we got the screen initialised */ + return; + + do { + posted = 0; + + /* Get libcaca event */ + SDL_mutexP(Caca_mutex); + event = caca_get_event(CACA_EVENT_ANY); + SDL_mutexV(Caca_mutex); + + if ( event & (CACA_EVENT_KEY_PRESS | CACA_EVENT_KEY_RELEASE)) { + int key; + switch ( event & 0xffffff ) + { + case CACA_KEY_LEFT: key = SDLK_LEFT; break; + case CACA_KEY_RIGHT: key = SDLK_RIGHT; break; + case CACA_KEY_UP: key = SDLK_UP; break; + case CACA_KEY_DOWN: key = SDLK_DOWN; break; + default: key = event & 0xff; break; + } + /* Key pressed */ +/* printf("Key pressed: %d (%c)\n", key, key); */ + keysym.scancode = key; + keysym.sym = key; + keysym.mod = KMOD_NONE; + keysym.unicode = 0; + if ( SDL_TranslateUNICODE ) { + keysym.unicode = key; + } + posted += SDL_PrivateKeyboard((event & CACA_EVENT_KEY_PRESS) ? SDL_PRESSED : SDL_RELEASED, &keysym); + } + else if ( event & (CACA_EVENT_MOUSE_PRESS | CACA_EVENT_MOUSE_RELEASE) ) { + /* FIXME: we currently ignore the button type! */ + int button = event & 0x00ffffff; + if ( button > 3 ) { + button = 1; + } + posted += SDL_PrivateMouseButton((event & CACA_EVENT_MOUSE_PRESS) ? SDL_PRESSED : SDL_RELEASED, button, 0, 0); + } + else if ( event & CACA_EVENT_MOUSE_MOTION ) { + int new_x = 0, new_y = 0; + new_x = ((event & 0x00fff000) >> 12) * Caca_w / caca_get_width(); + new_y = ((event & 0x00000fff) >> 0) * Caca_h / caca_get_height(); + posted += SDL_PrivateMouseMotion(0, 0, new_x, new_y); + } + } while ( posted ); +} + +void Caca_InitOSKeymap(_THIS) +{ + return; +} + + diff --git a/3rdparty/SDL/src/video/caca/SDL_cacaevents_c.h b/3rdparty/SDL/src/video/caca/SDL_cacaevents_c.h new file mode 100644 index 0000000..988c3b7 --- /dev/null +++ b/3rdparty/SDL/src/video/caca/SDL_cacaevents_c.h @@ -0,0 +1,35 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ + +#ifdef SAVE_RCSID +static char rcsid = + "@(#) $Id: libsdl-1.2.11-libcaca.patch,v 1.1 2006/09/18 16:06:06 mr_bones_ Exp $"; +#endif + +#include "SDL_cacavideo.h" + +/* Variables and functions exported by SDL_sysevents.c to other parts. + of the native video subsystem (SDL_sysvideo.c) +*/ +extern void Caca_PumpEvents(_THIS); +extern void Caca_InitOSKeymap(_THIS); + diff --git a/3rdparty/SDL/src/video/caca/SDL_cacavideo.c b/3rdparty/SDL/src/video/caca/SDL_cacavideo.c new file mode 100644 index 0000000..59a070c --- /dev/null +++ b/3rdparty/SDL/src/video/caca/SDL_cacavideo.c @@ -0,0 +1,304 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 2003 Sam Hocevar + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Sam Hocevar + sam@zoy.org +*/ + +#ifdef SAVE_RCSID +static char rcsid = + "@(#) $Id: libsdl-1.2.11-libcaca.patch,v 1.1 2006/09/18 16:06:06 mr_bones_ Exp $"; +#endif + +/* libcaca based SDL video driver implementation. +*/ + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <unistd.h> +#include <sys/stat.h> + + +#include "SDL.h" +#include "SDL_error.h" +#include "SDL_video.h" +#include "SDL_mouse.h" +#include "../SDL_sysvideo.h" +#include "../SDL_pixels_c.h" +#include "../../events/SDL_events_c.h" + +#include "SDL_cacavideo.h" +#include "SDL_cacaevents_c.h" + +#include <caca.h> +#ifdef CACA_API_VERSION_1 +#include <caca0.h> +#endif + +/* Initialization/Query functions */ +static int Caca_VideoInit(_THIS, SDL_PixelFormat *vformat); +static SDL_Rect **Caca_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags); +static SDL_Surface *Caca_SetVideoMode(_THIS, SDL_Surface *current, int width, int height, int bpp, Uint32 flags); +static void Caca_VideoQuit(_THIS); + +/* Hardware surface functions */ +static int Caca_AllocHWSurface(_THIS, SDL_Surface *surface); +static int Caca_LockHWSurface(_THIS, SDL_Surface *surface); +static int Caca_FlipHWSurface(_THIS, SDL_Surface *surface); +static void Caca_UnlockHWSurface(_THIS, SDL_Surface *surface); +static void Caca_FreeHWSurface(_THIS, SDL_Surface *surface); + +/* Cache the VideoDevice struct */ +static struct SDL_VideoDevice *local_this; + +/* libcaca driver bootstrap functions */ + +static int Caca_Available(void) +{ + return 1; /* Always available ! */ +} + +static void Caca_DeleteDevice(SDL_VideoDevice *device) +{ + free(device->hidden); + free(device); +} +static SDL_VideoDevice *Caca_CreateDevice(int devindex) +{ + SDL_VideoDevice *device; + + /* Initialize all variables that we clean on shutdown */ + device = (SDL_VideoDevice *)malloc(sizeof(SDL_VideoDevice)); + if ( device ) { + memset(device, 0, (sizeof *device)); + device->hidden = (struct SDL_PrivateVideoData *) + malloc((sizeof *device->hidden)); + } + if ( (device == NULL) || (device->hidden == NULL) ) { + SDL_OutOfMemory(); + if ( device ) { + free(device); + } + return(0); + } + memset(device->hidden, 0, (sizeof *device->hidden)); + + /* Set the function pointers */ + device->VideoInit = Caca_VideoInit; + device->ListModes = Caca_ListModes; + device->SetVideoMode = Caca_SetVideoMode; + device->CreateYUVOverlay = NULL; + device->SetColors = NULL; + device->UpdateRects = NULL; + device->VideoQuit = Caca_VideoQuit; + device->AllocHWSurface = Caca_AllocHWSurface; + device->CheckHWBlit = NULL; + device->FillHWRect = NULL; + device->SetHWColorKey = NULL; + device->SetHWAlpha = NULL; + device->LockHWSurface = Caca_LockHWSurface; + device->UnlockHWSurface = Caca_UnlockHWSurface; + device->FlipHWSurface = NULL; + device->FreeHWSurface = Caca_FreeHWSurface; + device->SetCaption = NULL; + device->SetIcon = NULL; + device->IconifyWindow = NULL; + device->GrabInput = NULL; + device->GetWMInfo = NULL; + device->InitOSKeymap = Caca_InitOSKeymap; + device->PumpEvents = Caca_PumpEvents; + + device->free = Caca_DeleteDevice; + + return device; +} + +VideoBootStrap CACA_bootstrap = { + "caca", "Color ASCII Art Library", + Caca_Available, Caca_CreateDevice +}; + +int Caca_VideoInit(_THIS, SDL_PixelFormat *vformat) +{ + int i; + + /* Initialize all variables that we clean on shutdown */ + for ( i=0; i<SDL_NUMMODES; ++i ) { + SDL_modelist[i] = malloc(sizeof(SDL_Rect)); + SDL_modelist[i]->x = SDL_modelist[i]->y = 0; + } + /* Modes sorted largest to smallest */ + SDL_modelist[0]->w = 1024; SDL_modelist[0]->h = 768; + SDL_modelist[1]->w = 800; SDL_modelist[1]->h = 600; + SDL_modelist[2]->w = 640; SDL_modelist[2]->h = 480; + SDL_modelist[3]->w = 320; SDL_modelist[3]->h = 400; + SDL_modelist[4]->w = 320; SDL_modelist[4]->h = 240; + SDL_modelist[5]->w = 320; SDL_modelist[5]->h = 200; + SDL_modelist[6] = NULL; + + Caca_mutex = SDL_CreateMutex(); + + /* Initialize the library */ + if ( caca_init() != 0 ) { + SDL_SetError("Unable to initialize libcaca"); + return(-1); + } + + /* Initialize private variables */ + Caca_lastkey = 0; + Caca_bitmap = NULL; + Caca_buffer = NULL; + + local_this = this; + + /* Determine the screen depth (use default 8-bit depth) */ + vformat->BitsPerPixel = 8; + vformat->BytesPerPixel = 1; + + /* We're done! */ + return(0); +} + +SDL_Rect **Caca_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags) +{ + if(format->BitsPerPixel != 8) + return NULL; + + if ( flags & SDL_FULLSCREEN ) { + return SDL_modelist; + } else { + return (SDL_Rect **) -1; + } +} + +/* Various screen update functions available */ +static void Caca_DirectUpdate(_THIS, int numrects, SDL_Rect *rects); + +SDL_Surface *Caca_SetVideoMode(_THIS, SDL_Surface *current, + int width, int height, int bpp, Uint32 flags) +{ + if ( Caca_buffer ) { + free( Caca_buffer ); + Caca_buffer = NULL; + } + + if ( Caca_bitmap ) { + caca_free_bitmap( Caca_bitmap ); + Caca_bitmap = NULL; + } + + Caca_buffer = malloc(2 * ((width + 15) & ~15) * height); + if ( ! Caca_buffer ) { + SDL_SetError("Couldn't allocate buffer for requested mode"); + return(NULL); + } + + memset(Caca_buffer, 0, 2 * ((width + 15) & ~15) * height); + + /* Allocate the new pixel format for the screen */ + if ( ! SDL_ReallocFormat(current, 16, 0xf800, 0x07e0, 0x001f, 0) ) { + return(NULL); + } + + /* Set up the new mode framebuffer */ + current->flags = SDL_FULLSCREEN; + Caca_w = current->w = width; + Caca_h = current->h = height; + current->pitch = 2 * ((width + 15) & ~15); + current->pixels = Caca_buffer; + + /* Create the libcaca bitmap */ + Caca_bitmap = caca_create_bitmap( 16, width, height, current->pitch, 0xf800, 0x07e0, 0x001f, 0x0000 ); + if ( ! Caca_bitmap ) { + SDL_SetError("Couldn't allocate libcaca bitmap"); + return(NULL); + } + + /* Set the blit function */ + this->UpdateRects = Caca_DirectUpdate; + + /* We're done */ + return(current); +} + +/* We don't actually allow hardware surfaces other than the main one */ +static int Caca_AllocHWSurface(_THIS, SDL_Surface *surface) +{ + return(-1); +} +static void Caca_FreeHWSurface(_THIS, SDL_Surface *surface) +{ + return; +} + +/* We need to wait for vertical retrace on page flipped displays */ +static int Caca_LockHWSurface(_THIS, SDL_Surface *surface) +{ + /* TODO ? */ + return(0); +} +static void Caca_UnlockHWSurface(_THIS, SDL_Surface *surface) +{ + return; +} + +/* FIXME: How is this done with libcaca? */ +static int Caca_FlipHWSurface(_THIS, SDL_Surface *surface) +{ + SDL_mutexP(Caca_mutex); + caca_refresh(); + SDL_mutexV(Caca_mutex); + return(0); +} + +static void Caca_DirectUpdate(_THIS, int numrects, SDL_Rect *rects) +{ + SDL_mutexP(Caca_mutex); + caca_draw_bitmap( 0, 0, caca_get_width() - 1, caca_get_height() - 1, + Caca_bitmap, Caca_buffer ); + caca_refresh(); + SDL_mutexV(Caca_mutex); + return; +} + +/* Note: If we are terminated, this could be called in the middle of + another SDL video routine -- notably UpdateRects. +*/ +void Caca_VideoQuit(_THIS) +{ + int i; + + /* Free video mode lists */ + for ( i=0; i<SDL_NUMMODES; ++i ) { + if ( SDL_modelist[i] != NULL ) { + free(SDL_modelist[i]); + SDL_modelist[i] = NULL; + } + } + + if ( Caca_bitmap ) { + caca_free_bitmap( Caca_bitmap ); + Caca_bitmap = NULL; + } + + caca_end(); + + SDL_DestroyMutex(Caca_mutex); +} + diff --git a/3rdparty/SDL/src/video/caca/SDL_cacavideo.h b/3rdparty/SDL/src/video/caca/SDL_cacavideo.h new file mode 100644 index 0000000..91fcc81 --- /dev/null +++ b/3rdparty/SDL/src/video/caca/SDL_cacavideo.h @@ -0,0 +1,76 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 2003 Sam Hocevar + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Sam Hocevar + sam@zoy.org +*/ + +#ifdef SAVE_RCSID +static char rcsid = + "@(#) $Id: libsdl-1.2.11-libcaca.patch,v 1.1 2006/09/18 16:06:06 mr_bones_ Exp $"; +#endif + +#ifndef _SDL_cacavideo_h +#define _SDL_cacavideo_h + +#include "SDL_mouse.h" +#include "../SDL_sysvideo.h" +#include "SDL_mutex.h" + +#include <sys/time.h> +#include <time.h> + +#include <caca.h> +#ifdef CACA_API_VERSION_1 +#include <caca0.h> +#endif + +/* Hidden "this" pointer for the video functions */ +#define _THIS SDL_VideoDevice *this + +#define SDL_NUMMODES 6 + +/* Private display data */ +struct SDL_PrivateVideoData { + SDL_Rect *SDL_modelist[SDL_NUMMODES+1]; + SDL_mutex *mutex; + + struct caca_bitmap *bitmap; + void *buffer; + int w, h; + + int lastkey; + struct timeval lasttime; +}; + +/* Old variable names */ +#define SDL_modelist (this->hidden->SDL_modelist) +#define Caca_palette (this->hidden->palette) +#define Caca_bitmap (this->hidden->bitmap) +#define Caca_buffer (this->hidden->buffer) + +#define Caca_w (this->hidden->w) +#define Caca_h (this->hidden->h) + +#define Caca_lastkey (this->hidden->lastkey) +#define Caca_lasttime (this->hidden->lasttime) + +#define Caca_mutex (this->hidden->mutex) + +#endif /* _SDL_cacavideo_h */ + diff --git a/3rdparty/SDL/src/video/dc/SDL_dcevents.c b/3rdparty/SDL/src/video/dc/SDL_dcevents.c new file mode 100644 index 0000000..38dcca4 --- /dev/null +++ b/3rdparty/SDL/src/video/dc/SDL_dcevents.c @@ -0,0 +1,152 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#include "SDL.h" +#include "../../events/SDL_sysevents.h" +#include "../../events/SDL_events_c.h" +#include "SDL_dcvideo.h" +#include "SDL_dcevents_c.h" + +#include <dc/maple.h> +#include <dc/maple/mouse.h> +#include <dc/maple/keyboard.h> + +const static unsigned short sdl_key[]= { + /*0*/ 0, 0, 0, 0, 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', + 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', + 'u', 'v', 'w', 'x', 'y', 'z', + /*1e*/ '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', + /*28*/ SDLK_RETURN, SDLK_ESCAPE, SDLK_BACKSPACE, SDLK_TAB, SDLK_SPACE, SDLK_MINUS, SDLK_PLUS, SDLK_LEFTBRACKET, + SDLK_RIGHTBRACKET, SDLK_BACKSLASH , 0, SDLK_SEMICOLON, SDLK_QUOTE, + /*35*/ '~', SDLK_COMMA, SDLK_PERIOD, SDLK_SLASH, SDLK_CAPSLOCK, + SDLK_F1, SDLK_F2, SDLK_F3, SDLK_F4, SDLK_F5, SDLK_F6, SDLK_F7, SDLK_F8, SDLK_F9, SDLK_F10, SDLK_F11, SDLK_F12, + /*46*/ SDLK_PRINT, SDLK_SCROLLOCK, SDLK_PAUSE, SDLK_INSERT, SDLK_HOME, SDLK_PAGEUP, SDLK_DELETE, SDLK_END, SDLK_PAGEDOWN, SDLK_RIGHT, SDLK_LEFT, SDLK_DOWN, SDLK_UP, + /*53*/ SDLK_NUMLOCK, SDLK_KP_DIVIDE, SDLK_KP_MULTIPLY, SDLK_KP_MINUS, SDLK_KP_PLUS, SDLK_KP_ENTER, + SDLK_KP1, SDLK_KP2, SDLK_KP3, SDLK_KP4, SDLK_KP5, SDLK_KP6, + /*5f*/ SDLK_KP7, SDLK_KP8, SDLK_KP9, SDLK_KP0, SDLK_KP_PERIOD, 0 /* S3 */ +}; + +const static unsigned short sdl_shift[] = { + SDLK_LCTRL,SDLK_LSHIFT,SDLK_LALT,0 /* S1 */, + SDLK_RCTRL,SDLK_RSHIFT,SDLK_RALT,0 /* S2 */, +}; + +#define MOUSE_WHEELUP (1<<4) +#define MOUSE_WHEELDOWN (1<<5) + +static void mouse_update(void) +{ +const static char sdl_mousebtn[] = { + MOUSE_LEFTBUTTON, + MOUSE_RIGHTBUTTON, + MOUSE_SIDEBUTTON, + MOUSE_WHEELUP, + MOUSE_WHEELDOWN +}; + + uint8 addr; + mouse_cond_t cond; + + static int prev_buttons; + int buttons,changed; + int i; + + if ((addr = maple_first_mouse())==0 || mouse_get_cond(addr, &cond)<0) return; + + buttons = cond.buttons^0xff; + if (cond.dz<0) buttons|=MOUSE_WHEELUP; + if (cond.dz>0) buttons|=MOUSE_WHEELDOWN; + + if (cond.dx||cond.dy) SDL_PrivateMouseMotion(0,1,cond.dx,cond.dy); + + changed = buttons^prev_buttons; + for(i=0;i<sizeof(sdl_mousebtn);i++) { + if (changed & sdl_mousebtn[i]) { + SDL_PrivateMouseButton((buttons & sdl_mousebtn[i])?SDL_PRESSED:SDL_RELEASED,i,0,0); + } + } + prev_buttons = buttons; +} + +static void keyboard_update(void) +{ + static kbd_state_t old_state; + static uint8 old_addr; + + kbd_state_t *state; + uint8 addr; + int port,unit; + + int shiftkeys; + SDL_keysym keysym; + + int i; + + addr = maple_first_kb(); + + if (addr==0) return; + + if (addr!=old_addr) { + old_addr = addr; + SDL_memset(&old_state,0,sizeof(old_state)); + } + + maple_raddr(addr,&port,&unit); + + state = maple_dev_state(port,unit); + if (!state) return; + + shiftkeys = state->shift_keys ^ old_state.shift_keys; + for(i=0;i<sizeof(sdl_shift);i++) { + if ((shiftkeys>>i)&1) { + keysym.sym = sdl_shift[i]; + SDL_PrivateKeyboard(((state->shift_keys>>i)&1)?SDL_PRESSED:SDL_RELEASED,&keysym); + } + } + + for(i=0;i<sizeof(sdl_key);i++) { + if (state->matrix[i]!=old_state.matrix[i]) { + int key = sdl_key[i]; + if (key) { + keysym.sym = key; + SDL_PrivateKeyboard(state->matrix[i]?SDL_PRESSED:SDL_RELEASED,&keysym); + } + } + } + + old_state = *state; +} + +void DC_PumpEvents(_THIS) +{ + keyboard_update(); + mouse_update(); +} + +void DC_InitOSKeymap(_THIS) +{ + /* do nothing. */ +} + +/* end of SDL_dcevents.c ... */ + diff --git a/3rdparty/SDL/src/video/dc/SDL_dcevents_c.h b/3rdparty/SDL/src/video/dc/SDL_dcevents_c.h new file mode 100644 index 0000000..3196eae --- /dev/null +++ b/3rdparty/SDL/src/video/dc/SDL_dcevents_c.h @@ -0,0 +1,33 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#include "SDL_dcvideo.h" + +/* Variables and functions exported by SDL_sysevents.c to other parts + of the native video subsystem (SDL_sysvideo.c) +*/ +extern void DC_InitOSKeymap(_THIS); +extern void DC_PumpEvents(_THIS); + +/* end of SDL_dcevents_c.h ... */ + diff --git a/3rdparty/SDL/src/video/dc/SDL_dcmouse.c b/3rdparty/SDL/src/video/dc/SDL_dcmouse.c new file mode 100644 index 0000000..61a0ba0 --- /dev/null +++ b/3rdparty/SDL/src/video/dc/SDL_dcmouse.c @@ -0,0 +1,35 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#include <stdio.h> + +#include "SDL_mouse.h" +#include "../../events/SDL_events_c.h" + +#include "SDL_dcmouse_c.h" + + +/* The implementation dependent data for the window manager cursor */ +struct WMcursor { + int unused; +}; diff --git a/3rdparty/SDL/src/video/dc/SDL_dcmouse_c.h b/3rdparty/SDL/src/video/dc/SDL_dcmouse_c.h new file mode 100644 index 0000000..dc018bb --- /dev/null +++ b/3rdparty/SDL/src/video/dc/SDL_dcmouse_c.h @@ -0,0 +1,26 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#include "SDL_dcvideo.h" + +/* Functions to be exported */ diff --git a/3rdparty/SDL/src/video/dc/SDL_dcvideo.c b/3rdparty/SDL/src/video/dc/SDL_dcvideo.c new file mode 100644 index 0000000..5838a49 --- /dev/null +++ b/3rdparty/SDL/src/video/dc/SDL_dcvideo.c @@ -0,0 +1,445 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#include "SDL_video.h" +#include "SDL_mouse.h" +#include "../SDL_sysvideo.h" +#include "../SDL_pixels_c.h" +#include "../../events/SDL_events_c.h" + +#include "SDL_dcvideo.h" +#include "SDL_dcevents_c.h" +#include "SDL_dcmouse_c.h" + +#include <dc/video.h> +#include <dc/pvr.h> + + +/* Initialization/Query functions */ +static int DC_VideoInit(_THIS, SDL_PixelFormat *vformat); +static SDL_Rect **DC_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags); +static SDL_Surface *DC_SetVideoMode(_THIS, SDL_Surface *current, int width, int height, int bpp, Uint32 flags); +static int DC_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors); +static void DC_VideoQuit(_THIS); + +/* Hardware surface functions */ +static int DC_AllocHWSurface(_THIS, SDL_Surface *surface); +static int DC_LockHWSurface(_THIS, SDL_Surface *surface); +static void DC_UnlockHWSurface(_THIS, SDL_Surface *surface); +static void DC_FreeHWSurface(_THIS, SDL_Surface *surface); +static int DC_FlipHWSurface(_THIS, SDL_Surface *surface); + +/* etc. */ +static void DC_UpdateRects(_THIS, int numrects, SDL_Rect *rects); + +/* OpenGL */ +#if SDL_VIDEO_OPENGL +static void *DC_GL_GetProcAddress(_THIS, const char *proc); +static int DC_GL_LoadLibrary(_THIS, const char *path); +static int DC_GL_GetAttribute(_THIS, SDL_GLattr attrib, int* value); +static void DC_GL_SwapBuffers(_THIS); +#endif + +/* DC driver bootstrap functions */ + +static int DC_Available(void) +{ + return 1; +} + +static void DC_DeleteDevice(SDL_VideoDevice *device) +{ + SDL_free(device->hidden); + SDL_free(device); +} + +static SDL_VideoDevice *DC_CreateDevice(int devindex) +{ + SDL_VideoDevice *device; + + /* Initialize all variables that we clean on shutdown */ + device = (SDL_VideoDevice *)SDL_malloc(sizeof(SDL_VideoDevice)); + if ( device ) { + SDL_memset(device, 0, (sizeof *device)); + device->hidden = (struct SDL_PrivateVideoData *) + SDL_malloc((sizeof *device->hidden)); + } + if ( (device == NULL) || (device->hidden == NULL) ) { + SDL_OutOfMemory(); + if ( device ) { + SDL_free(device); + } + return(0); + } + SDL_memset(device->hidden, 0, (sizeof *device->hidden)); + + /* Set the function pointers */ + device->VideoInit = DC_VideoInit; + device->ListModes = DC_ListModes; + device->SetVideoMode = DC_SetVideoMode; + device->CreateYUVOverlay = NULL; + device->SetColors = DC_SetColors; + device->UpdateRects = DC_UpdateRects; + device->VideoQuit = DC_VideoQuit; + device->AllocHWSurface = DC_AllocHWSurface; + device->CheckHWBlit = NULL; + device->FillHWRect = NULL; + device->SetHWColorKey = NULL; + device->SetHWAlpha = NULL; + device->LockHWSurface = DC_LockHWSurface; + device->UnlockHWSurface = DC_UnlockHWSurface; + device->FlipHWSurface = DC_FlipHWSurface; + device->FreeHWSurface = DC_FreeHWSurface; +#if SDL_VIDEO_OPENGL + device->GL_LoadLibrary = DC_GL_LoadLibrary; + device->GL_GetProcAddress = DC_GL_GetProcAddress; + device->GL_GetAttribute = DC_GL_GetAttribute; + device->GL_MakeCurrent = NULL; + device->GL_SwapBuffers = DC_GL_SwapBuffers; +#endif + device->SetCaption = NULL; + device->SetIcon = NULL; + device->IconifyWindow = NULL; + device->GrabInput = NULL; + device->GetWMInfo = NULL; + device->InitOSKeymap = DC_InitOSKeymap; + device->PumpEvents = DC_PumpEvents; + + device->free = DC_DeleteDevice; + + return device; +} + +VideoBootStrap DC_bootstrap = { + "dcvideo", "Dreamcast Video", + DC_Available, DC_CreateDevice +}; + + +int DC_VideoInit(_THIS, SDL_PixelFormat *vformat) +{ + /* Determine the screen depth (use default 16-bit depth) */ + /* we change this during the SDL_SetVideoMode implementation... */ + vformat->BitsPerPixel = 16; + vformat->Rmask = 0x0000f800; + vformat->Gmask = 0x000007e0; + vformat->Bmask = 0x0000001f; + + /* We're done! */ + return(0); +} + +const static SDL_Rect + RECT_800x600 = {0,0,800,600}, + RECT_640x480 = {0,0,640,480}, + RECT_320x240 = {0,0,320,240}; +const static SDL_Rect *vid_modes[] = { + &RECT_800x600, + &RECT_640x480, + &RECT_320x240, + NULL +}; + +SDL_Rect **DC_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags) +{ + switch(format->BitsPerPixel) { + case 15: + case 16: + return &vid_modes; + case 32: + if (!(flags & SDL_OPENGL)) + return &vid_modes; + default: + return NULL; + } +// return (SDL_Rect **) -1; +} + +pvr_init_params_t params = { + /* Enable opaque and translucent polygons with size 16 */ + { PVR_BINSIZE_16, PVR_BINSIZE_0, PVR_BINSIZE_16, PVR_BINSIZE_0, PVR_BINSIZE_16 }, + + /* Vertex buffer size */ + 512*1024 +}; + +#if SDL_VIDEO_OPENGL +static int pvr_inited; +#endif + +SDL_Surface *DC_SetVideoMode(_THIS, SDL_Surface *current, + int width, int height, int bpp, Uint32 flags) +{ + int disp_mode,pixel_mode,pitch; + Uint32 Rmask, Gmask, Bmask; + + if (width==320 && height==240) disp_mode=DM_320x240; + else if (width==640 && height==480) disp_mode=DM_640x480; + else if (width==800 && height==600) disp_mode=DM_800x608; + else { + SDL_SetError("Couldn't find requested mode in list"); + return(NULL); + } + + switch(bpp) { + case 15: pixel_mode = PM_RGB555; pitch = width*2; + /* 5-5-5 */ + Rmask = 0x00007c00; + Gmask = 0x000003e0; + Bmask = 0x0000001f; + break; + case 16: pixel_mode = PM_RGB565; pitch = width*2; + /* 5-6-5 */ + Rmask = 0x0000f800; + Gmask = 0x000007e0; + Bmask = 0x0000001f; + break; + case 24: bpp = 32; + case 32: pixel_mode = PM_RGB888; pitch = width*4; + Rmask = 0x00ff0000; + Gmask = 0x0000ff00; + Bmask = 0x000000ff; +#if SDL_VIDEO_OPENGL + if (!(flags & SDL_OPENGL)) +#endif + break; + default: + SDL_SetError("Couldn't find requested mode in list"); + return(NULL); + } + +// if ( bpp != current->format->BitsPerPixel ) { + if ( ! SDL_ReallocFormat(current, bpp, Rmask, Gmask, Bmask, 0) ) { + return(NULL); + } +// } + + /* Set up the new mode framebuffer */ + current->flags = (SDL_FULLSCREEN|SDL_HWSURFACE); + current->w = width; + current->h = height; + current->pitch = pitch; + +#if SDL_VIDEO_OPENGL + if (pvr_inited) { + pvr_inited = 0; + pvr_shutdown(); + } +#endif + + vid_set_mode(disp_mode,pixel_mode); + + current->pixels = vram_s; + +#if SDL_VIDEO_OPENGL + if (flags & SDL_OPENGL) { + this->gl_config.driver_loaded = 1; + current->flags = SDL_FULLSCREEN | SDL_OPENGL; + current->pixels = NULL; + pvr_inited = 1; + pvr_init(¶ms); + glKosInit(); + glKosBeginFrame(); + } else +#endif + if (flags | SDL_DOUBLEBUF) { + current->flags |= SDL_DOUBLEBUF; + current->pixels = (void*)((int)current->pixels | 0x400000); + } + + /* We're done */ + return(current); +} + +/* We don't actually allow hardware surfaces other than the main one */ +static int DC_AllocHWSurface(_THIS, SDL_Surface *surface) +{ + return(-1); +} +static void DC_FreeHWSurface(_THIS, SDL_Surface *surface) +{ + return; +} + +/* We need to wait for vertical retrace on page flipped displays */ +static int DC_LockHWSurface(_THIS, SDL_Surface *surface) +{ + return(0); +} + +static void DC_UnlockHWSurface(_THIS, SDL_Surface *surface) +{ + return; +} + +static int DC_FlipHWSurface(_THIS, SDL_Surface *surface) +{ + if (surface->flags & SDL_DOUBLEBUF) { + vid_set_start((int)surface->pixels & 0xffffff); + surface->pixels = (void*)((int)surface->pixels ^ 0x400000); + } + return(0); +} + +static void DC_UpdateRects(_THIS, int numrects, SDL_Rect *rects) +{ + /* do nothing. */ +} + +static int DC_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors) +{ + /* do nothing of note. */ + return(1); +} + +/* Note: If we are terminated, this could be called in the middle of + another SDL video routine -- notably UpdateRects. +*/ +static void DC_VideoQuit(_THIS) +{ +#if SDL_VIDEO_OPENGL + if (pvr_inited) { + pvr_inited = 0; + pvr_shutdown(); + } +#endif +} + +#if SDL_VIDEO_OPENGL + +void dmyfunc(void) {} + +typedef void (*funcptr)(); +const static struct { + char *name; + funcptr addr; +} glfuncs[] = { +#define DEF(func) {#func,&func} + DEF(glBegin), + DEF(glBindTexture), + DEF(glBlendFunc), + DEF(glColor4f), +// DEF(glCopyImageID), + DEF(glDisable), + DEF(glEnable), + DEF(glEnd), + DEF(glFlush), + DEF(glGenTextures), + DEF(glGetString), + DEF(glLoadIdentity), + DEF(glMatrixMode), + DEF(glOrtho), + DEF(glPixelStorei), +// DEF(glPopAttrib), +// DEF(glPopClientAttrib), + {"glPopAttrib",&dmyfunc}, + {"glPopClientAttrib",&dmyfunc}, + DEF(glPopMatrix), +// DEF(glPushAttrib), +// DEF(glPushClientAttrib), + {"glPushAttrib",&dmyfunc}, + {"glPushClientAttrib",&dmyfunc}, + DEF(glPushMatrix), + DEF(glTexCoord2f), + DEF(glTexEnvf), + DEF(glTexImage2D), + DEF(glTexParameteri), + DEF(glTexSubImage2D), + DEF(glVertex2i), + DEF(glViewport), +#undef DEF +}; + +static void *DC_GL_GetProcAddress(_THIS, const char *proc) +{ + void *ret; + int i; + + ret = glKosGetProcAddress(proc); + if (ret) return ret; + + for(i=0;i<sizeof(glfuncs)/sizeof(glfuncs[0]);i++) { + if (SDL_strcmp(proc,glfuncs[i].name)==0) return glfuncs[i].addr; + } + + return NULL; +} + +static int DC_GL_LoadLibrary(_THIS, const char *path) +{ + this->gl_config.driver_loaded = 1; + + return 0; +} + +static int DC_GL_GetAttribute(_THIS, SDL_GLattr attrib, int* value) +{ + GLenum mesa_attrib; + int val; + + switch(attrib) { + case SDL_GL_RED_SIZE: + val = 5; + break; + case SDL_GL_GREEN_SIZE: + val = 6; + break; + case SDL_GL_BLUE_SIZE: + val = 5; + break; + case SDL_GL_ALPHA_SIZE: + val = 0; + break; + case SDL_GL_DOUBLEBUFFER: + val = 1; + break; + case SDL_GL_DEPTH_SIZE: + val = 16; /* or 32? */ + break; + case SDL_GL_STENCIL_SIZE: + val = 0; + break; + case SDL_GL_ACCUM_RED_SIZE: + val = 0; + break; + case SDL_GL_ACCUM_GREEN_SIZE: + val = 0; + case SDL_GL_ACCUM_BLUE_SIZE: + val = 0; + break; + case SDL_GL_ACCUM_ALPHA_SIZE: + val = 0; + break; + default : + return -1; + } + *value = val; + return 0; +} + +static void DC_GL_SwapBuffers(_THIS) +{ + glKosFinishFrame(); + glKosBeginFrame(); +} +#endif diff --git a/3rdparty/SDL/src/video/dc/SDL_dcvideo.h b/3rdparty/SDL/src/video/dc/SDL_dcvideo.h new file mode 100644 index 0000000..837f028 --- /dev/null +++ b/3rdparty/SDL/src/video/dc/SDL_dcvideo.h @@ -0,0 +1,42 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#ifndef _SDL_dcvideo_h +#define _SDL_dcvideo_h + +#include "SDL_mouse.h" +#include "SDL_mutex.h" +#include "../SDL_sysvideo.h" + +/* Hidden "this" pointer for the video functions */ +#define _THIS SDL_VideoDevice *this + + +/* Private display data */ + +struct SDL_PrivateVideoData { + int w, h; + void *buffer; +}; + +#endif /* _SDL_dcvideo_h */ diff --git a/3rdparty/SDL/src/video/default_cursor.h b/3rdparty/SDL/src/video/default_cursor.h new file mode 100644 index 0000000..d637223 --- /dev/null +++ b/3rdparty/SDL/src/video/default_cursor.h @@ -0,0 +1,116 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ + +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Default cursor - it happens to be the Mac cursor, but could be anything */ + +#define DEFAULT_CWIDTH 16 +#define DEFAULT_CHEIGHT 16 +#define DEFAULT_CHOTX 0 +#define DEFAULT_CHOTY 0 + +/* Added a real MacOS cursor, at the request of Luc-Olivier de Charrire */ +#define USE_MACOS_CURSOR + +#ifdef USE_MACOS_CURSOR + +static unsigned char default_cdata[] = +{ + 0x00,0x00, + 0x40,0x00, + 0x60,0x00, + 0x70,0x00, + 0x78,0x00, + 0x7C,0x00, + 0x7E,0x00, + 0x7F,0x00, + 0x7F,0x80, + 0x7C,0x00, + 0x6C,0x00, + 0x46,0x00, + 0x06,0x00, + 0x03,0x00, + 0x03,0x00, + 0x00,0x00 +}; +static unsigned char default_cmask[] = +{ + 0xC0,0x00, + 0xE0,0x00, + 0xF0,0x00, + 0xF8,0x00, + 0xFC,0x00, + 0xFE,0x00, + 0xFF,0x00, + 0xFF,0x80, + 0xFF,0xC0, + 0xFF,0xE0, + 0xFE,0x00, + 0xEF,0x00, + 0xCF,0x00, + 0x87,0x80, + 0x07,0x80, + 0x03,0x00 +}; + +#else + +static unsigned char default_cdata[] = +{ + 0x00,0x00, + 0x40,0x00, + 0x60,0x00, + 0x70,0x00, + 0x78,0x00, + 0x7C,0x00, + 0x7E,0x00, + 0x7F,0x00, + 0x7F,0x80, + 0x7C,0x00, + 0x6C,0x00, + 0x46,0x00, + 0x06,0x00, + 0x03,0x00, + 0x03,0x00, + 0x00,0x00 +}; +static unsigned char default_cmask[] = +{ + 0x40,0x00, + 0xE0,0x00, + 0xF0,0x00, + 0xF8,0x00, + 0xFC,0x00, + 0xFE,0x00, + 0xFF,0x00, + 0xFF,0x80, + 0xFF,0xC0, + 0xFF,0x80, + 0xFE,0x00, + 0xEF,0x00, + 0x4F,0x00, + 0x07,0x80, + 0x07,0x80, + 0x03,0x00 +}; + +#endif /* TRUE_MACINTOSH_CURSOR */ diff --git a/3rdparty/SDL/src/video/dga/SDL_dgaevents.c b/3rdparty/SDL/src/video/dga/SDL_dgaevents.c new file mode 100644 index 0000000..4e6d5f0 --- /dev/null +++ b/3rdparty/SDL/src/video/dga/SDL_dgaevents.c @@ -0,0 +1,163 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* Handle the event stream, converting DGA events into SDL events */ + +#include <stdio.h> +#include <X11/Xlib.h> +#include "../Xext/extensions/xf86dga.h" + +#include "SDL_timer.h" +#include "../SDL_sysvideo.h" +#include "../../events/SDL_events_c.h" +#include "SDL_dgavideo.h" +#include "SDL_dgaevents_c.h" + +/* get function pointers... */ +#include "../x11/SDL_x11dyn.h" + +/* Heheh we're using X11 event code */ +extern int X11_Pending(Display *display); +extern void X11_InitKeymap(void); +extern SDLKey X11_TranslateKeycode(Display *display, KeyCode kc); + +static int DGA_DispatchEvent(_THIS) +{ + int posted; + SDL_NAME(XDGAEvent) xevent; + + XNextEvent(DGA_Display, (XEvent *)&xevent); + + posted = 0; + xevent.type -= DGA_event_base; + switch (xevent.type) { + + /* Mouse motion? */ + case MotionNotify: { + if ( SDL_VideoSurface ) { + posted = SDL_PrivateMouseMotion(0, 1, + xevent.xmotion.dx, xevent.xmotion.dy); + } + } + break; + + /* Mouse button press? */ + case ButtonPress: { + posted = SDL_PrivateMouseButton(SDL_PRESSED, + xevent.xbutton.button, 0, 0); + } + break; + + /* Mouse button release? */ + case ButtonRelease: { + posted = SDL_PrivateMouseButton(SDL_RELEASED, + xevent.xbutton.button, 0, 0); + } + break; + + /* Key press? */ + case KeyPress: { + SDL_keysym keysym; + KeyCode keycode; + XKeyEvent xkey; + + SDL_NAME(XDGAKeyEventToXKeyEvent)(&xevent.xkey, &xkey); + keycode = xkey.keycode; +#ifdef DEBUG_XEVENTS +printf("KeyPress (X11 keycode = 0x%X)\n", xkey.keycode); +#endif + /* Get the translated SDL virtual keysym */ + keysym.scancode = keycode; + keysym.sym = X11_TranslateKeycode(DGA_Display, keycode); + keysym.mod = KMOD_NONE; + keysym.unicode = 0; + + /* Look up the translated value for the key event */ + if ( SDL_TranslateUNICODE ) { + static XComposeStatus state; + char keybuf[32]; + + if ( XLookupString(&xkey, keybuf, sizeof(keybuf), NULL, &state) ) { + /* + * FIXME: XLookupString() may yield more than one + * character, so we need a mechanism to allow for + * this (perhaps null keypress events with a + * unicode value) + */ + keysym.unicode = (Uint8)keybuf[0]; + } + } + posted = SDL_PrivateKeyboard(SDL_PRESSED, &keysym); + } + break; + + /* Key release? */ + case KeyRelease: { + SDL_keysym keysym; + KeyCode keycode; + XKeyEvent xkey; + + SDL_NAME(XDGAKeyEventToXKeyEvent)(&xevent.xkey, &xkey); + keycode = xkey.keycode; +#ifdef DEBUG_XEVENTS +printf("KeyRelease (X11 keycode = 0x%X)\n", xkey.keycode); +#endif + /* Get the translated SDL virtual keysym */ + keysym.scancode = keycode; + keysym.sym = X11_TranslateKeycode(DGA_Display, keycode); + keysym.mod = KMOD_NONE; + keysym.unicode = 0; + posted = SDL_PrivateKeyboard(SDL_RELEASED, &keysym); + } + break; + } + return(posted); +} + +void DGA_PumpEvents(_THIS) +{ + /* Keep processing pending events */ + LOCK_DISPLAY(); + + /* Update activity every five seconds to prevent screensaver. --ryan. */ + if (!allow_screensaver) { + static Uint32 screensaverTicks; + Uint32 nowTicks = SDL_GetTicks(); + if ((nowTicks - screensaverTicks) > 5000) { + XResetScreenSaver(DGA_Display); + screensaverTicks = nowTicks; + } + } + + while ( X11_Pending(DGA_Display) ) { + DGA_DispatchEvent(this); + } + + UNLOCK_DISPLAY(); +} + +void DGA_InitOSKeymap(_THIS) +{ + X11_InitKeymap(); +} + diff --git a/3rdparty/SDL/src/video/dga/SDL_dgaevents_c.h b/3rdparty/SDL/src/video/dga/SDL_dgaevents_c.h new file mode 100644 index 0000000..45f8cc5 --- /dev/null +++ b/3rdparty/SDL/src/video/dga/SDL_dgaevents_c.h @@ -0,0 +1,28 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#include "SDL_dgavideo.h" + +/* Functions to be exported */ +extern void DGA_PumpEvents(_THIS); +extern void DGA_InitOSKeymap(_THIS); diff --git a/3rdparty/SDL/src/video/dga/SDL_dgamouse.c b/3rdparty/SDL/src/video/dga/SDL_dgamouse.c new file mode 100644 index 0000000..43bc5d6 --- /dev/null +++ b/3rdparty/SDL/src/video/dga/SDL_dgamouse.c @@ -0,0 +1,35 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#include <stdio.h> + +#include "SDL_mouse.h" +#include "../../events/SDL_events_c.h" +#include "SDL_dgavideo.h" +#include "SDL_dgamouse_c.h" + + +/* The implementation dependent data for the window manager cursor */ +struct WMcursor { + int unused; +}; diff --git a/3rdparty/SDL/src/video/dga/SDL_dgamouse_c.h b/3rdparty/SDL/src/video/dga/SDL_dgamouse_c.h new file mode 100644 index 0000000..4ea8b21 --- /dev/null +++ b/3rdparty/SDL/src/video/dga/SDL_dgamouse_c.h @@ -0,0 +1,26 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#include "SDL_dgavideo.h" + +/* Functions to be exported */ diff --git a/3rdparty/SDL/src/video/dga/SDL_dgavideo.c b/3rdparty/SDL/src/video/dga/SDL_dgavideo.c new file mode 100644 index 0000000..267d5cc --- /dev/null +++ b/3rdparty/SDL/src/video/dga/SDL_dgavideo.c @@ -0,0 +1,1101 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* DGA 2.0 based SDL video driver implementation. +*/ + +#include <stdio.h> + +#include <X11/Xlib.h> +#include "../Xext/extensions/xf86dga.h" + +#include "SDL_video.h" +#include "SDL_mouse.h" +#include "../SDL_sysvideo.h" +#include "../SDL_pixels_c.h" +#include "../../events/SDL_events_c.h" +#include "SDL_dgavideo.h" +#include "SDL_dgamouse_c.h" +#include "SDL_dgaevents_c.h" + +/* get function pointers... */ +#include "../x11/SDL_x11dyn.h" + +/*#define DGA_DEBUG*/ + +/* Initialization/Query functions */ +static int DGA_VideoInit(_THIS, SDL_PixelFormat *vformat); +static SDL_Rect **DGA_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags); +static SDL_Surface *DGA_SetVideoMode(_THIS, SDL_Surface *current, int width, int height, int bpp, Uint32 flags); +static int DGA_SetColors(_THIS, int firstcolor, int ncolors, + SDL_Color *colors); +static int DGA_SetGammaRamp(_THIS, Uint16 *ramp); +static void DGA_VideoQuit(_THIS); + +/* Hardware surface functions */ +static int DGA_InitHWSurfaces(_THIS, SDL_Surface *screen, Uint8 *base, int size); +static void DGA_FreeHWSurfaces(_THIS); +static int DGA_AllocHWSurface(_THIS, SDL_Surface *surface); +static int DGA_FillHWRect(_THIS, SDL_Surface *dst, SDL_Rect *rect, Uint32 color); +static int DGA_CheckHWBlit(_THIS, SDL_Surface *src, SDL_Surface *dst); +static int DGA_LockHWSurface(_THIS, SDL_Surface *surface); +static void DGA_UnlockHWSurface(_THIS, SDL_Surface *surface); +static void DGA_FreeHWSurface(_THIS, SDL_Surface *surface); +static int DGA_FlipHWSurface(_THIS, SDL_Surface *surface); + +/* DGA driver bootstrap functions */ + +static int DGA_Available(void) +{ + const char *display = NULL; + Display *dpy = NULL; + int available = 0; + + /* The driver is available is available if the display is local + and the DGA 2.0+ extension is available, and we can map mem. + */ + if ( SDL_X11_LoadSymbols() ) { + if ( (SDL_strncmp(XDisplayName(display), ":", 1) == 0) || + (SDL_strncmp(XDisplayName(display), "unix:", 5) == 0) ) { + dpy = XOpenDisplay(display); + if ( dpy ) { + int events, errors, major, minor; + + if ( SDL_NAME(XDGAQueryExtension)(dpy, &events, &errors) && + SDL_NAME(XDGAQueryVersion)(dpy, &major, &minor) ) { + int screen; + + screen = DefaultScreen(dpy); + if ( (major >= 2) && + SDL_NAME(XDGAOpenFramebuffer)(dpy, screen) ) { + available = 1; + SDL_NAME(XDGACloseFramebuffer)(dpy, screen); + } + } + XCloseDisplay(dpy); + } + } + SDL_X11_UnloadSymbols(); + } + return(available); +} + +static void DGA_DeleteDevice(SDL_VideoDevice *device) +{ + if (device != NULL) { + SDL_free(device->hidden); + SDL_free(device); + SDL_X11_UnloadSymbols(); + } +} + +static SDL_VideoDevice *DGA_CreateDevice(int devindex) +{ + SDL_VideoDevice *device = NULL; + + /* Initialize all variables that we clean on shutdown */ + if (SDL_X11_LoadSymbols()) { + device = (SDL_VideoDevice *)SDL_malloc(sizeof(SDL_VideoDevice)); + if ( device ) { + SDL_memset(device, 0, (sizeof *device)); + device->hidden = (struct SDL_PrivateVideoData *) + SDL_malloc((sizeof *device->hidden)); + } + if ( (device == NULL) || (device->hidden == NULL) ) { + SDL_OutOfMemory(); + if ( device ) { + SDL_free(device); + } + SDL_X11_UnloadSymbols(); + return(0); + } + SDL_memset(device->hidden, 0, (sizeof *device->hidden)); + + /* Set the function pointers */ + device->VideoInit = DGA_VideoInit; + device->ListModes = DGA_ListModes; + device->SetVideoMode = DGA_SetVideoMode; + device->SetColors = DGA_SetColors; + device->UpdateRects = NULL; + device->VideoQuit = DGA_VideoQuit; + device->AllocHWSurface = DGA_AllocHWSurface; + device->CheckHWBlit = DGA_CheckHWBlit; + device->FillHWRect = DGA_FillHWRect; + device->SetHWColorKey = NULL; + device->SetHWAlpha = NULL; + device->LockHWSurface = DGA_LockHWSurface; + device->UnlockHWSurface = DGA_UnlockHWSurface; + device->FlipHWSurface = DGA_FlipHWSurface; + device->FreeHWSurface = DGA_FreeHWSurface; + device->SetGammaRamp = DGA_SetGammaRamp; + device->GetGammaRamp = NULL; + device->SetCaption = NULL; + device->SetIcon = NULL; + device->IconifyWindow = NULL; + device->GrabInput = NULL; + device->GetWMInfo = NULL; + device->InitOSKeymap = DGA_InitOSKeymap; + device->PumpEvents = DGA_PumpEvents; + + device->free = DGA_DeleteDevice; + } + + return device; +} + +VideoBootStrap DGA_bootstrap = { + "dga", "XFree86 DGA 2.0", + DGA_Available, DGA_CreateDevice +}; + +static int DGA_AddMode(_THIS, int bpp, int w, int h) +{ + SDL_Rect *mode; + int index; + int next_mode; + + /* Check to see if we already have this mode */ + if ( bpp < 8 ) { /* Not supported */ + return(0); + } + index = ((bpp+7)/8)-1; + if ( SDL_nummodes[index] > 0 ) { + mode = SDL_modelist[index][SDL_nummodes[index]-1]; + if ( (mode->w == w) && (mode->h == h) ) { + return(0); + } + } + + /* Set up the new video mode rectangle */ + mode = (SDL_Rect *)SDL_malloc(sizeof *mode); + if ( mode == NULL ) { + SDL_OutOfMemory(); + return(-1); + } + mode->x = 0; + mode->y = 0; + mode->w = w; + mode->h = h; + + /* Allocate the new list of modes, and fill in the new mode */ + next_mode = SDL_nummodes[index]; + SDL_modelist[index] = (SDL_Rect **) + SDL_realloc(SDL_modelist[index], (1+next_mode+1)*sizeof(SDL_Rect *)); + if ( SDL_modelist[index] == NULL ) { + SDL_OutOfMemory(); + SDL_nummodes[index] = 0; + SDL_free(mode); + return(-1); + } + SDL_modelist[index][next_mode] = mode; + SDL_modelist[index][next_mode+1] = NULL; + SDL_nummodes[index]++; + + return(0); +} + +/* This whole function is a hack. :) */ +static Uint32 get_video_size(_THIS) +{ + /* This is a non-exported function from libXxf86dga.a */ + extern unsigned char *SDL_NAME(XDGAGetMappedMemory)(int screen); + FILE *proc; + unsigned long mem; + unsigned start, stop; + char line[BUFSIZ]; + Uint32 size; + + mem = (unsigned long)SDL_NAME(XDGAGetMappedMemory)(DGA_Screen); + size = 0; + proc = fopen("/proc/self/maps", "r"); + if ( proc ) { + while ( fgets(line, sizeof(line)-1, proc) ) { + SDL_sscanf(line, "%x-%x", &start, &stop); + if ( start == mem ) { + size = (Uint32)((stop-start)/1024); + break; + } + } + fclose(proc); + } + return(size); +} + +#ifdef DGA_DEBUG +static void PrintMode(SDL_NAME(XDGAMode) *mode) +{ + printf("Mode: %s (%dx%d) at %d bpp (%f refresh, %d pitch) num: %d\n", + mode->name, + mode->viewportWidth, mode->viewportHeight, + mode->depth == 24 ? mode->bitsPerPixel : mode->depth, + mode->verticalRefresh, mode->bytesPerScanline, mode->num); + printf("\tRGB: 0x%8.8x 0x%8.8x 0x%8.8x (%d - %s)\n", + mode->redMask, mode->greenMask, mode->blueMask, + mode->visualClass, + mode->visualClass == TrueColor ? "truecolor" : + mode->visualClass == DirectColor ? "directcolor" : + mode->visualClass == PseudoColor ? "pseudocolor" : "unknown"); + printf("\tFlags: "); + if ( mode->flags & XDGAConcurrentAccess ) + printf(" XDGAConcurrentAccess"); + if ( mode->flags & XDGASolidFillRect ) + printf(" XDGASolidFillRect"); + if ( mode->flags & XDGABlitRect ) + printf(" XDGABlitRect"); + if ( mode->flags & XDGABlitTransRect ) + printf(" XDGABlitTransRect"); + if ( mode->flags & XDGAPixmap ) + printf(" XDGAPixmap"); + if ( mode->flags & XDGAInterlaced ) + printf(" XDGAInterlaced"); + if ( mode->flags & XDGADoublescan ) + printf(" XDGADoublescan"); + if ( mode->viewportFlags & XDGAFlipRetrace ) + printf(" XDGAFlipRetrace"); + if ( mode->viewportFlags & XDGAFlipImmediate ) + printf(" XDGAFlipImmediate"); + printf("\n"); +} +#endif /* DGA_DEBUG */ + +static int cmpmodes(const void *va, const void *vb) +{ + const SDL_NAME(XDGAMode) *a = (const SDL_NAME(XDGAMode) *)va; + const SDL_NAME(XDGAMode) *b = (const SDL_NAME(XDGAMode) *)vb; + + if ( (a->viewportWidth == b->viewportWidth) && + (b->viewportHeight == a->viewportHeight) ) { + /* Prefer 32 bpp over 24 bpp, 16 bpp over 15 bpp */ + int a_bpp = a->depth == 24 ? a->bitsPerPixel : a->depth; + int b_bpp = b->depth == 24 ? b->bitsPerPixel : b->depth; + if ( a_bpp != b_bpp ) { + return b_bpp - a_bpp; + } + /* Prefer DirectColor visuals, for gamma support */ + if ( a->visualClass == DirectColor && b->visualClass != DirectColor ) + return -1; + if ( b->visualClass == DirectColor && a->visualClass != DirectColor ) + return 1; + /* Maintain server refresh rate sorting */ + return a->num - b->num; + } else if ( a->viewportWidth == b->viewportWidth ) { + return b->viewportHeight - a->viewportHeight; + } else { + return b->viewportWidth - a->viewportWidth; + } +} +static void UpdateHWInfo(_THIS, SDL_NAME(XDGAMode) *mode) +{ + this->info.wm_available = 0; + this->info.hw_available = 1; + if ( mode->flags & XDGABlitRect ) { + this->info.blit_hw = 1; + } else { + this->info.blit_hw = 0; + } + if ( mode->flags & XDGABlitTransRect ) { + this->info.blit_hw_CC = 1; + } else { + this->info.blit_hw_CC = 0; + } + if ( mode->flags & XDGASolidFillRect ) { + this->info.blit_fill = 1; + } else { + this->info.blit_fill = 0; + } + this->info.video_mem = get_video_size(this); +} + +static int DGA_VideoInit(_THIS, SDL_PixelFormat *vformat) +{ + const char *env; + const char *display; + int event_base, error_base; + int major_version, minor_version; + Visual *visual; + SDL_NAME(XDGAMode) *modes; + int i, num_modes; + + /* Open the X11 display */ + display = NULL; /* Get it from DISPLAY environment variable */ + + DGA_Display = XOpenDisplay(display); + if ( DGA_Display == NULL ) { + SDL_SetError("Couldn't open X11 display"); + return(-1); + } + + /* Check for the DGA extension */ + if ( ! SDL_NAME(XDGAQueryExtension)(DGA_Display, &event_base, &error_base) || + ! SDL_NAME(XDGAQueryVersion)(DGA_Display, &major_version, &minor_version) ) { + SDL_SetError("DGA extension not available"); + XCloseDisplay(DGA_Display); + return(-1); + } + if ( major_version < 2 ) { + SDL_SetError("DGA driver requires DGA 2.0 or newer"); + XCloseDisplay(DGA_Display); + return(-1); + } + DGA_event_base = event_base; + + /* Determine the current screen size */ + this->info.current_w = DisplayWidth(DGA_Display, DGA_Screen); + this->info.current_h = DisplayHeight(DGA_Display, DGA_Screen); + + /* Determine the current screen depth */ + visual = DefaultVisual(DGA_Display, DGA_Screen); + { + XPixmapFormatValues *pix_format; + int i, num_formats; + + vformat->BitsPerPixel = DefaultDepth(DGA_Display, DGA_Screen); + pix_format = XListPixmapFormats(DGA_Display, &num_formats); + if ( pix_format == NULL ) { + SDL_SetError("Couldn't determine screen formats"); + XCloseDisplay(DGA_Display); + return(-1); + } + for ( i=0; i<num_formats; ++i ) { + if ( vformat->BitsPerPixel == pix_format[i].depth ) + break; + } + if ( i != num_formats ) + vformat->BitsPerPixel = pix_format[i].bits_per_pixel; + XFree((char *)pix_format); + } + if ( vformat->BitsPerPixel > 8 ) { + vformat->Rmask = visual->red_mask; + vformat->Gmask = visual->green_mask; + vformat->Bmask = visual->blue_mask; + } + + /* Open access to the framebuffer */ + if ( ! SDL_NAME(XDGAOpenFramebuffer)(DGA_Display, DGA_Screen) ) { + SDL_SetError("Unable to map the video memory"); + XCloseDisplay(DGA_Display); + return(-1); + } + + /* Allow environment override of screensaver disable. */ + env = SDL_getenv("SDL_VIDEO_ALLOW_SCREENSAVER"); + if ( env ) { + allow_screensaver = SDL_atoi(env); + } else { +#ifdef SDL_VIDEO_DISABLE_SCREENSAVER + allow_screensaver = 0; +#else + allow_screensaver = 1; +#endif + } + + /* Query for the list of available video modes */ + modes = SDL_NAME(XDGAQueryModes)(DGA_Display, DGA_Screen, &num_modes); + SDL_qsort(modes, num_modes, sizeof *modes, cmpmodes); + for ( i=0; i<num_modes; ++i ) { + if ( ((modes[i].visualClass == PseudoColor) || + (modes[i].visualClass == DirectColor) || + (modes[i].visualClass == TrueColor)) && + !(modes[i].flags & (XDGAInterlaced|XDGADoublescan)) ) { +#ifdef DGA_DEBUG + PrintMode(&modes[i]); +#endif + DGA_AddMode(this, modes[i].bitsPerPixel, + modes[i].viewportWidth, + modes[i].viewportHeight); + } + } + UpdateHWInfo(this, modes); + XFree(modes); + + /* Create the hardware surface lock mutex */ + hw_lock = SDL_CreateMutex(); + if ( hw_lock == NULL ) { + SDL_SetError("Unable to create lock mutex"); + DGA_VideoQuit(this); + return(-1); + } + +#ifdef LOCK_DGA_DISPLAY + /* Create the event lock so we're thread-safe.. :-/ */ + event_lock = SDL_CreateMutex(); +#endif /* LOCK_DGA_DISPLAY */ + + /* We're done! */ + return(0); +} + +SDL_Rect **DGA_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags) +{ + return(SDL_modelist[((format->BitsPerPixel+7)/8)-1]); +} + +/* Various screen update functions available */ +static void DGA_DirectUpdate(_THIS, int numrects, SDL_Rect *rects); + +SDL_Surface *DGA_SetVideoMode(_THIS, SDL_Surface *current, + int width, int height, int bpp, Uint32 flags) +{ + SDL_NAME(XDGAMode) *modes; + int i, num_modes; + SDL_NAME(XDGADevice) *mode; + int screen_len; + Uint8 *surfaces_mem; + int surfaces_len; + + /* Free any previous colormap */ + if ( DGA_colormap ) { + XFreeColormap(DGA_Display, DGA_colormap); + DGA_colormap = 0; + } + + /* Search for a matching video mode */ + modes = SDL_NAME(XDGAQueryModes)(DGA_Display, DGA_Screen, &num_modes); + SDL_qsort(modes, num_modes, sizeof *modes, cmpmodes); + for ( i=0; i<num_modes; ++i ) { + int depth; + + depth = modes[i].depth; + if ( depth == 24 ) { /* Distinguish between 24 and 32 bpp */ + depth = modes[i].bitsPerPixel; + } + if ( (depth == bpp) && + (modes[i].viewportWidth == width) && + (modes[i].viewportHeight == height) && + ((modes[i].visualClass == PseudoColor) || + (modes[i].visualClass == DirectColor) || + (modes[i].visualClass == TrueColor)) && + !(modes[i].flags & (XDGAInterlaced|XDGADoublescan)) ) { + break; + } + } + if ( i == num_modes ) { + SDL_SetError("No matching video mode found"); + return(NULL); + } +#ifdef DGA_DEBUG + PrintMode(&modes[i]); +#endif + + /* Set the video mode */ + mode = SDL_NAME(XDGASetMode)(DGA_Display, DGA_Screen, modes[i].num); + XFree(modes); + if ( mode == NULL ) { + SDL_SetError("Unable to switch to requested mode"); + return(NULL); + } + DGA_visualClass = mode->mode.visualClass; + memory_base = (Uint8 *)mode->data; + memory_pitch = mode->mode.bytesPerScanline; + + /* Set up the new mode framebuffer */ + current->flags = (SDL_FULLSCREEN|SDL_HWSURFACE); + current->w = mode->mode.viewportWidth; + current->h = mode->mode.viewportHeight; + current->pitch = memory_pitch; + current->pixels = memory_base; + if ( ! SDL_ReallocFormat(current, mode->mode.bitsPerPixel, + mode->mode.redMask, + mode->mode.greenMask, + mode->mode.blueMask, 0) ) { + return(NULL); + } + screen_len = current->h*current->pitch; + + /* Create a colormap if necessary */ + if ( (DGA_visualClass == PseudoColor) || + (DGA_visualClass == DirectColor) ) { + DGA_colormap = SDL_NAME(XDGACreateColormap)(DGA_Display, DGA_Screen, + mode, AllocAll); + if ( DGA_visualClass == PseudoColor ) { + current->flags |= SDL_HWPALETTE; + } else { + /* Initialize the colormap to the identity mapping */ + SDL_GetGammaRamp(0, 0, 0); + this->screen = current; + DGA_SetGammaRamp(this, this->gamma); + this->screen = NULL; + } + } else { + DGA_colormap = SDL_NAME(XDGACreateColormap)(DGA_Display, DGA_Screen, + mode, AllocNone); + } + SDL_NAME(XDGAInstallColormap)(DGA_Display, DGA_Screen, DGA_colormap); + + /* Update the hardware capabilities */ + UpdateHWInfo(this, &mode->mode); + + /* Set up the information for hardware surfaces */ + surfaces_mem = (Uint8 *)current->pixels + screen_len; + surfaces_len = (mode->mode.imageHeight*current->pitch - screen_len); + + /* Update for double-buffering, if we can */ + SDL_NAME(XDGASetViewport)(DGA_Display, DGA_Screen, 0, 0, XDGAFlipRetrace); + if ( flags & SDL_DOUBLEBUF ) { + if ( mode->mode.imageHeight >= (current->h*2) ) { + current->flags |= SDL_DOUBLEBUF; + flip_page = 0; + flip_yoffset[0] = 0; + flip_yoffset[1] = current->h; + flip_address[0] = memory_base; + flip_address[1] = memory_base+screen_len; + surfaces_mem += screen_len; + surfaces_len -= screen_len; + } + } + + /* Allocate memory tracking for hardware surfaces */ + DGA_FreeHWSurfaces(this); + if ( surfaces_len < 0 ) { + surfaces_len = 0; + } + DGA_InitHWSurfaces(this, current, surfaces_mem, surfaces_len); + + /* Expose the back buffer as surface memory */ + if ( current->flags & SDL_DOUBLEBUF ) { + this->screen = current; + DGA_FlipHWSurface(this, current); + this->screen = NULL; + } + + /* Set the update rectangle function */ + this->UpdateRects = DGA_DirectUpdate; + + /* Enable mouse and keyboard support */ + { long input_mask; + input_mask = (KeyPressMask | KeyReleaseMask); + input_mask |= (ButtonPressMask | ButtonReleaseMask); + input_mask |= PointerMotionMask; + SDL_NAME(XDGASelectInput)(DGA_Display, DGA_Screen, input_mask); + } + + /* We're done */ + return(current); +} + +#ifdef DGA_DEBUG +static void DGA_DumpHWSurfaces(_THIS) +{ + vidmem_bucket *bucket; + + printf("Memory left: %d (%d total)\n", surfaces_memleft, surfaces_memtotal); + printf("\n"); + printf(" Base Size\n"); + for ( bucket=&surfaces; bucket; bucket=bucket->next ) { + printf("Bucket: %p, %d (%s)\n", bucket->base, bucket->size, bucket->used ? "used" : "free"); + if ( bucket->prev ) { + if ( bucket->base != bucket->prev->base+bucket->prev->size ) { + printf("Warning, corrupt bucket list! (prev)\n"); + } + } else { + if ( bucket != &surfaces ) { + printf("Warning, corrupt bucket list! (!prev)\n"); + } + } + if ( bucket->next ) { + if ( bucket->next->base != bucket->base+bucket->size ) { + printf("Warning, corrupt bucket list! (next)\n"); + } + } + } + printf("\n"); +} +#endif + +static int DGA_InitHWSurfaces(_THIS, SDL_Surface *screen, Uint8 *base, int size) +{ + vidmem_bucket *bucket; + + surfaces_memtotal = size; + surfaces_memleft = size; + + if ( surfaces_memleft > 0 ) { + bucket = (vidmem_bucket *)SDL_malloc(sizeof(*bucket)); + if ( bucket == NULL ) { + SDL_OutOfMemory(); + return(-1); + } + bucket->prev = &surfaces; + bucket->used = 0; + bucket->dirty = 0; + bucket->base = base; + bucket->size = size; + bucket->next = NULL; + } else { + bucket = NULL; + } + + surfaces.prev = NULL; + surfaces.used = 1; + surfaces.dirty = 0; + surfaces.base = screen->pixels; + surfaces.size = (unsigned int)((long)base - (long)surfaces.base); + surfaces.next = bucket; + screen->hwdata = (struct private_hwdata *)((char*)&surfaces); + return(0); +} +static void DGA_FreeHWSurfaces(_THIS) +{ + vidmem_bucket *bucket, *freeable; + + bucket = surfaces.next; + while ( bucket ) { + freeable = bucket; + bucket = bucket->next; + SDL_free(freeable); + } + surfaces.next = NULL; +} + +static __inline__ void DGA_AddBusySurface(SDL_Surface *surface) +{ + ((vidmem_bucket *)surface->hwdata)->dirty = 1; +} + +static __inline__ int DGA_IsSurfaceBusy(SDL_Surface *surface) +{ + return ((vidmem_bucket *)surface->hwdata)->dirty; +} + +static __inline__ void DGA_WaitBusySurfaces(_THIS) +{ + vidmem_bucket *bucket; + + /* Wait for graphic operations to complete */ + SDL_NAME(XDGASync)(DGA_Display, DGA_Screen); + + /* Clear all surface dirty bits */ + for ( bucket=&surfaces; bucket; bucket=bucket->next ) { + bucket->dirty = 0; + } +} + +static int DGA_AllocHWSurface(_THIS, SDL_Surface *surface) +{ + vidmem_bucket *bucket; + int size; + int extra; + int retval = 0; + +/* Temporarily, we only allow surfaces the same width as display. + Some blitters require the pitch between two hardware surfaces + to be the same. Others have interesting alignment restrictions. +*/ +if ( surface->pitch > SDL_VideoSurface->pitch ) { + SDL_SetError("Surface requested wider than screen"); + return(-1); +} +surface->pitch = SDL_VideoSurface->pitch; + size = surface->h * surface->pitch; +#ifdef DGA_DEBUG + fprintf(stderr, "Allocating bucket of %d bytes\n", size); +#endif + LOCK_DISPLAY(); + + /* Quick check for available mem */ + if ( size > surfaces_memleft ) { + SDL_SetError("Not enough video memory"); + retval = -1; + goto done; + } + + /* Search for an empty bucket big enough */ + for ( bucket=&surfaces; bucket; bucket=bucket->next ) { + if ( ! bucket->used && (size <= bucket->size) ) { + break; + } + } + if ( bucket == NULL ) { + SDL_SetError("Video memory too fragmented"); + retval = -1; + goto done; + } + + /* Create a new bucket for left-over memory */ + extra = (bucket->size - size); + if ( extra ) { + vidmem_bucket *newbucket; + +#ifdef DGA_DEBUG + fprintf(stderr, "Adding new free bucket of %d bytes\n", extra); +#endif + newbucket = (vidmem_bucket *)SDL_malloc(sizeof(*newbucket)); + if ( newbucket == NULL ) { + SDL_OutOfMemory(); + retval = -1; + goto done; + } + newbucket->prev = bucket; + newbucket->used = 0; + newbucket->base = bucket->base+size; + newbucket->size = extra; + newbucket->next = bucket->next; + if ( bucket->next ) { + bucket->next->prev = newbucket; + } + bucket->next = newbucket; + } + + /* Set the current bucket values and return it! */ + bucket->used = 1; + bucket->size = size; + bucket->dirty = 0; +#ifdef DGA_DEBUG + fprintf(stderr, "Allocated %d bytes at %p\n", bucket->size, bucket->base); +#endif + surfaces_memleft -= size; + surface->flags |= SDL_HWSURFACE; + surface->pixels = bucket->base; + surface->hwdata = (struct private_hwdata *)bucket; +done: + UNLOCK_DISPLAY(); + return(retval); +} +static void DGA_FreeHWSurface(_THIS, SDL_Surface *surface) +{ + vidmem_bucket *bucket, *freeable; + + /* Wait for any pending operations involving this surface */ + if ( DGA_IsSurfaceBusy(surface) ) { + LOCK_DISPLAY(); + DGA_WaitBusySurfaces(this); + UNLOCK_DISPLAY(); + } + + /* Look for the bucket in the current list */ + for ( bucket=&surfaces; bucket; bucket=bucket->next ) { + if ( bucket == (vidmem_bucket *)surface->hwdata ) { + break; + } + } + if ( bucket && bucket->used ) { + /* Add the memory back to the total */ +#ifdef DGA_DEBUG + printf("Freeing bucket of %d bytes\n", bucket->size); +#endif + surfaces_memleft += bucket->size; + + /* Can we merge the space with surrounding buckets? */ + bucket->used = 0; + if ( bucket->next && ! bucket->next->used ) { +#ifdef DGA_DEBUG + printf("Merging with next bucket, for %d total bytes\n", bucket->size+bucket->next->size); +#endif + freeable = bucket->next; + bucket->size += bucket->next->size; + bucket->next = bucket->next->next; + if ( bucket->next ) { + bucket->next->prev = bucket; + } + SDL_free(freeable); + } + if ( bucket->prev && ! bucket->prev->used ) { +#ifdef DGA_DEBUG + printf("Merging with previous bucket, for %d total bytes\n", bucket->prev->size+bucket->size); +#endif + freeable = bucket; + bucket->prev->size += bucket->size; + bucket->prev->next = bucket->next; + if ( bucket->next ) { + bucket->next->prev = bucket->prev; + } + SDL_free(freeable); + } + } + surface->pixels = NULL; + surface->hwdata = NULL; +} + +static __inline__ void DGA_dst_to_xy(_THIS, SDL_Surface *dst, int *x, int *y) +{ + *x = (long)((Uint8 *)dst->pixels - memory_base)%memory_pitch; + *y = (long)((Uint8 *)dst->pixels - memory_base)/memory_pitch; +} + +static int DGA_FillHWRect(_THIS, SDL_Surface *dst, SDL_Rect *rect, Uint32 color) +{ + int x, y; + unsigned int w, h; + + /* Don't fill the visible part of the screen, wait until flipped */ + LOCK_DISPLAY(); + if ( was_flipped && (dst == this->screen) ) { + while ( SDL_NAME(XDGAGetViewportStatus)(DGA_Display, DGA_Screen) ) + /* Keep waiting for the hardware ... */ ; + was_flipped = 0; + } + DGA_dst_to_xy(this, dst, &x, &y); + x += rect->x; + y += rect->y; + w = rect->w; + h = rect->h; +#if 0 + printf("Hardware accelerated rectangle fill: %dx%d at %d,%d\n", w, h, x, y); +#endif + SDL_NAME(XDGAFillRectangle)(DGA_Display, DGA_Screen, x, y, w, h, color); + if ( !(this->screen->flags & SDL_DOUBLEBUF) ) { + XFlush(DGA_Display); + } + DGA_AddBusySurface(dst); + UNLOCK_DISPLAY(); + return(0); +} + +static int HWAccelBlit(SDL_Surface *src, SDL_Rect *srcrect, + SDL_Surface *dst, SDL_Rect *dstrect) +{ + SDL_VideoDevice *this; + int srcx, srcy; + int dstx, dsty; + unsigned int w, h; + + this = current_video; + /* Don't blit to the visible part of the screen, wait until flipped */ + LOCK_DISPLAY(); + if ( was_flipped && (dst == this->screen) ) { + while ( SDL_NAME(XDGAGetViewportStatus)(DGA_Display, DGA_Screen) ) + /* Keep waiting for the hardware ... */ ; + was_flipped = 0; + } + DGA_dst_to_xy(this, src, &srcx, &srcy); + srcx += srcrect->x; + srcy += srcrect->y; + DGA_dst_to_xy(this, dst, &dstx, &dsty); + dstx += dstrect->x; + dsty += dstrect->y; + w = srcrect->w; + h = srcrect->h; +#if 0 + printf("Blitting %dx%d from %d,%d to %d,%d\n", w, h, srcx, srcy, dstx, dsty); +#endif + if ( (src->flags & SDL_SRCCOLORKEY) == SDL_SRCCOLORKEY ) { + SDL_NAME(XDGACopyTransparentArea)(DGA_Display, DGA_Screen, + srcx, srcy, w, h, dstx, dsty, src->format->colorkey); + } else { + SDL_NAME(XDGACopyArea)(DGA_Display, DGA_Screen, + srcx, srcy, w, h, dstx, dsty); + } + if ( !(this->screen->flags & SDL_DOUBLEBUF) ) { + XFlush(DGA_Display); + } + DGA_AddBusySurface(src); + DGA_AddBusySurface(dst); + UNLOCK_DISPLAY(); + return(0); +} + +static int DGA_CheckHWBlit(_THIS, SDL_Surface *src, SDL_Surface *dst) +{ + int accelerated; + + /* Set initial acceleration on */ + src->flags |= SDL_HWACCEL; + + /* Set the surface attributes */ + if ( (src->flags & SDL_SRCALPHA) == SDL_SRCALPHA ) { + if ( ! this->info.blit_hw_A ) { + src->flags &= ~SDL_HWACCEL; + } + } + if ( (src->flags & SDL_SRCCOLORKEY) == SDL_SRCCOLORKEY ) { + if ( ! this->info.blit_hw_CC ) { + src->flags &= ~SDL_HWACCEL; + } + } + + /* Check to see if final surface blit is accelerated */ + accelerated = !!(src->flags & SDL_HWACCEL); + if ( accelerated ) { + src->map->hw_blit = HWAccelBlit; + } + return(accelerated); +} + +static __inline__ void DGA_WaitFlip(_THIS) +{ + if ( was_flipped ) { + while ( SDL_NAME(XDGAGetViewportStatus)(DGA_Display, DGA_Screen) ) + /* Keep waiting for the hardware ... */ ; + was_flipped = 0; + } +} + +static int DGA_LockHWSurface(_THIS, SDL_Surface *surface) +{ + if ( surface == this->screen ) { + SDL_mutexP(hw_lock); + LOCK_DISPLAY(); + if ( DGA_IsSurfaceBusy(surface) ) { + DGA_WaitBusySurfaces(this); + } + DGA_WaitFlip(this); + UNLOCK_DISPLAY(); + } else { + if ( DGA_IsSurfaceBusy(surface) ) { + LOCK_DISPLAY(); + DGA_WaitBusySurfaces(this); + UNLOCK_DISPLAY(); + } + } + return(0); +} +static void DGA_UnlockHWSurface(_THIS, SDL_Surface *surface) +{ + if ( surface == this->screen ) { + SDL_mutexV(hw_lock); + } +} + +static int DGA_FlipHWSurface(_THIS, SDL_Surface *surface) +{ + /* Wait for vertical retrace and then flip display */ + LOCK_DISPLAY(); + if ( DGA_IsSurfaceBusy(this->screen) ) { + DGA_WaitBusySurfaces(this); + } + DGA_WaitFlip(this); + SDL_NAME(XDGASetViewport)(DGA_Display, DGA_Screen, + 0, flip_yoffset[flip_page], XDGAFlipRetrace); + XFlush(DGA_Display); + UNLOCK_DISPLAY(); + was_flipped = 1; + flip_page = !flip_page; + + surface->pixels = flip_address[flip_page]; + return(0); +} + +static void DGA_DirectUpdate(_THIS, int numrects, SDL_Rect *rects) +{ + /* The application is already updating the visible video memory */ + return; +} + +static int DGA_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors) +{ + int i; + XColor *xcmap; + + /* This happens on initialization */ + if ( ! DGA_colormap ) { + return(0); + } + xcmap = SDL_stack_alloc(XColor, ncolors); + for ( i=0; i<ncolors; ++i ) { + xcmap[i].pixel = firstcolor + i; + xcmap[i].red = (colors[i].r<<8)|colors[i].r; + xcmap[i].green = (colors[i].g<<8)|colors[i].g; + xcmap[i].blue = (colors[i].b<<8)|colors[i].b; + xcmap[i].flags = (DoRed|DoGreen|DoBlue); + } + LOCK_DISPLAY(); + XStoreColors(DGA_Display, DGA_colormap, xcmap, ncolors); + XSync(DGA_Display, False); + UNLOCK_DISPLAY(); + SDL_stack_free(xcmap); + + /* That was easy. :) */ + return(1); +} + +int DGA_SetGammaRamp(_THIS, Uint16 *ramp) +{ + int i, ncolors; + XColor xcmap[256]; + + /* See if actually setting the gamma is supported */ + if ( DGA_visualClass != DirectColor ) { + SDL_SetError("Gamma correction not supported on this visual"); + return(-1); + } + + /* Calculate the appropriate palette for the given gamma ramp */ + if ( this->screen->format->BitsPerPixel <= 16 ) { + ncolors = 64; /* Is this right? */ + } else { + ncolors = 256; + } + for ( i=0; i<ncolors; ++i ) { + Uint8 c = (256 * i / ncolors); + xcmap[i].pixel = SDL_MapRGB(this->screen->format, c, c, c); + xcmap[i].red = ramp[0*256+c]; + xcmap[i].green = ramp[1*256+c]; + xcmap[i].blue = ramp[2*256+c]; + xcmap[i].flags = (DoRed|DoGreen|DoBlue); + } + LOCK_DISPLAY(); + XStoreColors(DGA_Display, DGA_colormap, xcmap, ncolors); + XSync(DGA_Display, False); + UNLOCK_DISPLAY(); + return(0); +} + +void DGA_VideoQuit(_THIS) +{ + int i, j; + + if ( DGA_Display ) { + /* Free colormap, if necessary */ + if ( DGA_colormap ) { + XFreeColormap(DGA_Display, DGA_colormap); + DGA_colormap = 0; + } + + /* Unmap memory and reset video mode */ + SDL_NAME(XDGACloseFramebuffer)(DGA_Display, DGA_Screen); + if ( this->screen ) { + /* Tell SDL not to free the pixels */ + DGA_FreeHWSurface(this, this->screen); + } + SDL_NAME(XDGASetMode)(DGA_Display, DGA_Screen, 0); + + /* Clear the lock mutex */ + if ( hw_lock != NULL ) { + SDL_DestroyMutex(hw_lock); + hw_lock = NULL; + } +#ifdef LOCK_DGA_DISPLAY + if ( event_lock != NULL ) { + SDL_DestroyMutex(event_lock); + event_lock = NULL; + } +#endif /* LOCK_DGA_DISPLAY */ + + /* Clean up defined video modes */ + for ( i=0; i<NUM_MODELISTS; ++i ) { + if ( SDL_modelist[i] != NULL ) { + for ( j=0; SDL_modelist[i][j]; ++j ) { + SDL_free(SDL_modelist[i][j]); + } + SDL_free(SDL_modelist[i]); + SDL_modelist[i] = NULL; + } + } + + /* Clean up the memory bucket list */ + DGA_FreeHWSurfaces(this); + + /* Close up the display */ + XCloseDisplay(DGA_Display); + } +} diff --git a/3rdparty/SDL/src/video/dga/SDL_dgavideo.h b/3rdparty/SDL/src/video/dga/SDL_dgavideo.h new file mode 100644 index 0000000..bd2ecb8 --- /dev/null +++ b/3rdparty/SDL/src/video/dga/SDL_dgavideo.h @@ -0,0 +1,124 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#ifndef _SDL_dgavideo_h +#define _SDL_dgavideo_h + +#include <X11/Xlib.h> + +/* Apparently some X11 systems can't include this multiple times... */ +#ifndef SDL_INCLUDED_XLIBINT_H +#define SDL_INCLUDED_XLIBINT_H 1 +#include <X11/Xlibint.h> +#endif + +#include <X11/Xproto.h> + +#include "SDL_mouse.h" +#include "SDL_mutex.h" +#include "../SDL_sysvideo.h" + +/* Hidden "this" pointer for the video functions */ +#define _THIS SDL_VideoDevice *this + +/* Define this if you need the DGA driver to be thread-safe */ +#define LOCK_DGA_DISPLAY +#ifdef LOCK_DGA_DISPLAY +#define LOCK_DISPLAY() SDL_mutexP(event_lock) +#define UNLOCK_DISPLAY() SDL_mutexV(event_lock) +#else +#define LOCK_DISPLAY() +#define UNLOCK_DISPLAY() +#endif + + +/* This is the structure we use to keep track of video memory */ +typedef struct vidmem_bucket { + struct vidmem_bucket *prev; + int used; + int dirty; + Uint8 *base; + unsigned int size; + struct vidmem_bucket *next; +} vidmem_bucket; + +/* Private display data */ +struct SDL_PrivateVideoData { + Display *DGA_Display; + Colormap DGA_colormap; + int visualClass; + +#define NUM_MODELISTS 4 /* 8, 16, 24, and 32 bits-per-pixel */ + int SDL_nummodes[NUM_MODELISTS]; + SDL_Rect **SDL_modelist[NUM_MODELISTS]; + + /* Information for the video surface */ + Uint8 *memory_base; + int memory_pitch; + SDL_mutex *hw_lock; + int sync_needed; + int was_flipped; + + /* Information for hardware surfaces */ + vidmem_bucket surfaces; + int surfaces_memtotal; + int surfaces_memleft; + + /* Information for double-buffering */ + int flip_page; + int flip_yoffset[2]; + Uint8 *flip_address[2]; + + /* Used to handle DGA events */ + int event_base; +#ifdef LOCK_DGA_DISPLAY + SDL_mutex *event_lock; +#endif + + /* Screensaver settings */ + int allow_screensaver; +}; + +/* Old variable names */ +#define DGA_Display (this->hidden->DGA_Display) +#define DGA_Screen DefaultScreen(DGA_Display) +#define DGA_colormap (this->hidden->DGA_colormap) +#define DGA_visualClass (this->hidden->visualClass) +#define memory_base (this->hidden->memory_base) +#define memory_pitch (this->hidden->memory_pitch) +#define flip_page (this->hidden->flip_page) +#define flip_yoffset (this->hidden->flip_yoffset) +#define flip_address (this->hidden->flip_address) +#define sync_needed (this->hidden->sync_needed) +#define was_flipped (this->hidden->was_flipped) +#define SDL_nummodes (this->hidden->SDL_nummodes) +#define SDL_modelist (this->hidden->SDL_modelist) +#define surfaces (this->hidden->surfaces) +#define surfaces_memtotal (this->hidden->surfaces_memtotal) +#define surfaces_memleft (this->hidden->surfaces_memleft) +#define hw_lock (this->hidden->hw_lock) +#define DGA_event_base (this->hidden->event_base) +#define event_lock (this->hidden->event_lock) +#define allow_screensaver (this->hidden->allow_screensaver) + +#endif /* _SDL_dgavideo_h */ diff --git a/3rdparty/SDL/src/video/directfb/SDL_DirectFB_events.c b/3rdparty/SDL/src/video/directfb/SDL_DirectFB_events.c new file mode 100644 index 0000000..246b75b --- /dev/null +++ b/3rdparty/SDL/src/video/directfb/SDL_DirectFB_events.c @@ -0,0 +1,219 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* Handle the event stream, converting DirectFB input events into SDL events */ + +#include <sys/types.h> +#include <sys/time.h> +#include <unistd.h> +#include <fcntl.h> +#include <termios.h> + +#include <directfb.h> + +#include "SDL.h" +#include "../SDL_sysvideo.h" +#include "../../events/SDL_sysevents.h" +#include "../../events/SDL_events_c.h" +#include "SDL_DirectFB_video.h" +#include "SDL_DirectFB_events.h" + +/* The translation tables from a DirectFB keycode to a SDL keysym */ +static SDLKey keymap[256]; +static SDL_keysym *DirectFB_TranslateKey (DFBInputEvent *ev, SDL_keysym *keysym); +static int DirectFB_TranslateButton (DFBInputEvent *ev); + +static int posted = 0; + + +void DirectFB_PumpEvents (_THIS) +{ + DFBInputEvent evt; + + while (HIDDEN->eventbuffer->GetEvent (HIDDEN->eventbuffer, + DFB_EVENT (&evt)) == DFB_OK) + { + SDL_keysym keysym; + + switch (evt.type) + { + case DIET_BUTTONPRESS: + posted += SDL_PrivateMouseButton(SDL_PRESSED, + DirectFB_TranslateButton (&evt), 0, 0); + break; + case DIET_BUTTONRELEASE: + posted += SDL_PrivateMouseButton(SDL_RELEASED, + DirectFB_TranslateButton (&evt), 0, 0); + break; + case DIET_KEYPRESS: + posted += SDL_PrivateKeyboard(SDL_PRESSED, DirectFB_TranslateKey(&evt, &keysym)); + break; + case DIET_KEYRELEASE: + posted += SDL_PrivateKeyboard(SDL_RELEASED, DirectFB_TranslateKey(&evt, &keysym)); + break; + case DIET_AXISMOTION: + if (evt.flags & DIEF_AXISREL) + { + if (evt.axis == DIAI_X) + posted += SDL_PrivateMouseMotion(0, 1, evt.axisrel, 0); + else if (evt.axis == DIAI_Y) + posted += SDL_PrivateMouseMotion(0, 1, 0, evt.axisrel); + } + else if (evt.flags & DIEF_AXISABS) + { + static int last_x, last_y; + if (evt.axis == DIAI_X) + last_x = evt.axisabs; + else if (evt.axis == DIAI_Y) + last_y = evt.axisabs; + posted += SDL_PrivateMouseMotion(0, 0, last_x, last_y); + } + break; + default: + ; + } + } +} + +void DirectFB_InitOSKeymap (_THIS) +{ + int i; + + /* Initialize the DirectFB key translation table */ + for (i=0; i<SDL_arraysize(keymap); ++i) + keymap[i] = SDLK_UNKNOWN; + + keymap[DIKI_A - DIKI_UNKNOWN] = SDLK_a; + keymap[DIKI_B - DIKI_UNKNOWN] = SDLK_b; + keymap[DIKI_C - DIKI_UNKNOWN] = SDLK_c; + keymap[DIKI_D - DIKI_UNKNOWN] = SDLK_d; + keymap[DIKI_E - DIKI_UNKNOWN] = SDLK_e; + keymap[DIKI_F - DIKI_UNKNOWN] = SDLK_f; + keymap[DIKI_G - DIKI_UNKNOWN] = SDLK_g; + keymap[DIKI_H - DIKI_UNKNOWN] = SDLK_h; + keymap[DIKI_I - DIKI_UNKNOWN] = SDLK_i; + keymap[DIKI_J - DIKI_UNKNOWN] = SDLK_j; + keymap[DIKI_K - DIKI_UNKNOWN] = SDLK_k; + keymap[DIKI_L - DIKI_UNKNOWN] = SDLK_l; + keymap[DIKI_M - DIKI_UNKNOWN] = SDLK_m; + keymap[DIKI_N - DIKI_UNKNOWN] = SDLK_n; + keymap[DIKI_O - DIKI_UNKNOWN] = SDLK_o; + keymap[DIKI_P - DIKI_UNKNOWN] = SDLK_p; + keymap[DIKI_Q - DIKI_UNKNOWN] = SDLK_q; + keymap[DIKI_R - DIKI_UNKNOWN] = SDLK_r; + keymap[DIKI_S - DIKI_UNKNOWN] = SDLK_s; + keymap[DIKI_T - DIKI_UNKNOWN] = SDLK_t; + keymap[DIKI_U - DIKI_UNKNOWN] = SDLK_u; + keymap[DIKI_V - DIKI_UNKNOWN] = SDLK_v; + keymap[DIKI_W - DIKI_UNKNOWN] = SDLK_w; + keymap[DIKI_X - DIKI_UNKNOWN] = SDLK_x; + keymap[DIKI_Y - DIKI_UNKNOWN] = SDLK_y; + keymap[DIKI_Z - DIKI_UNKNOWN] = SDLK_z; + + keymap[DIKI_0 - DIKI_UNKNOWN] = SDLK_0; + keymap[DIKI_1 - DIKI_UNKNOWN] = SDLK_1; + keymap[DIKI_2 - DIKI_UNKNOWN] = SDLK_2; + keymap[DIKI_3 - DIKI_UNKNOWN] = SDLK_3; + keymap[DIKI_4 - DIKI_UNKNOWN] = SDLK_4; + keymap[DIKI_5 - DIKI_UNKNOWN] = SDLK_5; + keymap[DIKI_6 - DIKI_UNKNOWN] = SDLK_6; + keymap[DIKI_7 - DIKI_UNKNOWN] = SDLK_7; + keymap[DIKI_8 - DIKI_UNKNOWN] = SDLK_8; + keymap[DIKI_9 - DIKI_UNKNOWN] = SDLK_9; + + keymap[DIKI_F1 - DIKI_UNKNOWN] = SDLK_F1; + keymap[DIKI_F2 - DIKI_UNKNOWN] = SDLK_F2; + keymap[DIKI_F3 - DIKI_UNKNOWN] = SDLK_F3; + keymap[DIKI_F4 - DIKI_UNKNOWN] = SDLK_F4; + keymap[DIKI_F5 - DIKI_UNKNOWN] = SDLK_F5; + keymap[DIKI_F6 - DIKI_UNKNOWN] = SDLK_F6; + keymap[DIKI_F7 - DIKI_UNKNOWN] = SDLK_F7; + keymap[DIKI_F8 - DIKI_UNKNOWN] = SDLK_F8; + keymap[DIKI_F9 - DIKI_UNKNOWN] = SDLK_F9; + keymap[DIKI_F10 - DIKI_UNKNOWN] = SDLK_F10; + keymap[DIKI_F11 - DIKI_UNKNOWN] = SDLK_F11; + keymap[DIKI_F12 - DIKI_UNKNOWN] = SDLK_F12; + + keymap[DIKI_ESCAPE - DIKI_UNKNOWN] = SDLK_ESCAPE; + keymap[DIKI_LEFT - DIKI_UNKNOWN] = SDLK_LEFT; + keymap[DIKI_RIGHT - DIKI_UNKNOWN] = SDLK_RIGHT; + keymap[DIKI_UP - DIKI_UNKNOWN] = SDLK_UP; + keymap[DIKI_DOWN - DIKI_UNKNOWN] = SDLK_DOWN; + keymap[DIKI_CONTROL_L - DIKI_UNKNOWN] = SDLK_LCTRL; + keymap[DIKI_CONTROL_R - DIKI_UNKNOWN] = SDLK_RCTRL; + keymap[DIKI_SHIFT_L - DIKI_UNKNOWN] = SDLK_LSHIFT; + keymap[DIKI_SHIFT_R - DIKI_UNKNOWN] = SDLK_RSHIFT; + keymap[DIKI_ALT_L - DIKI_UNKNOWN] = SDLK_LALT; + keymap[DIKI_ALT_R - DIKI_UNKNOWN] = SDLK_RALT; + keymap[DIKI_TAB - DIKI_UNKNOWN] = SDLK_TAB; + keymap[DIKI_ENTER - DIKI_UNKNOWN] = SDLK_RETURN; + keymap[DIKI_SPACE - DIKI_UNKNOWN] = SDLK_SPACE; + keymap[DIKI_BACKSPACE - DIKI_UNKNOWN] = SDLK_BACKSPACE; + keymap[DIKI_INSERT - DIKI_UNKNOWN] = SDLK_INSERT; + keymap[DIKI_DELETE - DIKI_UNKNOWN] = SDLK_DELETE; + keymap[DIKI_HOME - DIKI_UNKNOWN] = SDLK_HOME; + keymap[DIKI_END - DIKI_UNKNOWN] = SDLK_END; + keymap[DIKI_PAGE_UP - DIKI_UNKNOWN] = SDLK_PAGEUP; + keymap[DIKI_PAGE_DOWN - DIKI_UNKNOWN] = SDLK_PAGEDOWN; + keymap[DIKI_CAPS_LOCK - DIKI_UNKNOWN] = SDLK_CAPSLOCK; + keymap[DIKI_NUM_LOCK - DIKI_UNKNOWN] = SDLK_NUMLOCK; + keymap[DIKI_SCROLL_LOCK - DIKI_UNKNOWN] = SDLK_SCROLLOCK; + keymap[DIKI_PRINT - DIKI_UNKNOWN] = SDLK_PRINT; + keymap[DIKI_PAUSE - DIKI_UNKNOWN] = SDLK_PAUSE; + keymap[DIKI_KP_DIV - DIKI_UNKNOWN] = SDLK_KP_DIVIDE; + keymap[DIKI_KP_MULT - DIKI_UNKNOWN] = SDLK_KP_MULTIPLY; + keymap[DIKI_KP_MINUS - DIKI_UNKNOWN] = SDLK_KP_MINUS; + keymap[DIKI_KP_PLUS - DIKI_UNKNOWN] = SDLK_KP_PLUS; + keymap[DIKI_KP_ENTER - DIKI_UNKNOWN] = SDLK_KP_ENTER; +} + + +static SDL_keysym *DirectFB_TranslateKey (DFBInputEvent *ev, SDL_keysym *keysym) +{ + /* Set the keysym information */ + keysym->scancode = ev->key_id; + keysym->mod = KMOD_NONE; /* FIXME */ + keysym->unicode = (DFB_KEY_TYPE (ev->key_symbol) == DIKT_UNICODE) ? ev->key_symbol : 0; + + if (ev->key_symbol > 0 && ev->key_symbol < 128) + keysym->sym = ev->key_symbol; + else + keysym->sym = keymap[ev->key_id - DIKI_UNKNOWN]; + + return keysym; +} + +static int DirectFB_TranslateButton (DFBInputEvent *ev) +{ + switch (ev->button) + { + case DIBI_LEFT: + return 1; + case DIBI_MIDDLE: + return 2; + case DIBI_RIGHT: + return 3; + default: + return 0; + } +} diff --git a/3rdparty/SDL/src/video/directfb/SDL_DirectFB_events.h b/3rdparty/SDL/src/video/directfb/SDL_DirectFB_events.h new file mode 100644 index 0000000..20f3967 --- /dev/null +++ b/3rdparty/SDL/src/video/directfb/SDL_DirectFB_events.h @@ -0,0 +1,29 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#include "SDL_DirectFB_video.h" + +/* Functions to be exported */ +extern void DirectFB_InitOSKeymap(_THIS); +extern void DirectFB_PumpEvents(_THIS); + diff --git a/3rdparty/SDL/src/video/directfb/SDL_DirectFB_keys.h b/3rdparty/SDL/src/video/directfb/SDL_DirectFB_keys.h new file mode 100644 index 0000000..2868ee6 --- /dev/null +++ b/3rdparty/SDL/src/video/directfb/SDL_DirectFB_keys.h @@ -0,0 +1,135 @@ + +#define SCANCODE_ESCAPE 1 + +#define SCANCODE_1 2 +#define SCANCODE_2 3 +#define SCANCODE_3 4 +#define SCANCODE_4 5 +#define SCANCODE_5 6 +#define SCANCODE_6 7 +#define SCANCODE_7 8 +#define SCANCODE_8 9 +#define SCANCODE_9 10 +#define SCANCODE_0 11 + +#define SCANCODE_MINUS 12 +#define SCANCODE_EQUAL 13 + +#define SCANCODE_BACKSPACE 14 +#define SCANCODE_TAB 15 + +#define SCANCODE_Q 16 +#define SCANCODE_W 17 +#define SCANCODE_E 18 +#define SCANCODE_R 19 +#define SCANCODE_T 20 +#define SCANCODE_Y 21 +#define SCANCODE_U 22 +#define SCANCODE_I 23 +#define SCANCODE_O 24 +#define SCANCODE_P 25 +#define SCANCODE_BRACKET_LEFT 26 +#define SCANCODE_BRACKET_RIGHT 27 + +#define SCANCODE_ENTER 28 + +#define SCANCODE_LEFTCONTROL 29 + +#define SCANCODE_A 30 +#define SCANCODE_S 31 +#define SCANCODE_D 32 +#define SCANCODE_F 33 +#define SCANCODE_G 34 +#define SCANCODE_H 35 +#define SCANCODE_J 36 +#define SCANCODE_K 37 +#define SCANCODE_L 38 +#define SCANCODE_SEMICOLON 39 +#define SCANCODE_APOSTROPHE 40 +#define SCANCODE_GRAVE 41 + +#define SCANCODE_LEFTSHIFT 42 +#define SCANCODE_BACKSLASH 43 + +#define SCANCODE_Z 44 +#define SCANCODE_X 45 +#define SCANCODE_C 46 +#define SCANCODE_V 47 +#define SCANCODE_B 48 +#define SCANCODE_N 49 +#define SCANCODE_M 50 +#define SCANCODE_COMMA 51 +#define SCANCODE_PERIOD 52 +#define SCANCODE_SLASH 53 + +#define SCANCODE_RIGHTSHIFT 54 +#define SCANCODE_KEYPADMULTIPLY 55 + +#define SCANCODE_LEFTALT 56 +#define SCANCODE_SPACE 57 +#define SCANCODE_CAPSLOCK 58 + +#define SCANCODE_F1 59 +#define SCANCODE_F2 60 +#define SCANCODE_F3 61 +#define SCANCODE_F4 62 +#define SCANCODE_F5 63 +#define SCANCODE_F6 64 +#define SCANCODE_F7 65 +#define SCANCODE_F8 66 +#define SCANCODE_F9 67 +#define SCANCODE_F10 68 + +#define SCANCODE_NUMLOCK 69 +#define SCANCODE_SCROLLLOCK 70 + +#define SCANCODE_KEYPAD7 71 +#define SCANCODE_CURSORUPLEFT 71 +#define SCANCODE_KEYPAD8 72 +#define SCANCODE_CURSORUP 72 +#define SCANCODE_KEYPAD9 73 +#define SCANCODE_CURSORUPRIGHT 73 +#define SCANCODE_KEYPADMINUS 74 +#define SCANCODE_KEYPAD4 75 +#define SCANCODE_CURSORLEFT 75 +#define SCANCODE_KEYPAD5 76 +#define SCANCODE_KEYPAD6 77 +#define SCANCODE_CURSORRIGHT 77 +#define SCANCODE_KEYPADPLUS 78 +#define SCANCODE_KEYPAD1 79 +#define SCANCODE_CURSORDOWNLEFT 79 +#define SCANCODE_KEYPAD2 80 +#define SCANCODE_CURSORDOWN 80 +#define SCANCODE_KEYPAD3 81 +#define SCANCODE_CURSORDOWNRIGHT 81 +#define SCANCODE_KEYPAD0 82 +#define SCANCODE_KEYPADPERIOD 83 + +#define SCANCODE_LESS 86 + +#define SCANCODE_F11 87 +#define SCANCODE_F12 88 + +#define SCANCODE_KEYPADENTER 96 +#define SCANCODE_RIGHTCONTROL 97 +#define SCANCODE_CONTROL 97 +#define SCANCODE_KEYPADDIVIDE 98 +#define SCANCODE_PRINTSCREEN 99 +#define SCANCODE_RIGHTALT 100 +#define SCANCODE_BREAK 101 /* Beware: is 119 */ +#define SCANCODE_BREAK_ALTERNATIVE 119 /* on some keyboards! */ + +#define SCANCODE_HOME 102 +#define SCANCODE_CURSORBLOCKUP 90 /* Cursor key block */ +#define SCANCODE_PAGEUP 104 +#define SCANCODE_CURSORBLOCKLEFT 92 /* Cursor key block */ +#define SCANCODE_CURSORBLOCKRIGHT 94 /* Cursor key block */ +#define SCANCODE_END 107 +#define SCANCODE_CURSORBLOCKDOWN 108 /* Cursor key block */ +#define SCANCODE_PAGEDOWN 109 +#define SCANCODE_INSERT 110 +#define SCANCODE_REMOVE 111 + +#define SCANCODE_RIGHTWIN 126 +#define SCANCODE_LEFTWIN 125 + diff --git a/3rdparty/SDL/src/video/directfb/SDL_DirectFB_video.c b/3rdparty/SDL/src/video/directfb/SDL_DirectFB_video.c new file mode 100644 index 0000000..f665ec6 --- /dev/null +++ b/3rdparty/SDL/src/video/directfb/SDL_DirectFB_video.c @@ -0,0 +1,1171 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org + + MGA CRTC2 support by Thomas Jarosch - tomj@simonv.com + CRTC2 support is inspired by mplayer's dfbmga driver + written by Ville Syrj��<syrjala@sci.fi> +*/ +#include "SDL_config.h" + +/* DirectFB video driver implementation. +*/ + +#include <fcntl.h> +#include <unistd.h> +#include <sys/mman.h> + +#include <directfb.h> +#include <directfb_version.h> + +#include "SDL_video.h" +#include "SDL_mouse.h" +#include "../SDL_sysvideo.h" +#include "../SDL_pixels_c.h" +#include "../../events/SDL_events_c.h" +#include "SDL_DirectFB_video.h" +#include "SDL_DirectFB_events.h" +#include "SDL_DirectFB_yuv.h" + +/* The implementation dependent data for the window manager cursor */ +struct WMcursor { + int unused; +}; + + +/* Initialization/Query functions */ +static int DirectFB_VideoInit(_THIS, SDL_PixelFormat *vformat); +static SDL_Rect **DirectFB_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags); +static SDL_Surface *DirectFB_SetVideoMode(_THIS, SDL_Surface *current, int width, int height, int bpp, Uint32 flags); +static int DirectFB_SetColors(_THIS, int firstcolor, int ncolors, + SDL_Color *colors); +static void DirectFB_VideoQuit(_THIS); + +/* Hardware surface functions */ +static int DirectFB_AllocHWSurface(_THIS, SDL_Surface *surface); +static int DirectFB_FillHWRect(_THIS, SDL_Surface *dst, SDL_Rect *dstrect, Uint32 color); +static int DirectFB_LockHWSurface(_THIS, SDL_Surface *surface); +static void DirectFB_UnlockHWSurface(_THIS, SDL_Surface *surface); +static void DirectFB_FreeHWSurface(_THIS, SDL_Surface *surface); +static int DirectFB_CheckHWBlit(_THIS, SDL_Surface *src, SDL_Surface *dst); +static int DirectFB_HWAccelBlit(SDL_Surface *src, SDL_Rect *srcrect, + SDL_Surface *dst, SDL_Rect *dstrect); +static int DirectFB_SetHWColorKey(_THIS, SDL_Surface *surface, Uint32 key); +static int DirectFB_SetHWAlpha(_THIS, SDL_Surface *surface, Uint8 alpha); +static int DirectFB_FlipHWSurface(_THIS, SDL_Surface *surface); +static int DirectFB_ShowWMCursor(_THIS, WMcursor *cursor); + +/* Various screen update functions available */ +static void DirectFB_DirectUpdate(_THIS, int numrects, SDL_Rect *rects); +static void DirectFB_WindowedUpdate(_THIS, int numrects, SDL_Rect *rects); + +/* This is the rect EnumModes2 uses */ +struct DirectFBEnumRect { + SDL_Rect r; + struct DirectFBEnumRect* next; +}; + +static struct DirectFBEnumRect *enumlist = NULL; + + +/* DirectFB driver bootstrap functions */ + +static int DirectFB_Available(void) +{ + return 1; +} + +static void DirectFB_DeleteDevice(SDL_VideoDevice *device) +{ + SDL_free(device->hidden); + SDL_free(device); +} + +static SDL_VideoDevice *DirectFB_CreateDevice(int devindex) +{ + SDL_VideoDevice *device; + + /* Initialize all variables that we clean on shutdown */ + device = (SDL_VideoDevice *)SDL_malloc(sizeof(SDL_VideoDevice)); + if (device) + { + SDL_memset (device, 0, (sizeof *device)); + device->hidden = (struct SDL_PrivateVideoData *) malloc (sizeof (*device->hidden)); + } + if (device == NULL || device->hidden == NULL) + { + SDL_OutOfMemory(); + if (device) + { + free (device); + } + return(0); + } + SDL_memset (device->hidden, 0, sizeof (*device->hidden)); + + /* Set the function pointers */ + device->VideoInit = DirectFB_VideoInit; + device->ListModes = DirectFB_ListModes; + device->SetVideoMode = DirectFB_SetVideoMode; + device->SetColors = DirectFB_SetColors; + device->UpdateRects = NULL; + device->CreateYUVOverlay = DirectFB_CreateYUVOverlay; + device->VideoQuit = DirectFB_VideoQuit; + device->AllocHWSurface = DirectFB_AllocHWSurface; + device->CheckHWBlit = DirectFB_CheckHWBlit; + device->FillHWRect = DirectFB_FillHWRect; + device->SetHWColorKey = DirectFB_SetHWColorKey; + device->SetHWAlpha = DirectFB_SetHWAlpha; + device->LockHWSurface = DirectFB_LockHWSurface; + device->UnlockHWSurface = DirectFB_UnlockHWSurface; + device->FlipHWSurface = DirectFB_FlipHWSurface; + device->FreeHWSurface = DirectFB_FreeHWSurface; + device->ShowWMCursor = DirectFB_ShowWMCursor; + device->SetCaption = NULL; + device->SetIcon = NULL; + device->IconifyWindow = NULL; + device->GrabInput = NULL; + device->GetWMInfo = NULL; + device->InitOSKeymap = DirectFB_InitOSKeymap; + device->PumpEvents = DirectFB_PumpEvents; + + device->free = DirectFB_DeleteDevice; + + return device; +} + +VideoBootStrap DirectFB_bootstrap = { + "directfb", "DirectFB", + DirectFB_Available, DirectFB_CreateDevice +}; + +static DFBSurfacePixelFormat GetFormatForBpp (int bpp, IDirectFBDisplayLayer *layer) +{ + DFBDisplayLayerConfig dlc; + int bytes = (bpp + 7) / 8; + + layer->GetConfiguration (layer, &dlc); + + if (bytes == DFB_BYTES_PER_PIXEL(dlc.pixelformat) && bytes > 1) + return dlc.pixelformat; + + switch (bytes) + { + case 1: + return DSPF_LUT8; + case 2: + return DSPF_RGB16; + case 3: + return DSPF_RGB24; + case 4: + return DSPF_RGB32; + } + + return DSPF_UNKNOWN; +} + +static DFBEnumerationResult EnumModesCallback (int width, + int height, + int bpp, + void *data) +{ + SDL_VideoDevice *this = (SDL_VideoDevice *)data; + struct DirectFBEnumRect *enumrect; + + HIDDEN->nummodes++; + + if (enumlist && enumlist->r.w == width && enumlist->r.h == height) + return DFENUM_OK; + + enumrect = SDL_calloc(1, sizeof(struct DirectFBEnumRect)); + if (!enumrect) + { + SDL_OutOfMemory(); + return DFENUM_CANCEL; + } + + enumrect->r.w = (Uint16)width; + enumrect->r.h = (Uint16)height; + enumrect->next = enumlist; + + enumlist = enumrect; + + return DFENUM_OK; +} + +struct private_hwdata { + IDirectFBSurface *surface; + IDirectFBPalette *palette; +}; + +void SetDirectFBerror (const char *function, DFBResult code) +{ + const char *error = DirectFBErrorString (code); + + if (error) + SDL_SetError("%s: %s", function, error); + else + SDL_SetError("Unknown error code from %s", function); +} + +static DFBSurfacePixelFormat SDLToDFBPixelFormat (SDL_PixelFormat *format) +{ + if (format->Rmask && format->Gmask && format->Bmask) + { + switch (format->BitsPerPixel) + { + case 8: + return DSPF_LUT8; + + case 16: + if (format->Rmask == 0xF800 && + format->Gmask == 0x07E0 && + format->Bmask == 0x001F) + return DSPF_RGB16; + /* fall through */ + + case 15: + if (format->Rmask == 0x7C00 && + format->Gmask == 0x03E0 && + format->Bmask == 0x001F) + return DSPF_ARGB1555; + break; + + case 24: + if (format->Rmask == 0xFF0000 && + format->Gmask == 0x00FF00 && + format->Bmask == 0x0000FF) + return DSPF_RGB24; + break; + + case 32: + if (format->Rmask == 0xFF0000 && + format->Gmask == 0x00FF00 && + format->Bmask == 0x0000FF) + { + if (format->Amask == 0xFF000000) + return DSPF_ARGB; + else + return DSPF_RGB32; + } + break; + } + } + else + { + switch (format->BitsPerPixel) + { + case 8: + return DSPF_LUT8; + case 15: + return DSPF_ARGB1555; + case 16: + return DSPF_RGB16; + case 24: + return DSPF_RGB24; + case 32: + return DSPF_RGB32; + } + } + + return DSPF_UNKNOWN; +} + +static SDL_Palette *AllocatePalette(int size) +{ + SDL_Palette *palette; + SDL_Color *colors; + + palette = SDL_calloc (1, sizeof(SDL_Palette)); + if (!palette) + { + SDL_OutOfMemory(); + return NULL; + } + + colors = SDL_calloc (size, sizeof(SDL_Color)); + if (!colors) + { + SDL_OutOfMemory(); + return NULL; + } + + palette->ncolors = size; + palette->colors = colors; + + return palette; +} + +static int DFBToSDLPixelFormat (DFBSurfacePixelFormat pixelformat, SDL_PixelFormat *format) +{ + format->Amask = format->Rmask = format->Gmask = format->Bmask = 0; + format->BitsPerPixel = format->BytesPerPixel = 0; + + switch (pixelformat) + { + case DSPF_A8: + format->Amask = 0x000000FF; + break; + + case DSPF_ARGB1555: + format->Rmask = 0x00007C00; + format->Gmask = 0x000003E0; + format->Bmask = 0x0000001F; + break; + + case DSPF_RGB16: + format->Rmask = 0x0000F800; + format->Gmask = 0x000007E0; + format->Bmask = 0x0000001F; + break; + + case DSPF_ARGB: + format->Amask = 0; /* apps don't seem to like that: 0xFF000000; */ + /* fall through */ + case DSPF_RGB24: + case DSPF_RGB32: + format->Rmask = 0x00FF0000; + format->Gmask = 0x0000FF00; + format->Bmask = 0x000000FF; + break; + + case DSPF_LUT8: + format->Rmask = 0x000000FF; + format->Gmask = 0x000000FF; + format->Bmask = 0x000000FF; + + if (!format->palette) + format->palette = AllocatePalette(256); + break; + + default: + fprintf (stderr, "SDL_DirectFB: Unsupported pixelformat (0x%08x)!\n", pixelformat); + return -1; + } + + format->BitsPerPixel = DFB_BYTES_PER_PIXEL(pixelformat) * 8; + format->BytesPerPixel = DFB_BYTES_PER_PIXEL(pixelformat); + + return 0; +} + + +int DirectFB_VideoInit(_THIS, SDL_PixelFormat *vformat) +{ + int i; + DFBResult ret; +#if (DIRECTFB_MAJOR_VERSION == 0) && (DIRECTFB_MINOR_VERSION == 9) && (DIRECTFB_MICRO_VERSION < 23) + DFBCardCapabilities caps; +#else + DFBGraphicsDeviceDescription caps; +#endif + DFBDisplayLayerConfig dlc; + struct DirectFBEnumRect *rect; + IDirectFB *dfb = NULL; + IDirectFBDisplayLayer *layer = NULL; + IDirectFBEventBuffer *events = NULL; + + HIDDEN->c2layer = NULL, HIDDEN->c2frame = NULL; + HIDDEN->enable_mga_crtc2 = 0; + HIDDEN->mga_crtc2_stretch_overscan = 1; + + ret = DirectFBInit (NULL, NULL); + if (ret) + { + SetDirectFBerror ("DirectFBInit", ret); + goto error; + } + + ret = DirectFBCreate (&dfb); + if (ret) + { + SetDirectFBerror ("DirectFBCreate", ret); + goto error; + } + + ret = dfb->GetDisplayLayer (dfb, DLID_PRIMARY, &layer); + if (ret) + { + SetDirectFBerror ("dfb->GetDisplayLayer", ret); + goto error; + } + + ret = dfb->CreateInputEventBuffer (dfb, DICAPS_ALL, DFB_FALSE, &events); + if (ret) + { + SetDirectFBerror ("dfb->CreateEventBuffer", ret); + goto error; + } + + layer->EnableCursor (layer, 1); + + /* Query layer configuration to determine the current mode and pixelformat */ + layer->GetConfiguration (layer, &dlc); + + /* If current format is not supported use LUT8 as the default */ + if (DFBToSDLPixelFormat (dlc.pixelformat, vformat)) + DFBToSDLPixelFormat (DSPF_LUT8, vformat); + + /* Enumerate the available fullscreen modes */ + ret = dfb->EnumVideoModes (dfb, EnumModesCallback, this); + if (ret) + { + SetDirectFBerror ("dfb->EnumVideoModes", ret); + goto error; + } + + HIDDEN->modelist = SDL_calloc (HIDDEN->nummodes + 1, sizeof(SDL_Rect *)); + if (!HIDDEN->modelist) + { + SDL_OutOfMemory(); + goto error; + } + + for (i = 0, rect = enumlist; rect; ++i, rect = rect->next ) + { + HIDDEN->modelist[i] = &rect->r; + } + + HIDDEN->modelist[i] = NULL; + + + /* Query card capabilities to get the video memory size */ +#if (DIRECTFB_MAJOR_VERSION == 0) && (DIRECTFB_MINOR_VERSION == 9) && (DIRECTFB_MICRO_VERSION < 23) + dfb->GetCardCapabilities (dfb, &caps); +#else + dfb->GetDeviceDescription (dfb, &caps); +#endif + + this->info.wm_available = 1; + this->info.hw_available = 1; + this->info.blit_hw = 1; + this->info.blit_hw_CC = 1; + this->info.blit_hw_A = 1; + this->info.blit_fill = 1; + this->info.video_mem = caps.video_memory / 1024; + this->info.current_w = dlc.width; + this->info.current_h = dlc.height; + + HIDDEN->initialized = 1; + HIDDEN->dfb = dfb; + HIDDEN->layer = layer; + HIDDEN->eventbuffer = events; + + if (SDL_getenv("SDL_DIRECTFB_MGA_CRTC2") != NULL) + HIDDEN->enable_mga_crtc2 = 1; + + if (HIDDEN->enable_mga_crtc2) + { + DFBDisplayLayerConfig dlc; + DFBDisplayLayerConfigFlags failed; + + ret = dfb->GetDisplayLayer (dfb, 2, &HIDDEN->c2layer); + if (ret) + { + SetDirectFBerror ("dfb->GetDisplayLayer(CRTC2)", ret); + goto error; + } + + ret = HIDDEN->layer->SetCooperativeLevel(HIDDEN->layer, DLSCL_EXCLUSIVE); + if (ret) + { + SetDirectFBerror ("layer->SetCooperativeLevel(CRTC2, EXCLUSIVE)", ret); + goto error; + } + + ret = HIDDEN->c2layer->SetCooperativeLevel(HIDDEN->c2layer, DLSCL_EXCLUSIVE); + if (ret) + { + SetDirectFBerror ("c2layer->SetCooperativeLevel(CRTC2, EXCLUSIVE)", ret); + goto error; + } + + HIDDEN->c2layer->SetOpacity(HIDDEN->c2layer, 0x0); + + /* Init the surface here as it got a fixed size */ + dlc.flags = DLCONF_PIXELFORMAT | DLCONF_BUFFERMODE; + dlc.buffermode = DLBM_BACKVIDEO; + dlc.pixelformat = DSPF_RGB32; + + ret = HIDDEN->c2layer->TestConfiguration( HIDDEN->c2layer, &dlc, &failed ); + if (ret) + { + SetDirectFBerror ("c2layer->TestConfiguration", ret); + goto error; + } + + ret = HIDDEN->c2layer->SetConfiguration( HIDDEN->c2layer, &dlc ); + if (ret) + { + SetDirectFBerror ("c2layer->SetConfiguration", ret); + goto error; + } + + ret = HIDDEN->c2layer->GetSurface( HIDDEN->c2layer, &HIDDEN->c2frame ); + if (ret) + { + SetDirectFBerror ("c2layer->GetSurface", ret); + goto error; + } + + HIDDEN->c2framesize.x = 0; + HIDDEN->c2framesize.y = 0; + HIDDEN->c2frame->GetSize( HIDDEN->c2frame, &HIDDEN->c2framesize.w, &HIDDEN->c2framesize.h); + + HIDDEN->c2frame->SetBlittingFlags( HIDDEN->c2frame, DSBLIT_NOFX ); + HIDDEN->c2frame->SetColor( HIDDEN->c2frame, 0, 0, 0, 0xff ); + + /* Clear CRTC2 */ + HIDDEN->c2frame->Clear(HIDDEN->c2frame, 0, 0, 0, 0xff ); + HIDDEN->c2frame->Flip(HIDDEN->c2frame, NULL, 0 ); + HIDDEN->c2frame->Clear(HIDDEN->c2frame, 0, 0, 0, 0xff ); + HIDDEN->c2frame->Flip(HIDDEN->c2frame, NULL, 0 ); + HIDDEN->c2frame->Clear(HIDDEN->c2frame, 0, 0, 0, 0xff ); + + HIDDEN->c2layer->SetOpacity(HIDDEN->c2layer, 0xFF ); + + /* Check if overscan is possibly set */ + if (SDL_getenv("SDL_DIRECTFB_MGA_OVERSCAN") != NULL) + { + float overscan = 0; + if (SDL_sscanf(SDL_getenv("SDL_DIRECTFB_MGA_OVERSCAN"), "%f", &overscan) == 1) + if (overscan > 0 && overscan < 2) + HIDDEN->mga_crtc2_stretch_overscan = overscan; + } + + #ifdef DIRECTFB_CRTC2_DEBUG + printf("CRTC2 overscan: %f\n", HIDDEN->mga_crtc2_stretch_overscan); + #endif + } + + return 0; + + error: + if (events) + events->Release (events); + + if (HIDDEN->c2frame) + HIDDEN->c2frame->Release (HIDDEN->c2frame); + + if (HIDDEN->c2layer) + HIDDEN->c2layer->Release (HIDDEN->c2layer); + + if (layer) + layer->Release (layer); + + if (dfb) + dfb->Release (dfb); + + return -1; +} + +static SDL_Rect **DirectFB_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags) +{ + if (flags & SDL_FULLSCREEN) + return HIDDEN->modelist; + else + if (SDLToDFBPixelFormat (format) != DSPF_UNKNOWN) + return (SDL_Rect**) -1; + + return NULL; +} + +static SDL_Surface *DirectFB_SetVideoMode(_THIS, SDL_Surface *current, int width, int height, int bpp, Uint32 flags) +{ + DFBResult ret; + DFBSurfaceDescription dsc; + DFBSurfacePixelFormat pixelformat; + IDirectFBSurface *surface; + + fprintf (stderr, "SDL DirectFB_SetVideoMode: %dx%d@%d, flags: 0x%08x\n", + width, height, bpp, flags); + + flags |= SDL_FULLSCREEN; + + /* Release previous primary surface */ + if (current->hwdata && current->hwdata->surface) + { + current->hwdata->surface->Release (current->hwdata->surface); + current->hwdata->surface = NULL; + + /* And its palette if present */ + if (current->hwdata->palette) + { + current->hwdata->palette->Release (current->hwdata->palette); + current->hwdata->palette = NULL; + } + } + else if (!current->hwdata) + { + /* Allocate the hardware acceleration data */ + current->hwdata = (struct private_hwdata *) SDL_calloc (1, sizeof(*current->hwdata)); + if (!current->hwdata) + { + SDL_OutOfMemory(); + return NULL; + } + } + + /* Set cooperative level depending on flag SDL_FULLSCREEN */ + if (flags & SDL_FULLSCREEN) + { + ret = HIDDEN->dfb->SetCooperativeLevel (HIDDEN->dfb, DFSCL_FULLSCREEN); + if (ret && !HIDDEN->enable_mga_crtc2) + { + DirectFBError ("dfb->SetCooperativeLevel", ret); + flags &= ~SDL_FULLSCREEN; + } + } + else + HIDDEN->dfb->SetCooperativeLevel (HIDDEN->dfb, DFSCL_NORMAL); + + /* Set video mode */ + ret = HIDDEN->dfb->SetVideoMode (HIDDEN->dfb, width, height, bpp); + if (ret) + { + if (flags & SDL_FULLSCREEN) + { + flags &= ~SDL_FULLSCREEN; + HIDDEN->dfb->SetCooperativeLevel (HIDDEN->dfb, DFSCL_NORMAL); + ret = HIDDEN->dfb->SetVideoMode (HIDDEN->dfb, width, height, bpp); + } + + if (ret) + { + SetDirectFBerror ("dfb->SetVideoMode", ret); + return NULL; + } + } + + /* Create primary surface */ + dsc.flags = DSDESC_CAPS | DSDESC_PIXELFORMAT; + dsc.caps = DSCAPS_PRIMARY | ((flags & SDL_DOUBLEBUF) ? DSCAPS_FLIPPING : 0); + dsc.pixelformat = GetFormatForBpp (bpp, HIDDEN->layer); + + ret = HIDDEN->dfb->CreateSurface (HIDDEN->dfb, &dsc, &surface); + if (ret && (flags & SDL_DOUBLEBUF)) + { + /* Try without double buffering */ + dsc.caps &= ~DSCAPS_FLIPPING; + ret = HIDDEN->dfb->CreateSurface (HIDDEN->dfb, &dsc, &surface); + } + if (ret) + { + SetDirectFBerror ("dfb->CreateSurface", ret); + return NULL; + } + + current->w = width; + current->h = height; + current->flags = SDL_HWSURFACE | SDL_PREALLOC; + + if (flags & SDL_FULLSCREEN) + { + current->flags |= SDL_FULLSCREEN; + this->UpdateRects = DirectFB_DirectUpdate; + } + else + this->UpdateRects = DirectFB_WindowedUpdate; + + if (dsc.caps & DSCAPS_FLIPPING) + current->flags |= SDL_DOUBLEBUF; + + surface->GetPixelFormat (surface, &pixelformat); + + DFBToSDLPixelFormat (pixelformat, current->format); + + /* Get the surface palette (if supported) */ + if (DFB_PIXELFORMAT_IS_INDEXED( pixelformat )) + { + surface->GetPalette (surface, ¤t->hwdata->palette); + + current->flags |= SDL_HWPALETTE; + } + + current->hwdata->surface = surface; + + /* MGA CRTC2 stuff */ + if (HIDDEN->enable_mga_crtc2) + { + /* no stretching if c2ssize == c2framesize */ + HIDDEN->c2ssize.x = 0, HIDDEN->c2ssize.y = 0; + HIDDEN->c2ssize.w = width; + HIDDEN->c2ssize.h = height; + + HIDDEN->c2dsize.x = 0, HIDDEN->c2dsize.y = 0; + HIDDEN->c2dsize.w = width; + HIDDEN->c2dsize.h = height; + + HIDDEN->mga_crtc2_stretch = 0; + + if (SDL_getenv("SDL_DIRECTFB_MGA_STRETCH") != NULL) + { + /* Normally assume a picture aspect ratio of 4:3 */ + int zoom_aspect_x = 4, zoom_aspect_y = 3, i, j; + + for (i = 1; i < 20; i++) + { + for (j = 1; j < 10; j++) + { + if ((float)width/(float)i*(float)j == height) + { + zoom_aspect_x = i; + zoom_aspect_y = j; + + /* break the loop */ + i = 21; + break; + } + } + } + + #ifdef DIRECTFB_CRTC2_DEBUG + printf("Source resolution: X: %d, Y: %d, Aspect ratio: %d:%d\n", width, height, zoom_aspect_x, zoom_aspect_y); + printf("CRTC2 resolution: X: %d, Y: %d\n", HIDDEN->c2framesize.w, HIDDEN->c2framesize.h); + #endif + + /* don't stretch only slightly smaller/larger images */ + if ((float)width < (float)HIDDEN->c2framesize.w*0.95 || (float)height < (float)HIDDEN->c2framesize.h*0.95) + { + while ((float)HIDDEN->c2dsize.w < (float)HIDDEN->c2framesize.w*HIDDEN->mga_crtc2_stretch_overscan && (float)HIDDEN->c2dsize.h < (float)HIDDEN->c2framesize.h*HIDDEN->mga_crtc2_stretch_overscan) + { + HIDDEN->c2dsize.w+=zoom_aspect_x; + HIDDEN->c2dsize.h+=zoom_aspect_y; + } + + /* one step down */ + HIDDEN->c2dsize.w-=zoom_aspect_x; + HIDDEN->c2dsize.h-=zoom_aspect_y; + + #ifdef DIRECTFB_CRTC2_DEBUG + printf("Stretched resolution: X: %d, Y: %d\n", HIDDEN->c2dsize.w, HIDDEN->c2dsize.h); + #endif + + HIDDEN->mga_crtc2_stretch = 1; + } + else if ((float)width > (float)HIDDEN->c2framesize.w*0.95 || (float)height > (float)HIDDEN->c2framesize.h*0.95) + { + while ((float)HIDDEN->c2dsize.w > (float)HIDDEN->c2framesize.w*HIDDEN->mga_crtc2_stretch_overscan || (float)HIDDEN->c2dsize.h > (float)HIDDEN->c2framesize.h*HIDDEN->mga_crtc2_stretch_overscan) + { + HIDDEN->c2dsize.w-=zoom_aspect_x; + HIDDEN->c2dsize.h-=zoom_aspect_y; + } + + #ifdef DIRECTFB_CRTC2_DEBUG + printf("Down-Stretched resolution: X: %d, Y: %d\n", HIDDEN->c2dsize.w, HIDDEN->c2dsize.h); + #endif + + HIDDEN->mga_crtc2_stretch = 1; + } else { + #ifdef DIRECTFB_CRTC2_DEBUG + printf("Not stretching image\n"); + #endif + } + + /* Panning */ + if (HIDDEN->c2framesize.w > HIDDEN->c2dsize.w) + HIDDEN->c2dsize.x = (HIDDEN->c2framesize.w - HIDDEN->c2dsize.w) / 2; + else + HIDDEN->c2dsize.x = (HIDDEN->c2dsize.w - HIDDEN->c2framesize.w) / 2; + + if (HIDDEN->c2framesize.h > HIDDEN->c2dsize.h) + HIDDEN->c2dsize.y = (HIDDEN->c2framesize.h - HIDDEN->c2dsize.h) / 2; + else + HIDDEN->c2dsize.y = (HIDDEN->c2dsize.h - HIDDEN->c2framesize.h) / 2; + + #ifdef DIRECTFB_CRTC2_DEBUG + printf("CRTC2 position X: %d, Y: %d\n", HIDDEN->c2dsize.x, HIDDEN->c2dsize.y); + #endif + } + } + + return current; +} + +static int DirectFB_AllocHWSurface(_THIS, SDL_Surface *surface) +{ + DFBResult ret; + DFBSurfaceDescription dsc; + + /* fprintf(stderr, "SDL: DirectFB_AllocHWSurface (%dx%d@%d, flags: 0x%08x)\n", + surface->w, surface->h, surface->format->BitsPerPixel, surface->flags);*/ + + if (surface->w < 8 || surface->h < 8) + return -1; + + /* fill surface description */ + dsc.flags = DSDESC_WIDTH | DSDESC_HEIGHT | DSDESC_PIXELFORMAT | DSDESC_CAPS; + dsc.width = surface->w; + dsc.height = surface->h; + dsc.caps = (surface->flags & SDL_DOUBLEBUF) ? DSCAPS_FLIPPING : 0; + + /* find the right pixelformat */ + dsc.pixelformat = SDLToDFBPixelFormat (surface->format); + if (dsc.pixelformat == DSPF_UNKNOWN) + return -1; + + /* Allocate the hardware acceleration data */ + surface->hwdata = (struct private_hwdata *) SDL_calloc (1, sizeof(*surface->hwdata)); + if (surface->hwdata == NULL) + { + SDL_OutOfMemory(); + return -1; + } + + /* Create the surface */ + ret = HIDDEN->dfb->CreateSurface (HIDDEN->dfb, &dsc, &surface->hwdata->surface); + if (ret) + { + SetDirectFBerror ("dfb->CreateSurface", ret); + free (surface->hwdata); + surface->hwdata = NULL; + return -1; + } + + surface->flags |= SDL_HWSURFACE | SDL_PREALLOC; + + return 0; +} + +static void DirectFB_FreeHWSurface(_THIS, SDL_Surface *surface) +{ + if (surface->hwdata && HIDDEN->initialized) + { + surface->hwdata->surface->Release (surface->hwdata->surface); + free (surface->hwdata); + surface->hwdata = NULL; + } +} + +static int DirectFB_CheckHWBlit(_THIS, SDL_Surface *src, SDL_Surface *dst) +{ + /* fprintf(stderr, "SDL: DirectFB_CheckHWBlit (src->hwdata: %p, dst->hwdata: %p)\n", + src->hwdata, dst->hwdata);*/ + + if (!src->hwdata || !dst->hwdata) + return 0; + + src->flags |= SDL_HWACCEL; + src->map->hw_blit = DirectFB_HWAccelBlit; + + return 1; +} + +static int DirectFB_HWAccelBlit(SDL_Surface *src, SDL_Rect *srcrect, + SDL_Surface *dst, SDL_Rect *dstrect) +{ + DFBSurfaceBlittingFlags flags = DSBLIT_NOFX; + + DFBRectangle sr = { srcrect->x, srcrect->y, srcrect->w, srcrect->h }; + DFBRectangle dr = { dstrect->x, dstrect->y, dstrect->w, dstrect->h }; + + IDirectFBSurface *surface = dst->hwdata->surface; + + if (src->flags & SDL_SRCCOLORKEY) + { + flags |= DSBLIT_SRC_COLORKEY; + DirectFB_SetHWColorKey (NULL, src, src->format->colorkey); + } + + if (src->flags & SDL_SRCALPHA) + { + flags |= DSBLIT_BLEND_COLORALPHA; + surface->SetColor (surface, 0xff, 0xff, 0xff, src->format->alpha); + } + + surface->SetBlittingFlags (surface, flags); + + if (sr.w == dr.w && sr.h == dr.h) + surface->Blit (surface, src->hwdata->surface, &sr, dr.x, dr.y); + else + surface->StretchBlit (surface, src->hwdata->surface, &sr, &dr); + + return 0; +} + +static int DirectFB_FillHWRect(_THIS, SDL_Surface *dst, SDL_Rect *dstrect, Uint32 color) +{ + SDL_PixelFormat *fmt = dst->format; + IDirectFBSurface *surface = dst->hwdata->surface; + + /* ugly */ + surface->SetColor (surface, + (color & fmt->Rmask) >> (fmt->Rshift - fmt->Rloss), + (color & fmt->Gmask) >> (fmt->Gshift - fmt->Gloss), + (color & fmt->Bmask) << (fmt->Bloss - fmt->Bshift), 0xFF); + surface->FillRectangle (surface, dstrect->x, dstrect->y, dstrect->w, dstrect->h); + + return 0; +} + +static int DirectFB_SetHWColorKey(_THIS, SDL_Surface *src, Uint32 key) +{ + SDL_PixelFormat *fmt = src->format; + IDirectFBSurface *surface = src->hwdata->surface; + + if (fmt->BitsPerPixel == 8) + surface->SetSrcColorKeyIndex (surface, key); + else + /* ugly */ + surface->SetSrcColorKey (surface, + (key & fmt->Rmask) >> (fmt->Rshift - fmt->Rloss), + (key & fmt->Gmask) >> (fmt->Gshift - fmt->Gloss), + (key & fmt->Bmask) << (fmt->Bloss - fmt->Bshift)); + + return 0; +} + +static int DirectFB_SetHWAlpha(_THIS, SDL_Surface *surface, Uint8 alpha) +{ + return 0; +} + +static int DirectFB_FlipHWSurface(_THIS, SDL_Surface *surface) +{ + if (HIDDEN->enable_mga_crtc2) + { + int rtn = surface->hwdata->surface->Flip (surface->hwdata->surface, NULL, 0); + if (HIDDEN->mga_crtc2_stretch) + HIDDEN->c2frame->StretchBlit(HIDDEN->c2frame, surface->hwdata->surface, &HIDDEN->c2ssize, &HIDDEN->c2dsize); + else + HIDDEN->c2frame->Blit(HIDDEN->c2frame, surface->hwdata->surface, NULL, HIDDEN->c2dsize.x, HIDDEN->c2dsize.y); + + HIDDEN->c2frame->Flip(HIDDEN->c2frame, NULL, DSFLIP_WAITFORSYNC); + return rtn; + } + else + return surface->hwdata->surface->Flip (surface->hwdata->surface, NULL, DSFLIP_WAITFORSYNC); +} + +static int DirectFB_LockHWSurface(_THIS, SDL_Surface *surface) +{ + DFBResult ret; + void *data; + int pitch; + + ret = surface->hwdata->surface->Lock (surface->hwdata->surface, + DSLF_WRITE, &data, &pitch); + if (ret) + { + SetDirectFBerror ("surface->Lock", ret); + return -1; + } + + surface->pixels = data; + surface->pitch = pitch; + + return 0; +} + +static void DirectFB_UnlockHWSurface(_THIS, SDL_Surface *surface) +{ + surface->hwdata->surface->Unlock (surface->hwdata->surface); + surface->pixels = NULL; +} + +static void DirectFB_DirectUpdate(_THIS, int numrects, SDL_Rect *rects) +{ + if (HIDDEN->enable_mga_crtc2) + { + if (HIDDEN->mga_crtc2_stretch) + HIDDEN->c2frame->StretchBlit(HIDDEN->c2frame, this->screen->hwdata->surface, &HIDDEN->c2ssize, &HIDDEN->c2dsize); + else + HIDDEN->c2frame->Blit(HIDDEN->c2frame, this->screen->hwdata->surface, NULL, HIDDEN->c2dsize.x, HIDDEN->c2dsize.y); + + HIDDEN->c2frame->Flip(HIDDEN->c2frame, NULL, DSFLIP_WAITFORSYNC); + } +} + +static void DirectFB_WindowedUpdate(_THIS, int numrects, SDL_Rect *rects) +{ + DFBRegion region; + int i; + int region_valid = 0; + IDirectFBSurface *surface = this->screen->hwdata->surface; + + for (i=0; i<numrects; ++i) + { + int x2, y2; + + if ( ! rects[i].w ) /* Clipped? */ + continue; + + x2 = rects[i].x + rects[i].w - 1; + y2 = rects[i].y + rects[i].h - 1; + + if (region_valid) + { + if (rects[i].x < region.x1) + region.x1 = rects[i].x; + + if (rects[i].y < region.y1) + region.y1 = rects[i].y; + + if (x2 > region.x2) + region.x2 = x2; + + if (y2 > region.y2) + region.y2 = y2; + } + else + { + region.x1 = rects[i].x; + region.y1 = rects[i].y; + region.x2 = x2; + region.y2 = y2; + + region_valid = 1; + } + } + + if (region_valid) + { + if (HIDDEN->enable_mga_crtc2) + { + if (HIDDEN->mga_crtc2_stretch) + HIDDEN->c2frame->StretchBlit(HIDDEN->c2frame, surface, &HIDDEN->c2ssize, &HIDDEN->c2dsize); + else + HIDDEN->c2frame->Blit(HIDDEN->c2frame, surface, NULL, HIDDEN->c2dsize.x, HIDDEN->c2dsize.y); + + HIDDEN->c2frame->Flip(HIDDEN->c2frame, NULL, DSFLIP_WAITFORSYNC); + } + else + surface->Flip (surface, ®ion, DSFLIP_WAITFORSYNC); + } +} + +int DirectFB_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors) +{ + IDirectFBPalette *palette = this->screen->hwdata->palette; + + if (!palette) + return 0; + + if (firstcolor > 255) + return 0; + + if (firstcolor + ncolors > 256) + ncolors = 256 - firstcolor; + + if (ncolors > 0) + { + int i; + DFBColor entries[ncolors]; + + for (i=0; i<ncolors; i++) + { + entries[i].a = 0xff; + entries[i].r = colors[i].r; + entries[i].g = colors[i].g; + entries[i].b = colors[i].b; + } + + palette->SetEntries (palette, entries, ncolors, firstcolor); + } + + return 1; +} + +void DirectFB_VideoQuit(_THIS) +{ + struct DirectFBEnumRect *rect = enumlist; + + if (this->screen && this->screen->hwdata) + { + IDirectFBSurface *surface = this->screen->hwdata->surface; + IDirectFBPalette *palette = this->screen->hwdata->palette; + + if (palette) + palette->Release (palette); + + if (surface) + surface->Release (surface); + + this->screen->hwdata->surface = NULL; + this->screen->hwdata->palette = NULL; + } + + if (HIDDEN->c2frame) + { + HIDDEN->c2frame->Release (HIDDEN->c2frame); + HIDDEN->c2frame = NULL; + } + + if (HIDDEN->eventbuffer) + { + HIDDEN->eventbuffer->Release (HIDDEN->eventbuffer); + HIDDEN->eventbuffer = NULL; + } + + if (HIDDEN->c2layer) + { + HIDDEN->c2layer->Release (HIDDEN->c2layer); + HIDDEN->c2layer = NULL; + } + + if (HIDDEN->layer) + { + HIDDEN->layer->Release (HIDDEN->layer); + HIDDEN->layer = NULL; + } + + if (HIDDEN->dfb) + { + HIDDEN->dfb->Release (HIDDEN->dfb); + HIDDEN->dfb = NULL; + } + + /* Free video mode list */ + if (HIDDEN->modelist) + { + free (HIDDEN->modelist); + HIDDEN->modelist = NULL; + } + + /* Free mode enumeration list */ + while (rect) + { + struct DirectFBEnumRect *next = rect->next; + free (rect); + rect = next; + } + enumlist = NULL; + + HIDDEN->initialized = 0; +} + + +int DirectFB_ShowWMCursor(_THIS, WMcursor *cursor) +{ + /* We can only hide or show the default cursor */ + if ( cursor == NULL ) + { + HIDDEN->layer->SetCursorOpacity(HIDDEN->layer, 0x00); + } + else + { + HIDDEN->layer->SetCursorOpacity(HIDDEN->layer, 0xFF); + } + return 1; +} + +void DirectFB_FinalQuit(void) +{ +} diff --git a/3rdparty/SDL/src/video/directfb/SDL_DirectFB_video.h b/3rdparty/SDL/src/video/directfb/SDL_DirectFB_video.h new file mode 100644 index 0000000..e1fa12c --- /dev/null +++ b/3rdparty/SDL/src/video/directfb/SDL_DirectFB_video.h @@ -0,0 +1,62 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#ifndef _SDL_DirectFB_video_h +#define _SDL_DirectFB_video_h + +#include <directfb.h> + +#include "SDL_mouse.h" +#include "../SDL_sysvideo.h" + +#define _THIS SDL_VideoDevice *this + +/* Private display data */ + +struct SDL_PrivateVideoData +{ + int initialized; + + IDirectFB *dfb; + IDirectFBDisplayLayer *layer; + IDirectFBEventBuffer *eventbuffer; + + int nummodes; + SDL_Rect **modelist; + + /* MGA CRTC2 support */ + int enable_mga_crtc2; + int mga_crtc2_stretch; + float mga_crtc2_stretch_overscan; + IDirectFBDisplayLayer *c2layer; + IDirectFBSurface *c2frame; + DFBRectangle c2ssize; /* Real screen size */ + DFBRectangle c2dsize; /* Stretched screen size */ + DFBRectangle c2framesize; /* CRTC2 screen size */ +}; + +#define HIDDEN (this->hidden) + +void SetDirectFBerror (const char *function, DFBResult code); + +#endif /* _SDL_DirectFB_video_h */ diff --git a/3rdparty/SDL/src/video/directfb/SDL_DirectFB_yuv.c b/3rdparty/SDL/src/video/directfb/SDL_DirectFB_yuv.c new file mode 100644 index 0000000..fd0cef1 --- /dev/null +++ b/3rdparty/SDL/src/video/directfb/SDL_DirectFB_yuv.c @@ -0,0 +1,290 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* This is the DirectFB implementation of YUV video overlays */ + +#include "SDL_video.h" +#include "SDL_DirectFB_yuv.h" +#include "../SDL_yuvfuncs.h" + + +/* The functions used to manipulate software video overlays */ +static struct private_yuvhwfuncs directfb_yuvfuncs = { + DirectFB_LockYUVOverlay, + DirectFB_UnlockYUVOverlay, + DirectFB_DisplayYUVOverlay, + DirectFB_FreeYUVOverlay +}; + +struct private_yuvhwdata { + DFBDisplayLayerID layer_id; + + IDirectFBDisplayLayer *layer; + IDirectFBSurface *surface; + + /* These are just so we don't have to allocate them separately */ + Uint16 pitches[3]; + Uint8 *planes[3]; +}; + +static DFBEnumerationResult +enum_layers_callback( DFBDisplayLayerID id, + DFBDisplayLayerDescription desc, + void *data ) +{ + struct private_yuvhwdata *hwdata = (struct private_yuvhwdata *) data; + + /* we don't want the primary */ + if (id == DLID_PRIMARY) + return DFENUM_OK; + + /* take the one with a surface for video */ + if ((desc.caps & DLCAPS_SURFACE) && (desc.type & DLTF_VIDEO)) + { + hwdata->layer_id = id; + + return DFENUM_CANCEL; + } + + return DFENUM_OK; +} + + +static DFBResult CreateYUVSurface(_THIS, struct private_yuvhwdata *hwdata, + int width, int height, Uint32 format) +{ + DFBResult ret; + IDirectFB *dfb = HIDDEN->dfb; + IDirectFBDisplayLayer *layer; + DFBDisplayLayerConfig conf; + + ret = dfb->EnumDisplayLayers (dfb, enum_layers_callback, hwdata); + if (ret) + { + SetDirectFBerror("IDirectFB::EnumDisplayLayers", ret); + return ret; + } + + if (!hwdata->layer_id) + return DFB_UNSUPPORTED; + + ret = dfb->GetDisplayLayer (dfb, hwdata->layer_id, &layer); + if (ret) + { + SetDirectFBerror("IDirectFB::GetDisplayLayer", ret); + return ret; + } + + conf.flags = DLCONF_WIDTH | DLCONF_HEIGHT | DLCONF_PIXELFORMAT; + conf.width = width; + conf.height = height; + + switch (format) + { + case SDL_YV12_OVERLAY: + conf.pixelformat = DSPF_YV12; + break; + case SDL_IYUV_OVERLAY: + conf.pixelformat = DSPF_I420; + break; + case SDL_YUY2_OVERLAY: + conf.pixelformat = DSPF_YUY2; + break; + case SDL_UYVY_OVERLAY: + conf.pixelformat = DSPF_UYVY; + break; + default: + fprintf (stderr, "SDL_DirectFB: Unsupported YUV format (0x%08x)!\n", format); + break; + } + + /* Need to set coop level or newer DirectFB versions will fail here. */ + ret = layer->SetCooperativeLevel (layer, DLSCL_ADMINISTRATIVE); + if (ret) + { + SetDirectFBerror("IDirectFBDisplayLayer::SetCooperativeLevel() failed", ret); + layer->Release (layer); + return ret; + } + + ret = layer->SetConfiguration (layer, &conf); + if (ret) + { + SetDirectFBerror("IDirectFBDisplayLayer::SetConfiguration", ret); + layer->Release (layer); + return ret; + } + + ret = layer->GetSurface (layer, &hwdata->surface); + if (ret) + { + SetDirectFBerror("IDirectFBDisplayLayer::GetSurface", ret); + layer->Release (layer); + return ret; + } + + hwdata->layer = layer; + + return DFB_OK; +} + +SDL_Overlay *DirectFB_CreateYUVOverlay(_THIS, int width, int height, Uint32 format, SDL_Surface *display) +{ + SDL_Overlay *overlay; + struct private_yuvhwdata *hwdata; + + /* Create the overlay structure */ + overlay = SDL_calloc (1, sizeof(SDL_Overlay)); + if (!overlay) + { + SDL_OutOfMemory(); + return NULL; + } + + /* Fill in the basic members */ + overlay->format = format; + overlay->w = width; + overlay->h = height; + + /* Set up the YUV surface function structure */ + overlay->hwfuncs = &directfb_yuvfuncs; + + /* Create the pixel data and lookup tables */ + hwdata = SDL_calloc(1, sizeof(struct private_yuvhwdata)); + overlay->hwdata = hwdata; + if (!hwdata) + { + SDL_OutOfMemory(); + SDL_FreeYUVOverlay (overlay); + return NULL; + } + + if (CreateYUVSurface (this, hwdata, width, height, format)) + { + SDL_FreeYUVOverlay (overlay); + return NULL; + } + + overlay->hw_overlay = 1; + + /* Set up the plane pointers */ + overlay->pitches = hwdata->pitches; + overlay->pixels = hwdata->planes; + switch (format) + { + case SDL_YV12_OVERLAY: + case SDL_IYUV_OVERLAY: + overlay->planes = 3; + break; + default: + overlay->planes = 1; + break; + } + + /* We're all done.. */ + return overlay; +} + +int DirectFB_LockYUVOverlay(_THIS, SDL_Overlay *overlay) +{ + DFBResult ret; + void *data; + int pitch; + IDirectFBSurface *surface = overlay->hwdata->surface; + + ret = surface->Lock (surface, DSLF_READ | DSLF_WRITE, &data, &pitch); + if (ret) + { + SetDirectFBerror("IDirectFBSurface::Lock", ret); + return -1; + } + + /* Find the pitch and offset values for the overlay */ + overlay->pitches[0] = (Uint16) pitch; + overlay->pixels[0] = (Uint8*) data; + + switch (overlay->format) + { + case SDL_YV12_OVERLAY: + case SDL_IYUV_OVERLAY: + /* Add the two extra planes */ + overlay->pitches[1] = overlay->pitches[0] / 2; + overlay->pitches[2] = overlay->pitches[0] / 2; + overlay->pixels[1] = overlay->pixels[0] + overlay->pitches[0] * overlay->h; + overlay->pixels[2] = overlay->pixels[1] + overlay->pitches[1] * overlay->h / 2; + break; + default: + /* Only one plane, no worries */ + break; + } + + return 0; +} + +void DirectFB_UnlockYUVOverlay(_THIS, SDL_Overlay *overlay) +{ + IDirectFBSurface *surface = overlay->hwdata->surface; + + overlay->pixels[0] = overlay->pixels[1] = overlay->pixels[2] = NULL; + + surface->Unlock (surface); +} + +int DirectFB_DisplayYUVOverlay(_THIS, SDL_Overlay *overlay, SDL_Rect *src, SDL_Rect *dst) +{ + DFBResult ret; + DFBDisplayLayerConfig conf; + IDirectFBDisplayLayer *primary = HIDDEN->layer; + IDirectFBDisplayLayer *layer = overlay->hwdata->layer; + + primary->GetConfiguration (primary, &conf); + + ret = layer->SetScreenLocation (layer, + dst->x / (float) conf.width, dst->y / (float) conf.height, + dst->w / (float) conf.width, dst->h / (float) conf.height ); + if (ret) + { + SetDirectFBerror("IDirectFBDisplayLayer::SetScreenLocation", ret); + return -1; + } + + return 0; +} + +void DirectFB_FreeYUVOverlay(_THIS, SDL_Overlay *overlay) +{ + struct private_yuvhwdata *hwdata; + + hwdata = overlay->hwdata; + if (hwdata) + { + if (hwdata->surface) + hwdata->surface->Release (hwdata->surface); + + if (hwdata->layer) + hwdata->layer->Release (hwdata->layer); + + free (hwdata); + } +} + diff --git a/3rdparty/SDL/src/video/directfb/SDL_DirectFB_yuv.h b/3rdparty/SDL/src/video/directfb/SDL_DirectFB_yuv.h new file mode 100644 index 0000000..64bc86f --- /dev/null +++ b/3rdparty/SDL/src/video/directfb/SDL_DirectFB_yuv.h @@ -0,0 +1,38 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* This is the DirectFB implementation of YUV video overlays */ + +#include "SDL_video.h" +#include "SDL_DirectFB_video.h" + +extern SDL_Overlay *DirectFB_CreateYUVOverlay(_THIS, int width, int height, Uint32 format, SDL_Surface *display); + +extern int DirectFB_LockYUVOverlay(_THIS, SDL_Overlay *overlay); + +extern void DirectFB_UnlockYUVOverlay(_THIS, SDL_Overlay *overlay); + +extern int DirectFB_DisplayYUVOverlay(_THIS, SDL_Overlay *overlay, SDL_Rect *src, SDL_Rect *dst); + +extern void DirectFB_FreeYUVOverlay(_THIS, SDL_Overlay *overlay); + diff --git a/3rdparty/SDL/src/video/dummy/SDL_nullevents.c b/3rdparty/SDL/src/video/dummy/SDL_nullevents.c new file mode 100644 index 0000000..177fc3f --- /dev/null +++ b/3rdparty/SDL/src/video/dummy/SDL_nullevents.c @@ -0,0 +1,45 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* Being a null driver, there's no event stream. We just define stubs for + most of the API. */ + +#include "SDL.h" +#include "../../events/SDL_sysevents.h" +#include "../../events/SDL_events_c.h" + +#include "SDL_nullvideo.h" +#include "SDL_nullevents_c.h" + +void DUMMY_PumpEvents(_THIS) +{ + /* do nothing. */ +} + +void DUMMY_InitOSKeymap(_THIS) +{ + /* do nothing. */ +} + +/* end of SDL_nullevents.c ... */ + diff --git a/3rdparty/SDL/src/video/dummy/SDL_nullevents_c.h b/3rdparty/SDL/src/video/dummy/SDL_nullevents_c.h new file mode 100644 index 0000000..3b65794 --- /dev/null +++ b/3rdparty/SDL/src/video/dummy/SDL_nullevents_c.h @@ -0,0 +1,33 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#include "SDL_nullvideo.h" + +/* Variables and functions exported by SDL_sysevents.c to other parts + of the native video subsystem (SDL_sysvideo.c) +*/ +extern void DUMMY_InitOSKeymap(_THIS); +extern void DUMMY_PumpEvents(_THIS); + +/* end of SDL_nullevents_c.h ... */ + diff --git a/3rdparty/SDL/src/video/dummy/SDL_nullmouse.c b/3rdparty/SDL/src/video/dummy/SDL_nullmouse.c new file mode 100644 index 0000000..47daea8 --- /dev/null +++ b/3rdparty/SDL/src/video/dummy/SDL_nullmouse.c @@ -0,0 +1,33 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#include "SDL_mouse.h" +#include "../../events/SDL_events_c.h" + +#include "SDL_nullmouse_c.h" + + +/* The implementation dependent data for the window manager cursor */ +struct WMcursor { + int unused; +}; diff --git a/3rdparty/SDL/src/video/dummy/SDL_nullmouse_c.h b/3rdparty/SDL/src/video/dummy/SDL_nullmouse_c.h new file mode 100644 index 0000000..479eb0e --- /dev/null +++ b/3rdparty/SDL/src/video/dummy/SDL_nullmouse_c.h @@ -0,0 +1,26 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#include "SDL_nullvideo.h" + +/* Functions to be exported */ diff --git a/3rdparty/SDL/src/video/dummy/SDL_nullvideo.c b/3rdparty/SDL/src/video/dummy/SDL_nullvideo.c new file mode 100644 index 0000000..7e096e2 --- /dev/null +++ b/3rdparty/SDL/src/video/dummy/SDL_nullvideo.c @@ -0,0 +1,239 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* Dummy SDL video driver implementation; this is just enough to make an + * SDL-based application THINK it's got a working video driver, for + * applications that call SDL_Init(SDL_INIT_VIDEO) when they don't need it, + * and also for use as a collection of stubs when porting SDL to a new + * platform for which you haven't yet written a valid video driver. + * + * This is also a great way to determine bottlenecks: if you think that SDL + * is a performance problem for a given platform, enable this driver, and + * then see if your application runs faster without video overhead. + * + * Initial work by Ryan C. Gordon (icculus@icculus.org). A good portion + * of this was cut-and-pasted from Stephane Peter's work in the AAlib + * SDL video driver. Renamed to "DUMMY" by Sam Lantinga. + */ + +#include "SDL_video.h" +#include "SDL_mouse.h" +#include "../SDL_sysvideo.h" +#include "../SDL_pixels_c.h" +#include "../../events/SDL_events_c.h" + +#include "SDL_nullvideo.h" +#include "SDL_nullevents_c.h" +#include "SDL_nullmouse_c.h" + +#define DUMMYVID_DRIVER_NAME "dummy" + +/* Initialization/Query functions */ +static int DUMMY_VideoInit(_THIS, SDL_PixelFormat *vformat); +static SDL_Rect **DUMMY_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags); +static SDL_Surface *DUMMY_SetVideoMode(_THIS, SDL_Surface *current, int width, int height, int bpp, Uint32 flags); +static int DUMMY_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors); +static void DUMMY_VideoQuit(_THIS); + +/* Hardware surface functions */ +static int DUMMY_AllocHWSurface(_THIS, SDL_Surface *surface); +static int DUMMY_LockHWSurface(_THIS, SDL_Surface *surface); +static void DUMMY_UnlockHWSurface(_THIS, SDL_Surface *surface); +static void DUMMY_FreeHWSurface(_THIS, SDL_Surface *surface); + +/* etc. */ +static void DUMMY_UpdateRects(_THIS, int numrects, SDL_Rect *rects); + +/* DUMMY driver bootstrap functions */ + +static int DUMMY_Available(void) +{ + const char *envr = SDL_getenv("SDL_VIDEODRIVER"); + if ((envr) && (SDL_strcmp(envr, DUMMYVID_DRIVER_NAME) == 0)) { + return(1); + } + + return(0); +} + +static void DUMMY_DeleteDevice(SDL_VideoDevice *device) +{ + SDL_free(device->hidden); + SDL_free(device); +} + +static SDL_VideoDevice *DUMMY_CreateDevice(int devindex) +{ + SDL_VideoDevice *device; + + /* Initialize all variables that we clean on shutdown */ + device = (SDL_VideoDevice *)SDL_malloc(sizeof(SDL_VideoDevice)); + if ( device ) { + SDL_memset(device, 0, (sizeof *device)); + device->hidden = (struct SDL_PrivateVideoData *) + SDL_malloc((sizeof *device->hidden)); + } + if ( (device == NULL) || (device->hidden == NULL) ) { + SDL_OutOfMemory(); + if ( device ) { + SDL_free(device); + } + return(0); + } + SDL_memset(device->hidden, 0, (sizeof *device->hidden)); + + /* Set the function pointers */ + device->VideoInit = DUMMY_VideoInit; + device->ListModes = DUMMY_ListModes; + device->SetVideoMode = DUMMY_SetVideoMode; + device->CreateYUVOverlay = NULL; + device->SetColors = DUMMY_SetColors; + device->UpdateRects = DUMMY_UpdateRects; + device->VideoQuit = DUMMY_VideoQuit; + device->AllocHWSurface = DUMMY_AllocHWSurface; + device->CheckHWBlit = NULL; + device->FillHWRect = NULL; + device->SetHWColorKey = NULL; + device->SetHWAlpha = NULL; + device->LockHWSurface = DUMMY_LockHWSurface; + device->UnlockHWSurface = DUMMY_UnlockHWSurface; + device->FlipHWSurface = NULL; + device->FreeHWSurface = DUMMY_FreeHWSurface; + device->SetCaption = NULL; + device->SetIcon = NULL; + device->IconifyWindow = NULL; + device->GrabInput = NULL; + device->GetWMInfo = NULL; + device->InitOSKeymap = DUMMY_InitOSKeymap; + device->PumpEvents = DUMMY_PumpEvents; + + device->free = DUMMY_DeleteDevice; + + return device; +} + +VideoBootStrap DUMMY_bootstrap = { + DUMMYVID_DRIVER_NAME, "SDL dummy video driver", + DUMMY_Available, DUMMY_CreateDevice +}; + + +int DUMMY_VideoInit(_THIS, SDL_PixelFormat *vformat) +{ + /* + fprintf(stderr, "WARNING: You are using the SDL dummy video driver!\n"); + */ + + /* Determine the screen depth (use default 8-bit depth) */ + /* we change this during the SDL_SetVideoMode implementation... */ + vformat->BitsPerPixel = 8; + vformat->BytesPerPixel = 1; + + /* We're done! */ + return(0); +} + +SDL_Rect **DUMMY_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags) +{ + return (SDL_Rect **) -1; +} + +SDL_Surface *DUMMY_SetVideoMode(_THIS, SDL_Surface *current, + int width, int height, int bpp, Uint32 flags) +{ + if ( this->hidden->buffer ) { + SDL_free( this->hidden->buffer ); + } + + this->hidden->buffer = SDL_malloc(width * height * (bpp / 8)); + if ( ! this->hidden->buffer ) { + SDL_SetError("Couldn't allocate buffer for requested mode"); + return(NULL); + } + +/* printf("Setting mode %dx%d\n", width, height); */ + + SDL_memset(this->hidden->buffer, 0, width * height * (bpp / 8)); + + /* Allocate the new pixel format for the screen */ + if ( ! SDL_ReallocFormat(current, bpp, 0, 0, 0, 0) ) { + SDL_free(this->hidden->buffer); + this->hidden->buffer = NULL; + SDL_SetError("Couldn't allocate new pixel format for requested mode"); + return(NULL); + } + + /* Set up the new mode framebuffer */ + current->flags = flags & SDL_FULLSCREEN; + this->hidden->w = current->w = width; + this->hidden->h = current->h = height; + current->pitch = current->w * (bpp / 8); + current->pixels = this->hidden->buffer; + + /* We're done */ + return(current); +} + +/* We don't actually allow hardware surfaces other than the main one */ +static int DUMMY_AllocHWSurface(_THIS, SDL_Surface *surface) +{ + return(-1); +} +static void DUMMY_FreeHWSurface(_THIS, SDL_Surface *surface) +{ + return; +} + +/* We need to wait for vertical retrace on page flipped displays */ +static int DUMMY_LockHWSurface(_THIS, SDL_Surface *surface) +{ + return(0); +} + +static void DUMMY_UnlockHWSurface(_THIS, SDL_Surface *surface) +{ + return; +} + +static void DUMMY_UpdateRects(_THIS, int numrects, SDL_Rect *rects) +{ + /* do nothing. */ +} + +int DUMMY_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors) +{ + /* do nothing of note. */ + return(1); +} + +/* Note: If we are terminated, this could be called in the middle of + another SDL video routine -- notably UpdateRects. +*/ +void DUMMY_VideoQuit(_THIS) +{ + if (this->screen->pixels != NULL) + { + SDL_free(this->screen->pixels); + this->screen->pixels = NULL; + } +} diff --git a/3rdparty/SDL/src/video/dummy/SDL_nullvideo.h b/3rdparty/SDL/src/video/dummy/SDL_nullvideo.h new file mode 100644 index 0000000..05c19e3 --- /dev/null +++ b/3rdparty/SDL/src/video/dummy/SDL_nullvideo.h @@ -0,0 +1,40 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#ifndef _SDL_nullvideo_h +#define _SDL_nullvideo_h + +#include "../SDL_sysvideo.h" + +/* Hidden "this" pointer for the video functions */ +#define _THIS SDL_VideoDevice *this + + +/* Private display data */ + +struct SDL_PrivateVideoData { + int w, h; + void *buffer; +}; + +#endif /* _SDL_nullvideo_h */ diff --git a/3rdparty/SDL/src/video/e_log.h b/3rdparty/SDL/src/video/e_log.h new file mode 100644 index 0000000..7f8bf71 --- /dev/null +++ b/3rdparty/SDL/src/video/e_log.h @@ -0,0 +1,140 @@ +/* @(#)e_log.c 5.1 93/09/24 */ +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunPro, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ + +#if defined(LIBM_SCCS) && !defined(lint) +static char rcsid[] = "$NetBSD: e_log.c,v 1.8 1995/05/10 20:45:49 jtc Exp $"; +#endif + +/* __ieee754_log(x) + * Return the logrithm of x + * + * Method : + * 1. Argument Reduction: find k and f such that + * x = 2^k * (1+f), + * where sqrt(2)/2 < 1+f < sqrt(2) . + * + * 2. Approximation of log(1+f). + * Let s = f/(2+f) ; based on log(1+f) = log(1+s) - log(1-s) + * = 2s + 2/3 s**3 + 2/5 s**5 + ....., + * = 2s + s*R + * We use a special Reme algorithm on [0,0.1716] to generate + * a polynomial of degree 14 to approximate R The maximum error + * of this polynomial approximation is bounded by 2**-58.45. In + * other words, + * 2 4 6 8 10 12 14 + * R(z) ~ Lg1*s +Lg2*s +Lg3*s +Lg4*s +Lg5*s +Lg6*s +Lg7*s + * (the values of Lg1 to Lg7 are listed in the program) + * and + * | 2 14 | -58.45 + * | Lg1*s +...+Lg7*s - R(z) | <= 2 + * | | + * Note that 2s = f - s*f = f - hfsq + s*hfsq, where hfsq = f*f/2. + * In order to guarantee error in log below 1ulp, we compute log + * by + * log(1+f) = f - s*(f - R) (if f is not too large) + * log(1+f) = f - (hfsq - s*(hfsq+R)). (better accuracy) + * + * 3. Finally, log(x) = k*ln2 + log(1+f). + * = k*ln2_hi+(f-(hfsq-(s*(hfsq+R)+k*ln2_lo))) + * Here ln2 is split into two floating point number: + * ln2_hi + ln2_lo, + * where n*ln2_hi is always exact for |n| < 2000. + * + * Special cases: + * log(x) is NaN with signal if x < 0 (including -INF) ; + * log(+INF) is +INF; log(0) is -INF with signal; + * log(NaN) is that NaN with no signal. + * + * Accuracy: + * according to an error analysis, the error is always less than + * 1 ulp (unit in the last place). + * + * Constants: + * The hexadecimal values are the intended ones for the following + * constants. The decimal values may be used, provided that the + * compiler will convert from decimal to binary accurately enough + * to produce the hexadecimal values shown. + */ + +/*#include "math.h"*/ +#include "math_private.h" + +#ifdef __STDC__ +static const double +#else +static double +#endif +ln2_hi = 6.93147180369123816490e-01, /* 3fe62e42 fee00000 */ +ln2_lo = 1.90821492927058770002e-10, /* 3dea39ef 35793c76 */ +Lg1 = 6.666666666666735130e-01, /* 3FE55555 55555593 */ +Lg2 = 3.999999999940941908e-01, /* 3FD99999 9997FA04 */ +Lg3 = 2.857142874366239149e-01, /* 3FD24924 94229359 */ +Lg4 = 2.222219843214978396e-01, /* 3FCC71C5 1D8E78AF */ +Lg5 = 1.818357216161805012e-01, /* 3FC74664 96CB03DE */ +Lg6 = 1.531383769920937332e-01, /* 3FC39A09 D078C69F */ +Lg7 = 1.479819860511658591e-01; /* 3FC2F112 DF3E5244 */ + +#ifdef __STDC__ + double __ieee754_log(double x) +#else + double __ieee754_log(x) + double x; +#endif +{ + double hfsq,f,s,z,R,w,t1,t2,dk; + int32_t k,hx,i,j; + u_int32_t lx; + + EXTRACT_WORDS(hx,lx,x); + + k=0; + if (hx < 0x00100000) { /* x < 2**-1022 */ + if (((hx&0x7fffffff)|lx)==0) + return -two54/zero; /* log(+-0)=-inf */ + if (hx<0) return (x-x)/zero; /* log(-#) = NaN */ + k -= 54; x *= two54; /* subnormal number, scale up x */ + GET_HIGH_WORD(hx,x); + } + if (hx >= 0x7ff00000) return x+x; + k += (hx>>20)-1023; + hx &= 0x000fffff; + i = (hx+0x95f64)&0x100000; + SET_HIGH_WORD(x,hx|(i^0x3ff00000)); /* normalize x or x/2 */ + k += (i>>20); + f = x-1.0; + if((0x000fffff&(2+hx))<3) { /* |f| < 2**-20 */ + if(f==zero) {if(k==0) return zero; else {dk=(double)k; + return dk*ln2_hi+dk*ln2_lo;} + } + R = f*f*(0.5-0.33333333333333333*f); + if(k==0) return f-R; else {dk=(double)k; + return dk*ln2_hi-((R-dk*ln2_lo)-f);} + } + s = f/(2.0+f); + dk = (double)k; + z = s*s; + i = hx-0x6147a; + w = z*z; + j = 0x6b851-hx; + t1= w*(Lg2+w*(Lg4+w*Lg6)); + t2= z*(Lg1+w*(Lg3+w*(Lg5+w*Lg7))); + i |= j; + R = t2+t1; + if(i>0) { + hfsq=0.5*f*f; + if(k==0) return f-(hfsq-s*(hfsq+R)); else + return dk*ln2_hi-((hfsq-(s*(hfsq+R)+dk*ln2_lo))-f); + } else { + if(k==0) return f-s*(f-R); else + return dk*ln2_hi-((s*(f-R)-dk*ln2_lo)-f); + } +} diff --git a/3rdparty/SDL/src/video/e_pow.h b/3rdparty/SDL/src/video/e_pow.h new file mode 100644 index 0000000..0aa372a --- /dev/null +++ b/3rdparty/SDL/src/video/e_pow.h @@ -0,0 +1,302 @@ +/* @(#)e_pow.c 5.1 93/09/24 */ +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunPro, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ + +#if defined(LIBM_SCCS) && !defined(lint) +static char rcsid[] = "$NetBSD: e_pow.c,v 1.9 1995/05/12 04:57:32 jtc Exp $"; +#endif + +/* __ieee754_pow(x,y) return x**y + * + * n + * Method: Let x = 2 * (1+f) + * 1. Compute and return log2(x) in two pieces: + * log2(x) = w1 + w2, + * where w1 has 53-24 = 29 bit trailing zeros. + * 2. Perform y*log2(x) = n+y' by simulating muti-precision + * arithmetic, where |y'|<=0.5. + * 3. Return x**y = 2**n*exp(y'*log2) + * + * Special cases: + * 1. (anything) ** 0 is 1 + * 2. (anything) ** 1 is itself + * 3. (anything) ** NAN is NAN + * 4. NAN ** (anything except 0) is NAN + * 5. +-(|x| > 1) ** +INF is +INF + * 6. +-(|x| > 1) ** -INF is +0 + * 7. +-(|x| < 1) ** +INF is +0 + * 8. +-(|x| < 1) ** -INF is +INF + * 9. +-1 ** +-INF is NAN + * 10. +0 ** (+anything except 0, NAN) is +0 + * 11. -0 ** (+anything except 0, NAN, odd integer) is +0 + * 12. +0 ** (-anything except 0, NAN) is +INF + * 13. -0 ** (-anything except 0, NAN, odd integer) is +INF + * 14. -0 ** (odd integer) = -( +0 ** (odd integer) ) + * 15. +INF ** (+anything except 0,NAN) is +INF + * 16. +INF ** (-anything except 0,NAN) is +0 + * 17. -INF ** (anything) = -0 ** (-anything) + * 18. (-anything) ** (integer) is (-1)**(integer)*(+anything**integer) + * 19. (-anything except 0 and inf) ** (non-integer) is NAN + * + * Accuracy: + * pow(x,y) returns x**y nearly rounded. In particular + * pow(integer,integer) + * always returns the correct integer provided it is + * representable. + * + * Constants : + * The hexadecimal values are the intended ones for the following + * constants. The decimal values may be used, provided that the + * compiler will convert from decimal to binary accurately enough + * to produce the hexadecimal values shown. + */ + +/*#include "math.h"*/ +#include "math_private.h" + +#ifdef __STDC__ +static const double +#else +static double +#endif +bp[] = {1.0, 1.5,}, +dp_h[] = { 0.0, 5.84962487220764160156e-01,}, /* 0x3FE2B803, 0x40000000 */ +dp_l[] = { 0.0, 1.35003920212974897128e-08,}, /* 0x3E4CFDEB, 0x43CFD006 */ + /* poly coefs for (3/2)*(log(x)-2s-2/3*s**3 */ +L1 = 5.99999999999994648725e-01, /* 0x3FE33333, 0x33333303 */ +L2 = 4.28571428578550184252e-01, /* 0x3FDB6DB6, 0xDB6FABFF */ +L3 = 3.33333329818377432918e-01, /* 0x3FD55555, 0x518F264D */ +L4 = 2.72728123808534006489e-01, /* 0x3FD17460, 0xA91D4101 */ +L5 = 2.30660745775561754067e-01, /* 0x3FCD864A, 0x93C9DB65 */ +L6 = 2.06975017800338417784e-01, /* 0x3FCA7E28, 0x4A454EEF */ +P1 = 1.66666666666666019037e-01, /* 0x3FC55555, 0x5555553E */ +P2 = -2.77777777770155933842e-03, /* 0xBF66C16C, 0x16BEBD93 */ +P3 = 6.61375632143793436117e-05, /* 0x3F11566A, 0xAF25DE2C */ +P4 = -1.65339022054652515390e-06, /* 0xBEBBBD41, 0xC5D26BF1 */ +P5 = 4.13813679705723846039e-08, /* 0x3E663769, 0x72BEA4D0 */ +lg2 = 6.93147180559945286227e-01, /* 0x3FE62E42, 0xFEFA39EF */ +lg2_h = 6.93147182464599609375e-01, /* 0x3FE62E43, 0x00000000 */ +lg2_l = -1.90465429995776804525e-09, /* 0xBE205C61, 0x0CA86C39 */ +ovt = 8.0085662595372944372e-0017, /* -(1024-log2(ovfl+.5ulp)) */ +cp = 9.61796693925975554329e-01, /* 0x3FEEC709, 0xDC3A03FD =2/(3ln2) */ +cp_h = 9.61796700954437255859e-01, /* 0x3FEEC709, 0xE0000000 =(float)cp */ +cp_l = -7.02846165095275826516e-09, /* 0xBE3E2FE0, 0x145B01F5 =tail of cp_h*/ +ivln2 = 1.44269504088896338700e+00, /* 0x3FF71547, 0x652B82FE =1/ln2 */ +ivln2_h = 1.44269502162933349609e+00, /* 0x3FF71547, 0x60000000 =24b 1/ln2*/ +ivln2_l = 1.92596299112661746887e-08; /* 0x3E54AE0B, 0xF85DDF44 =1/ln2 tail*/ + +#ifdef __STDC__ + double __ieee754_pow(double x, double y) +#else + double __ieee754_pow(x,y) + double x, y; +#endif +{ + double z,ax,z_h,z_l,p_h,p_l; + double y1,t1,t2,r,s,t,u,v,w; + int32_t i,j,k,yisint,n; + int32_t hx,hy,ix,iy; + u_int32_t lx,ly; + + EXTRACT_WORDS(hx,lx,x); + EXTRACT_WORDS(hy,ly,y); + ix = hx&0x7fffffff; iy = hy&0x7fffffff; + + /* y==zero: x**0 = 1 */ + if((iy|ly)==0) return one; + + /* +-NaN return x+y */ + if(ix > 0x7ff00000 || ((ix==0x7ff00000)&&(lx!=0)) || + iy > 0x7ff00000 || ((iy==0x7ff00000)&&(ly!=0))) + return x+y; + + /* determine if y is an odd int when x < 0 + * yisint = 0 ... y is not an integer + * yisint = 1 ... y is an odd int + * yisint = 2 ... y is an even int + */ + yisint = 0; + if(hx<0) { + if(iy>=0x43400000) yisint = 2; /* even integer y */ + else if(iy>=0x3ff00000) { + k = (iy>>20)-0x3ff; /* exponent */ + if(k>20) { + j = ly>>(52-k); + if((u_int32_t)(j<<(52-k))==ly) yisint = 2-(j&1); + } else if(ly==0) { + j = iy>>(20-k); + if((j<<(20-k))==iy) yisint = 2-(j&1); + } + } + } + + /* special value of y */ + if(ly==0) { + if (iy==0x7ff00000) { /* y is +-inf */ + if(((ix-0x3ff00000)|lx)==0) + return y - y; /* inf**+-1 is NaN */ + else if (ix >= 0x3ff00000)/* (|x|>1)**+-inf = inf,0 */ + return (hy>=0)? y: zero; + else /* (|x|<1)**-,+inf = inf,0 */ + return (hy<0)?-y: zero; + } + if(iy==0x3ff00000) { /* y is +-1 */ + if(hy<0) return one/x; else return x; + } + if(hy==0x40000000) return x*x; /* y is 2 */ + if(hy==0x3fe00000) { /* y is 0.5 */ + if(hx>=0) /* x >= +0 */ + return __ieee754_sqrt(x); + } + } + + ax = x < 0 ? -x : x; /*fabs(x);*/ + /* special value of x */ + if(lx==0) { + if(ix==0x7ff00000||ix==0||ix==0x3ff00000){ + z = ax; /*x is +-0,+-inf,+-1*/ + if(hy<0) z = one/z; /* z = (1/|x|) */ + if(hx<0) { + if(((ix-0x3ff00000)|yisint)==0) { + z = (z-z)/(z-z); /* (-1)**non-int is NaN */ + } else if(yisint==1) + z = -z; /* (x<0)**odd = -(|x|**odd) */ + } + return z; + } + } + + /* (x<0)**(non-int) is NaN */ + if(((((u_int32_t)hx>>31)-1)|yisint)==0) return (x-x)/(x-x); + + /* |y| is huge */ + if(iy>0x41e00000) { /* if |y| > 2**31 */ + if(iy>0x43f00000){ /* if |y| > 2**64, must o/uflow */ + if(ix<=0x3fefffff) return (hy<0)? huge*huge:tiny*tiny; + if(ix>=0x3ff00000) return (hy>0)? huge*huge:tiny*tiny; + } + /* over/underflow if x is not close to one */ + if(ix<0x3fefffff) return (hy<0)? huge*huge:tiny*tiny; + if(ix>0x3ff00000) return (hy>0)? huge*huge:tiny*tiny; + /* now |1-x| is tiny <= 2**-20, suffice to compute + log(x) by x-x^2/2+x^3/3-x^4/4 */ + t = x-1; /* t has 20 trailing zeros */ + w = (t*t)*(0.5-t*(0.3333333333333333333333-t*0.25)); + u = ivln2_h*t; /* ivln2_h has 21 sig. bits */ + v = t*ivln2_l-w*ivln2; + t1 = u+v; + SET_LOW_WORD(t1,0); + t2 = v-(t1-u); + } else { + double s2,s_h,s_l,t_h,t_l; + n = 0; + /* take care subnormal number */ + if(ix<0x00100000) + {ax *= two53; n -= 53; GET_HIGH_WORD(ix,ax); } + n += ((ix)>>20)-0x3ff; + j = ix&0x000fffff; + /* determine interval */ + ix = j|0x3ff00000; /* normalize ix */ + if(j<=0x3988E) k=0; /* |x|<sqrt(3/2) */ + else if(j<0xBB67A) k=1; /* |x|<sqrt(3) */ + else {k=0;n+=1;ix -= 0x00100000;} + SET_HIGH_WORD(ax,ix); + + /* compute s = s_h+s_l = (x-1)/(x+1) or (x-1.5)/(x+1.5) */ + u = ax-bp[k]; /* bp[0]=1.0, bp[1]=1.5 */ + v = one/(ax+bp[k]); + s = u*v; + s_h = s; + SET_LOW_WORD(s_h,0); + /* t_h=ax+bp[k] High */ + t_h = zero; + SET_HIGH_WORD(t_h,((ix>>1)|0x20000000)+0x00080000+(k<<18)); + t_l = ax - (t_h-bp[k]); + s_l = v*((u-s_h*t_h)-s_h*t_l); + /* compute log(ax) */ + s2 = s*s; + r = s2*s2*(L1+s2*(L2+s2*(L3+s2*(L4+s2*(L5+s2*L6))))); + r += s_l*(s_h+s); + s2 = s_h*s_h; + t_h = 3.0+s2+r; + SET_LOW_WORD(t_h,0); + t_l = r-((t_h-3.0)-s2); + /* u+v = s*(1+...) */ + u = s_h*t_h; + v = s_l*t_h+t_l*s; + /* 2/(3log2)*(s+...) */ + p_h = u+v; + SET_LOW_WORD(p_h,0); + p_l = v-(p_h-u); + z_h = cp_h*p_h; /* cp_h+cp_l = 2/(3*log2) */ + z_l = cp_l*p_h+p_l*cp+dp_l[k]; + /* log2(ax) = (s+..)*2/(3*log2) = n + dp_h + z_h + z_l */ + t = (double)n; + t1 = (((z_h+z_l)+dp_h[k])+t); + SET_LOW_WORD(t1,0); + t2 = z_l-(((t1-t)-dp_h[k])-z_h); + } + + s = one; /* s (sign of result -ve**odd) = -1 else = 1 */ + if(((((u_int32_t)hx>>31)-1)|(yisint-1))==0) + s = -one;/* (-ve)**(odd int) */ + + /* split up y into y1+y2 and compute (y1+y2)*(t1+t2) */ + y1 = y; + SET_LOW_WORD(y1,0); + p_l = (y-y1)*t1+y*t2; + p_h = y1*t1; + z = p_l+p_h; + EXTRACT_WORDS(j,i,z); + if (j>=0x40900000) { /* z >= 1024 */ + if(((j-0x40900000)|i)!=0) /* if z > 1024 */ + return s*huge*huge; /* overflow */ + else { + if(p_l+ovt>z-p_h) return s*huge*huge; /* overflow */ + } + } else if((j&0x7fffffff)>=0x4090cc00 ) { /* z <= -1075 */ + if(((j-0xc090cc00)|i)!=0) /* z < -1075 */ + return s*tiny*tiny; /* underflow */ + else { + if(p_l<=z-p_h) return s*tiny*tiny; /* underflow */ + } + } + /* + * compute 2**(p_h+p_l) + */ + i = j&0x7fffffff; + k = (i>>20)-0x3ff; + n = 0; + if(i>0x3fe00000) { /* if |z| > 0.5, set n = [z+0.5] */ + n = j+(0x00100000>>(k+1)); + k = ((n&0x7fffffff)>>20)-0x3ff; /* new k for n */ + t = zero; + SET_HIGH_WORD(t,n&~(0x000fffff>>k)); + n = ((n&0x000fffff)|0x00100000)>>(20-k); + if(j<0) n = -n; + p_h -= t; + } + t = p_l+p_h; + SET_LOW_WORD(t,0); + u = t*lg2_h; + v = (p_l-(t-p_h))*lg2+t*lg2_l; + z = u+v; + w = v-(z-u); + t = z*z; + t1 = z - t*(P1+t*(P2+t*(P3+t*(P4+t*P5)))); + r = (z*t1)/(t1-two)-(w+z*w); + z = one-(r-z); + GET_HIGH_WORD(j,z); + j += (n<<20); + if((j>>20)<=0) z = SDL_NAME(scalbn)(z,n); /* subnormal output */ + else SET_HIGH_WORD(z,j); + return s*z; +} diff --git a/3rdparty/SDL/src/video/e_sqrt.h b/3rdparty/SDL/src/video/e_sqrt.h new file mode 100644 index 0000000..657380e --- /dev/null +++ b/3rdparty/SDL/src/video/e_sqrt.h @@ -0,0 +1,493 @@ +/* @(#)e_sqrt.c 5.1 93/09/24 */ +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunPro, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ + +#if defined(LIBM_SCCS) && !defined(lint) +static char rcsid[] = "$NetBSD: e_sqrt.c,v 1.8 1995/05/10 20:46:17 jtc Exp $"; +#endif + +/* __ieee754_sqrt(x) + * Return correctly rounded sqrt. + * ------------------------------------------ + * | Use the hardware sqrt if you have one | + * ------------------------------------------ + * Method: + * Bit by bit method using integer arithmetic. (Slow, but portable) + * 1. Normalization + * Scale x to y in [1,4) with even powers of 2: + * find an integer k such that 1 <= (y=x*2^(2k)) < 4, then + * sqrt(x) = 2^k * sqrt(y) + * 2. Bit by bit computation + * Let q = sqrt(y) truncated to i bit after binary point (q = 1), + * i 0 + * i+1 2 + * s = 2*q , and y = 2 * ( y - q ). (1) + * i i i i + * + * To compute q from q , one checks whether + * i+1 i + * + * -(i+1) 2 + * (q + 2 ) <= y. (2) + * i + * -(i+1) + * If (2) is false, then q = q ; otherwise q = q + 2 . + * i+1 i i+1 i + * + * With some algebric manipulation, it is not difficult to see + * that (2) is equivalent to + * -(i+1) + * s + 2 <= y (3) + * i i + * + * The advantage of (3) is that s and y can be computed by + * i i + * the following recurrence formula: + * if (3) is false + * + * s = s , y = y ; (4) + * i+1 i i+1 i + * + * otherwise, + * -i -(i+1) + * s = s + 2 , y = y - s - 2 (5) + * i+1 i i+1 i i + * + * One may easily use induction to prove (4) and (5). + * Note. Since the left hand side of (3) contain only i+2 bits, + * it does not necessary to do a full (53-bit) comparison + * in (3). + * 3. Final rounding + * After generating the 53 bits result, we compute one more bit. + * Together with the remainder, we can decide whether the + * result is exact, bigger than 1/2ulp, or less than 1/2ulp + * (it will never equal to 1/2ulp). + * The rounding mode can be detected by checking whether + * huge + tiny is equal to huge, and whether huge - tiny is + * equal to huge for some floating point number "huge" and "tiny". + * + * Special cases: + * sqrt(+-0) = +-0 ... exact + * sqrt(inf) = inf + * sqrt(-ve) = NaN ... with invalid signal + * sqrt(NaN) = NaN ... with invalid signal for signaling NaN + * + * Other methods : see the appended file at the end of the program below. + *--------------- + */ + +/*#include "math.h"*/ +#include "math_private.h" + +#ifdef __STDC__ + double SDL_NAME(copysign)(double x, double y) +#else + double SDL_NAME(copysign)(x,y) + double x,y; +#endif +{ + u_int32_t hx,hy; + GET_HIGH_WORD(hx,x); + GET_HIGH_WORD(hy,y); + SET_HIGH_WORD(x,(hx&0x7fffffff)|(hy&0x80000000)); + return x; +} + +#ifdef __STDC__ + double SDL_NAME(scalbn) (double x, int n) +#else + double SDL_NAME(scalbn) (x,n) + double x; int n; +#endif +{ + int32_t k,hx,lx; + EXTRACT_WORDS(hx,lx,x); + k = (hx&0x7ff00000)>>20; /* extract exponent */ + if (k==0) { /* 0 or subnormal x */ + if ((lx|(hx&0x7fffffff))==0) return x; /* +-0 */ + x *= two54; + GET_HIGH_WORD(hx,x); + k = ((hx&0x7ff00000)>>20) - 54; + if (n< -50000) return tiny*x; /*underflow*/ + } + if (k==0x7ff) return x+x; /* NaN or Inf */ + k = k+n; + if (k > 0x7fe) return huge*SDL_NAME(copysign)(huge,x); /* overflow */ + if (k > 0) /* normal result */ + {SET_HIGH_WORD(x,(hx&0x800fffff)|(k<<20)); return x;} + if (k <= -54) { + if (n > 50000) /* in case integer overflow in n+k */ + return huge*SDL_NAME(copysign)(huge,x); /*overflow*/ + else return tiny*SDL_NAME(copysign)(tiny,x); /*underflow*/ + } + k += 54; /* subnormal result */ + SET_HIGH_WORD(x,(hx&0x800fffff)|(k<<20)); + return x*twom54; +} + +#ifdef __STDC__ + double __ieee754_sqrt(double x) +#else + double __ieee754_sqrt(x) + double x; +#endif +{ + double z; + int32_t sign = (int)0x80000000; + int32_t ix0,s0,q,m,t,i; + u_int32_t r,t1,s1,ix1,q1; + + EXTRACT_WORDS(ix0,ix1,x); + + /* take care of Inf and NaN */ + if((ix0&0x7ff00000)==0x7ff00000) { + return x*x+x; /* sqrt(NaN)=NaN, sqrt(+inf)=+inf + sqrt(-inf)=sNaN */ + } + /* take care of zero */ + if(ix0<=0) { + if(((ix0&(~sign))|ix1)==0) return x;/* sqrt(+-0) = +-0 */ + else if(ix0<0) + return (x-x)/(x-x); /* sqrt(-ve) = sNaN */ + } + /* normalize x */ + m = (ix0>>20); + if(m==0) { /* subnormal x */ + while(ix0==0) { + m -= 21; + ix0 |= (ix1>>11); ix1 <<= 21; + } + for(i=0;(ix0&0x00100000)==0;i++) ix0<<=1; + m -= i-1; + ix0 |= (ix1>>(32-i)); + ix1 <<= i; + } + m -= 1023; /* unbias exponent */ + ix0 = (ix0&0x000fffff)|0x00100000; + if(m&1){ /* odd m, double x to make it even */ + ix0 += ix0 + ((ix1&sign)>>31); + ix1 += ix1; + } + m >>= 1; /* m = [m/2] */ + + /* generate sqrt(x) bit by bit */ + ix0 += ix0 + ((ix1&sign)>>31); + ix1 += ix1; + q = q1 = s0 = s1 = 0; /* [q,q1] = sqrt(x) */ + r = 0x00200000; /* r = moving bit from right to left */ + + while(r!=0) { + t = s0+r; + if(t<=ix0) { + s0 = t+r; + ix0 -= t; + q += r; + } + ix0 += ix0 + ((ix1&sign)>>31); + ix1 += ix1; + r>>=1; + } + + r = sign; + while(r!=0) { + t1 = s1+r; + t = s0; + if((t<ix0)||((t==ix0)&&(t1<=ix1))) { + s1 = t1+r; + if(((int32_t)(t1&sign)==sign)&&(s1&sign)==0) s0 += 1; + ix0 -= t; + if (ix1 < t1) ix0 -= 1; + ix1 -= t1; + q1 += r; + } + ix0 += ix0 + ((ix1&sign)>>31); + ix1 += ix1; + r>>=1; + } + + /* use floating add to find out rounding direction */ + if((ix0|ix1)!=0) { + z = one-tiny; /* trigger inexact flag */ + if (z>=one) { + z = one+tiny; + if (q1==(u_int32_t)0xffffffff) { q1=0; q += 1;} + else if (z>one) { + if (q1==(u_int32_t)0xfffffffe) q+=1; + q1+=2; + } else + q1 += (q1&1); + } + } + ix0 = (q>>1)+0x3fe00000; + ix1 = q1>>1; + if ((q&1)==1) ix1 |= sign; + ix0 += (m <<20); + INSERT_WORDS(z,ix0,ix1); + return z; +} + +/* +Other methods (use floating-point arithmetic) +------------- +(This is a copy of a drafted paper by Prof W. Kahan +and K.C. Ng, written in May, 1986) + + Two algorithms are given here to implement sqrt(x) + (IEEE double precision arithmetic) in software. + Both supply sqrt(x) correctly rounded. The first algorithm (in + Section A) uses newton iterations and involves four divisions. + The second one uses reciproot iterations to avoid division, but + requires more multiplications. Both algorithms need the ability + to chop results of arithmetic operations instead of round them, + and the INEXACT flag to indicate when an arithmetic operation + is executed exactly with no roundoff error, all part of the + standard (IEEE 754-1985). The ability to perform shift, add, + subtract and logical AND operations upon 32-bit words is needed + too, though not part of the standard. + +A. sqrt(x) by Newton Iteration + + (1) Initial approximation + + Let x0 and x1 be the leading and the trailing 32-bit words of + a floating point number x (in IEEE double format) respectively + + 1 11 52 ...widths + ------------------------------------------------------ + x: |s| e | f | + ------------------------------------------------------ + msb lsb msb lsb ...order + + + ------------------------ ------------------------ + x0: |s| e | f1 | x1: | f2 | + ------------------------ ------------------------ + + By performing shifts and subtracts on x0 and x1 (both regarded + as integers), we obtain an 8-bit approximation of sqrt(x) as + follows. + + k := (x0>>1) + 0x1ff80000; + y0 := k - T1[31&(k>>15)]. ... y ~ sqrt(x) to 8 bits + Here k is a 32-bit integer and T1[] is an integer array containing + correction terms. Now magically the floating value of y (y's + leading 32-bit word is y0, the value of its trailing word is 0) + approximates sqrt(x) to almost 8-bit. + + Value of T1: + static int T1[32]= { + 0, 1024, 3062, 5746, 9193, 13348, 18162, 23592, + 29598, 36145, 43202, 50740, 58733, 67158, 75992, 85215, + 83599, 71378, 60428, 50647, 41945, 34246, 27478, 21581, + 16499, 12183, 8588, 5674, 3403, 1742, 661, 130,}; + + (2) Iterative refinement + + Apply Heron's rule three times to y, we have y approximates + sqrt(x) to within 1 ulp (Unit in the Last Place): + + y := (y+x/y)/2 ... almost 17 sig. bits + y := (y+x/y)/2 ... almost 35 sig. bits + y := y-(y-x/y)/2 ... within 1 ulp + + + Remark 1. + Another way to improve y to within 1 ulp is: + + y := (y+x/y) ... almost 17 sig. bits to 2*sqrt(x) + y := y - 0x00100006 ... almost 18 sig. bits to sqrt(x) + + 2 + (x-y )*y + y := y + 2* ---------- ...within 1 ulp + 2 + 3y + x + + + This formula has one division fewer than the one above; however, + it requires more multiplications and additions. Also x must be + scaled in advance to avoid spurious overflow in evaluating the + expression 3y*y+x. Hence it is not recommended uless division + is slow. If division is very slow, then one should use the + reciproot algorithm given in section B. + + (3) Final adjustment + + By twiddling y's last bit it is possible to force y to be + correctly rounded according to the prevailing rounding mode + as follows. Let r and i be copies of the rounding mode and + inexact flag before entering the square root program. Also we + use the expression y+-ulp for the next representable floating + numbers (up and down) of y. Note that y+-ulp = either fixed + point y+-1, or multiply y by nextafter(1,+-inf) in chopped + mode. + + I := FALSE; ... reset INEXACT flag I + R := RZ; ... set rounding mode to round-toward-zero + z := x/y; ... chopped quotient, possibly inexact + If(not I) then { ... if the quotient is exact + if(z=y) { + I := i; ... restore inexact flag + R := r; ... restore rounded mode + return sqrt(x):=y. + } else { + z := z - ulp; ... special rounding + } + } + i := TRUE; ... sqrt(x) is inexact + If (r=RN) then z=z+ulp ... rounded-to-nearest + If (r=RP) then { ... round-toward-+inf + y = y+ulp; z=z+ulp; + } + y := y+z; ... chopped sum + y0:=y0-0x00100000; ... y := y/2 is correctly rounded. + I := i; ... restore inexact flag + R := r; ... restore rounded mode + return sqrt(x):=y. + + (4) Special cases + + Square root of +inf, +-0, or NaN is itself; + Square root of a negative number is NaN with invalid signal. + + +B. sqrt(x) by Reciproot Iteration + + (1) Initial approximation + + Let x0 and x1 be the leading and the trailing 32-bit words of + a floating point number x (in IEEE double format) respectively + (see section A). By performing shifs and subtracts on x0 and y0, + we obtain a 7.8-bit approximation of 1/sqrt(x) as follows. + + k := 0x5fe80000 - (x0>>1); + y0:= k - T2[63&(k>>14)]. ... y ~ 1/sqrt(x) to 7.8 bits + + Here k is a 32-bit integer and T2[] is an integer array + containing correction terms. Now magically the floating + value of y (y's leading 32-bit word is y0, the value of + its trailing word y1 is set to zero) approximates 1/sqrt(x) + to almost 7.8-bit. + + Value of T2: + static int T2[64]= { + 0x1500, 0x2ef8, 0x4d67, 0x6b02, 0x87be, 0xa395, 0xbe7a, 0xd866, + 0xf14a, 0x1091b,0x11fcd,0x13552,0x14999,0x15c98,0x16e34,0x17e5f, + 0x18d03,0x19a01,0x1a545,0x1ae8a,0x1b5c4,0x1bb01,0x1bfde,0x1c28d, + 0x1c2de,0x1c0db,0x1ba73,0x1b11c,0x1a4b5,0x1953d,0x18266,0x16be0, + 0x1683e,0x179d8,0x18a4d,0x19992,0x1a789,0x1b445,0x1bf61,0x1c989, + 0x1d16d,0x1d77b,0x1dddf,0x1e2ad,0x1e5bf,0x1e6e8,0x1e654,0x1e3cd, + 0x1df2a,0x1d635,0x1cb16,0x1be2c,0x1ae4e,0x19bde,0x1868e,0x16e2e, + 0x1527f,0x1334a,0x11051,0xe951, 0xbe01, 0x8e0d, 0x5924, 0x1edd,}; + + (2) Iterative refinement + + Apply Reciproot iteration three times to y and multiply the + result by x to get an approximation z that matches sqrt(x) + to about 1 ulp. To be exact, we will have + -1ulp < sqrt(x)-z<1.0625ulp. + + ... set rounding mode to Round-to-nearest + y := y*(1.5-0.5*x*y*y) ... almost 15 sig. bits to 1/sqrt(x) + y := y*((1.5-2^-30)+0.5*x*y*y)... about 29 sig. bits to 1/sqrt(x) + ... special arrangement for better accuracy + z := x*y ... 29 bits to sqrt(x), with z*y<1 + z := z + 0.5*z*(1-z*y) ... about 1 ulp to sqrt(x) + + Remark 2. The constant 1.5-2^-30 is chosen to bias the error so that + (a) the term z*y in the final iteration is always less than 1; + (b) the error in the final result is biased upward so that + -1 ulp < sqrt(x) - z < 1.0625 ulp + instead of |sqrt(x)-z|<1.03125ulp. + + (3) Final adjustment + + By twiddling y's last bit it is possible to force y to be + correctly rounded according to the prevailing rounding mode + as follows. Let r and i be copies of the rounding mode and + inexact flag before entering the square root program. Also we + use the expression y+-ulp for the next representable floating + numbers (up and down) of y. Note that y+-ulp = either fixed + point y+-1, or multiply y by nextafter(1,+-inf) in chopped + mode. + + R := RZ; ... set rounding mode to round-toward-zero + switch(r) { + case RN: ... round-to-nearest + if(x<= z*(z-ulp)...chopped) z = z - ulp; else + if(x<= z*(z+ulp)...chopped) z = z; else z = z+ulp; + break; + case RZ:case RM: ... round-to-zero or round-to--inf + R:=RP; ... reset rounding mod to round-to-+inf + if(x<z*z ... rounded up) z = z - ulp; else + if(x>=(z+ulp)*(z+ulp) ...rounded up) z = z+ulp; + break; + case RP: ... round-to-+inf + if(x>(z+ulp)*(z+ulp)...chopped) z = z+2*ulp; else + if(x>z*z ...chopped) z = z+ulp; + break; + } + + Remark 3. The above comparisons can be done in fixed point. For + example, to compare x and w=z*z chopped, it suffices to compare + x1 and w1 (the trailing parts of x and w), regarding them as + two's complement integers. + + ...Is z an exact square root? + To determine whether z is an exact square root of x, let z1 be the + trailing part of z, and also let x0 and x1 be the leading and + trailing parts of x. + + If ((z1&0x03ffffff)!=0) ... not exact if trailing 26 bits of z!=0 + I := 1; ... Raise Inexact flag: z is not exact + else { + j := 1 - [(x0>>20)&1] ... j = logb(x) mod 2 + k := z1 >> 26; ... get z's 25-th and 26-th + fraction bits + I := i or (k&j) or ((k&(j+j+1))!=(x1&3)); + } + R:= r ... restore rounded mode + return sqrt(x):=z. + + If multiplication is cheaper then the foregoing red tape, the + Inexact flag can be evaluated by + + I := i; + I := (z*z!=x) or I. + + Note that z*z can overwrite I; this value must be sensed if it is + True. + + Remark 4. If z*z = x exactly, then bit 25 to bit 0 of z1 must be + zero. + + -------------------- + z1: | f2 | + -------------------- + bit 31 bit 0 + + Further more, bit 27 and 26 of z1, bit 0 and 1 of x1, and the odd + or even of logb(x) have the following relations: + + ------------------------------------------------- + bit 27,26 of z1 bit 1,0 of x1 logb(x) + ------------------------------------------------- + 00 00 odd and even + 01 01 even + 10 10 odd + 10 00 even + 11 01 even + ------------------------------------------------- + + (4) Special cases (see (4) of Section A). + + */ + diff --git a/3rdparty/SDL/src/video/fbcon/3dfx_mmio.h b/3rdparty/SDL/src/video/fbcon/3dfx_mmio.h new file mode 100644 index 0000000..b641454 --- /dev/null +++ b/3rdparty/SDL/src/video/fbcon/3dfx_mmio.h @@ -0,0 +1,56 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* 3Dfx register definitions */ + +#include "3dfx_regs.h" + +/* 3Dfx control macros */ + +#define tdfx_in8(reg) *(volatile Uint8 *)(mapped_io + (reg)) +#define tdfx_in32(reg) *(volatile Uint32 *)(mapped_io + (reg)) + +#define tdfx_out8(reg,v) *(volatile Uint8 *)(mapped_io + (reg)) = v; +#define tdfx_out32(reg,v) *(volatile Uint32 *)(mapped_io + (reg)) = v; + + +/* Wait for fifo space */ +#define tdfx_wait(space) \ +{ \ + while ( (tdfx_in8(TDFX_STATUS) & 0x1F) < space ) \ + ; \ +} + + +/* Wait for idle accelerator */ +#define tdfx_waitidle() \ +{ \ + int i = 0; \ + \ + tdfx_wait(1); \ + tdfx_out32(COMMAND_3D, COMMAND_3D_NOP); \ + do { \ + i = (tdfx_in32(TDFX_STATUS) & STATUS_BUSY) ? 0 : i + 1; \ + } while ( i != 3 ); \ +} + diff --git a/3rdparty/SDL/src/video/fbcon/3dfx_regs.h b/3rdparty/SDL/src/video/fbcon/3dfx_regs.h new file mode 100644 index 0000000..e86f727 --- /dev/null +++ b/3rdparty/SDL/src/video/fbcon/3dfx_regs.h @@ -0,0 +1,83 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#ifndef _3DFX_REGS_H +#define _3DFX_REGS_H + +/* This information comes from the public 3Dfx specs for the Voodoo 3000 */ + +/* mapped_io register offsets */ +#define TDFX_STATUS 0x00 + +#define INTCTRL (0x00100000 + 0x04) +#define CLIP0MIN (0x00100000 + 0x08) +#define CLIP0MAX (0x00100000 + 0x0c) +#define DSTBASE (0x00100000 + 0x10) +#define DSTFORMAT (0x00100000 + 0x14) +#define SRCCOLORKEYMIN (0x00100000 + 0x18) +#define SRCCOLORKEYMAX (0x00100000 + 0x1c) +#define DSTCOLORKEYMIN (0x00100000 + 0x20) +#define DSTCOLORKEYMAX (0x00100000 + 0x24) +#define BRESERROR0 (0x00100000 + 0x28) +#define BRESERROR1 (0x00100000 + 0x2c) +#define ROP_2D (0x00100000 + 0x30) +#define SRCBASE (0x00100000 + 0x34) +#define COMMANDEXTRA_2D (0x00100000 + 0x38) +#define PATTERN0 (0x00100000 + 0x44) +#define PATTERN1 (0x00100000 + 0x48) +#define CLIP1MIN (0x00100000 + 0x4c) +#define CLIP1MAX (0x00100000 + 0x50) +#define SRCFORMAT (0x00100000 + 0x54) +#define SRCSIZE (0x00100000 + 0x58) +#define SRCXY (0x00100000 + 0x5c) +#define COLORBACK (0x00100000 + 0x60) +#define COLORFORE (0x00100000 + 0x64) +#define DSTSIZE (0x00100000 + 0x68) +#define DSTXY (0x00100000 + 0x6c) +#define COMMAND_2D (0x00100000 + 0x70) +#define LAUNCH_2D (0x00100000 + 0x80) +#define PATTERNBASE (0x00100000 + 0x100) + +#define COMMAND_3D (0x00200000 + 0x120) + +/* register bitfields (not all, only as needed) */ + +#define BIT(x) (1UL << (x)) + +#define COMMAND_2D_BITBLT 0x01 +#define COMMAND_2D_FILLRECT 0x05 +#define COMMAND_2D_LINE 0x06 +#define COMMAND_2D_POLYGON_FILL 0x08 +#define COMMAND_2D_INITIATE BIT(8) +#define COMMAND_2D_REVERSELINE BIT(9) +#define COMMAND_2D_STIPPLELINE BIT(12) +#define COMMAND_2D_MONOCHROME_PATT BIT(13) +#define COMMAND_2D_MONOCHROME_TRANSP BIT(16) + +#define COMMAND_3D_NOP 0x00 + +#define STATUS_RETRACE BIT(6) +#define STATUS_BUSY BIT(9) + +#endif /* _3DFX_REGS_H */ + diff --git a/3rdparty/SDL/src/video/fbcon/SDL_fb3dfx.c b/3rdparty/SDL/src/video/fbcon/SDL_fb3dfx.c new file mode 100644 index 0000000..eb083b8 --- /dev/null +++ b/3rdparty/SDL/src/video/fbcon/SDL_fb3dfx.c @@ -0,0 +1,215 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#include "SDL_video.h" +#include "../SDL_blit.h" +#include "SDL_fb3dfx.h" +#include "3dfx_mmio.h" + + +/* Wait for vertical retrace */ +static void WaitVBL(_THIS) +{ + /* find start of retrace */ + tdfx_waitidle(); + while( (tdfx_in32(TDFX_STATUS) & STATUS_RETRACE) == STATUS_RETRACE ) + ; + /* wait until we're past the start */ + while( (tdfx_in32(TDFX_STATUS) & STATUS_RETRACE) == 0 ) + ; +} +static void WaitIdle(_THIS) +{ + tdfx_waitidle(); +} + +/* Sets video mem colorkey and accelerated blit function */ +static int SetHWColorKey(_THIS, SDL_Surface *surface, Uint32 key) +{ + return(0); +} + +static int FillHWRect(_THIS, SDL_Surface *dst, SDL_Rect *rect, Uint32 color) +{ + int bpp; + Uint32 dst_base; + Uint32 format; + int dstX, dstY; + + /* Don't blit to the display surface when switched away */ + if ( switched_away ) { + return -2; /* no hardware access */ + } + if ( dst == this->screen ) { + SDL_mutexP(hw_lock); + } + + /* Set the destination pixel format */ + dst_base = ((char *)dst->pixels - mapped_mem); + bpp = dst->format->BitsPerPixel; + format = dst->pitch | ((bpp+((bpp==8) ? 0 : 8)) << 13); + + /* Calculate source and destination base coordinates */ + dstX = rect->x; + dstY = rect->y; + + /* Execute the fill command */ + tdfx_wait(6); + tdfx_out32(DSTBASE, dst_base); + tdfx_out32(DSTFORMAT, format); + tdfx_out32(COLORFORE, color); + tdfx_out32(COMMAND_2D, COMMAND_2D_FILLRECT); + tdfx_out32(DSTSIZE, rect->w | (rect->h << 16)); + tdfx_out32(LAUNCH_2D, dstX | (dstY << 16)); + + FB_AddBusySurface(dst); + + if ( dst == this->screen ) { + SDL_mutexV(hw_lock); + } + return(0); +} + +static int HWAccelBlit(SDL_Surface *src, SDL_Rect *srcrect, + SDL_Surface *dst, SDL_Rect *dstrect) +{ + SDL_VideoDevice *this = current_video; + int bpp; + Uint32 src_format; + Uint32 src_base; + Uint32 dst_base; + int srcX, srcY; + int dstX, dstY; + Uint32 blitop; + Uint32 use_colorkey; + + /* Don't blit to the display surface when switched away */ + if ( switched_away ) { + return -2; /* no hardware access */ + } + if ( dst == this->screen ) { + SDL_mutexP(hw_lock); + } + + /* Set the source and destination pixel format */ + src_base = ((char *)src->pixels - mapped_mem); + bpp = src->format->BitsPerPixel; + src_format = src->pitch | ((bpp+((bpp==8) ? 0 : 8)) << 13); + dst_base = ((char *)dst->pixels - mapped_mem); + bpp = dst->format->BitsPerPixel; + + srcX = srcrect->x; + srcY = srcrect->y; + dstX = dstrect->x; + dstY = dstrect->y; + + /* Assemble the blit operation */ + blitop = COMMAND_2D_BITBLT | (0xCC << 24); + if ( srcX <= dstX ) { + blitop |= BIT(14); + srcX += (dstrect->w - 1); + dstX += (dstrect->w - 1); + } + if ( srcY <= dstY ) { + blitop |= BIT(15); + srcY += (dstrect->h - 1); + dstY += (dstrect->h - 1); + } + + /* Perform the blit! */ + if ( (src->flags & SDL_SRCCOLORKEY) == SDL_SRCCOLORKEY ) { + tdfx_wait(3); + tdfx_out32(SRCCOLORKEYMIN, src->format->colorkey); + tdfx_out32(SRCCOLORKEYMAX, src->format->colorkey); + tdfx_out32(ROP_2D, 0xAA00); + use_colorkey = 1; + } else { + use_colorkey = 0; + } + tdfx_wait(9); + tdfx_out32(SRCBASE, (Uint32)src_base); + tdfx_out32(SRCFORMAT, src_format); + tdfx_out32(DSTBASE, (Uint32)dst_base); + tdfx_out32(DSTFORMAT, src_format); + tdfx_out32(COMMAND_2D, blitop); + tdfx_out32(COMMANDEXTRA_2D, use_colorkey); + tdfx_out32(DSTSIZE, dstrect->w | (dstrect->h << 16)); + tdfx_out32(DSTXY, dstX | (dstY << 16)); + tdfx_out32(LAUNCH_2D, srcX | (srcY << 16)); + + FB_AddBusySurface(src); + FB_AddBusySurface(dst); + + if ( dst == this->screen ) { + SDL_mutexV(hw_lock); + } + return(0); +} + +static int CheckHWBlit(_THIS, SDL_Surface *src, SDL_Surface *dst) +{ + int accelerated; + + /* Set initial acceleration on */ + src->flags |= SDL_HWACCEL; + + /* Set the surface attributes */ + if ( (src->flags & SDL_SRCALPHA) == SDL_SRCALPHA ) { + if ( ! this->info.blit_hw_A ) { + src->flags &= ~SDL_HWACCEL; + } + } + if ( (src->flags & SDL_SRCCOLORKEY) == SDL_SRCCOLORKEY ) { + if ( ! this->info.blit_hw_CC ) { + src->flags &= ~SDL_HWACCEL; + } + } + + /* Check to see if final surface blit is accelerated */ + accelerated = !!(src->flags & SDL_HWACCEL); + if ( accelerated ) { + src->map->hw_blit = HWAccelBlit; + } + return(accelerated); +} + +void FB_3DfxAccel(_THIS, __u32 card) +{ + /* We have hardware accelerated surface functions */ + this->CheckHWBlit = CheckHWBlit; + wait_vbl = WaitVBL; + wait_idle = WaitIdle; + + /* Reset the 3Dfx controller */ + tdfx_out32(BRESERROR0, 0); + tdfx_out32(BRESERROR1, 0); + + /* The 3Dfx has an accelerated color fill */ + this->info.blit_fill = 1; + this->FillHWRect = FillHWRect; + + /* The 3Dfx has accelerated normal and colorkey blits */ + this->info.blit_hw = 1; + this->info.blit_hw_CC = 1; + this->SetHWColorKey = SetHWColorKey; +} diff --git a/3rdparty/SDL/src/video/fbcon/SDL_fb3dfx.h b/3rdparty/SDL/src/video/fbcon/SDL_fb3dfx.h new file mode 100644 index 0000000..4a59de9 --- /dev/null +++ b/3rdparty/SDL/src/video/fbcon/SDL_fb3dfx.h @@ -0,0 +1,29 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* 3Dfx hardware acceleration for the SDL framebuffer console driver */ + +#include "SDL_fbvideo.h" + +/* Set up the driver for 3Dfx acceleration */ +extern void FB_3DfxAccel(_THIS, __u32 card); diff --git a/3rdparty/SDL/src/video/fbcon/SDL_fbelo.c b/3rdparty/SDL/src/video/fbcon/SDL_fbelo.c new file mode 100644 index 0000000..63dff87 --- /dev/null +++ b/3rdparty/SDL/src/video/fbcon/SDL_fbelo.c @@ -0,0 +1,442 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#include <unistd.h> +#include <sys/time.h> +#include <ctype.h> + +#include "SDL_stdinc.h" +#include "SDL_fbvideo.h" +#include "SDL_fbelo.h" + +/* + calibration default values + values are read from the following environment variables: + + SDL_ELO_MIN_X + SDL_ELO_MAX_X + SDL_ELO_MIN_Y + SDL_ELO_MAX_Y +*/ + +static int ELO_MIN_X = 400; +static int ELO_MAX_X = 3670; +static int ELO_MIN_Y = 500; +static int ELO_MAX_Y = 3540; + +#define ELO_SNAP_SIZE 6 +#define ELO_TOUCH_BYTE 'T' +#define ELO_ID 'I' +#define ELO_MODE 'M' +#define ELO_PARAMETER 'P' +#define ELO_REPORT 'B' +#define ELO_ACK 'A' + +#define ELO_INIT_CHECKSUM 0xAA + +#define ELO_BTN_PRESS 0x01 +#define ELO_STREAM 0x02 +#define ELO_BTN_RELEASE 0x04 + +#define ELO_TOUCH_MODE 0x01 +#define ELO_STREAM_MODE 0x02 +#define ELO_UNTOUCH_MODE 0x04 +#define ELO_RANGE_CHECK_MODE 0x40 +#define ELO_TRIM_MODE 0x02 +#define ELO_CALIB_MODE 0x04 +#define ELO_SCALING_MODE 0x08 +#define ELO_TRACKING_MODE 0x40 + +#define ELO_SERIAL_MASK 0xF8 + +#define ELO_SERIAL_IO '0' + +#define ELO_MAX_TRIALS 3 +#define ELO_MAX_WAIT 100000 +#define ELO_UNTOUCH_DELAY 5 +#define ELO_REPORT_DELAY 1 + +/* eloParsePacket +*/ +int eloParsePacket(unsigned char* mousebuf, int* dx, int* dy, int* button_state) { + static int elo_button = 0; + static int last_x = 0; + static int last_y = 0; + int x,y; + + /* Check if we have a touch packet */ + if (mousebuf[1] != ELO_TOUCH_BYTE) { + return 0; + } + + x = ((mousebuf[4] << 8) | mousebuf[3]); + y = ((mousebuf[6] << 8) | mousebuf[5]); + + if((SDL_abs(x - last_x) > ELO_SNAP_SIZE) || (SDL_abs(y - last_y) > ELO_SNAP_SIZE)) { + *dx = ((mousebuf[4] << 8) | mousebuf[3]); + *dy = ((mousebuf[6] << 8) | mousebuf[5]); + } + else { + *dx = last_x; + *dy = last_y; + } + + last_x = *dx; + last_y = *dy; + + if ( (mousebuf[2] & 0x07) == ELO_BTN_PRESS ) { + elo_button = 1; + } + if ( (mousebuf[2] & 0x07) == ELO_BTN_RELEASE ) { + elo_button = 0; + } + + *button_state = elo_button; + return 1; +} + +/* Convert the raw coordinates from the ELO controller + to a screen position. +*/ +void eloConvertXY(_THIS, int *dx, int *dy) { + int input_x = *dx; + int input_y = *dy; + int width = ELO_MAX_X - ELO_MIN_X; + int height = ELO_MAX_Y - ELO_MIN_Y; + + *dx = ((int)cache_vinfo.xres - ((int)cache_vinfo.xres * (input_x - ELO_MIN_X)) / width); + *dy = (cache_vinfo.yres * (input_y - ELO_MIN_Y)) / height; +} + + +/* eloGetPacket +*/ +int eloGetPacket(unsigned char* buffer, int* buffer_p, int* checksum, int fd) { + int num_bytes; + int ok; + + if(fd == 0) { + num_bytes = ELO_PACKET_SIZE; + } + else { + num_bytes = read(fd, + (char *) (buffer + *buffer_p), + ELO_PACKET_SIZE - *buffer_p); + } + + if (num_bytes < 0) { +#ifdef DEBUG_MOUSE + fprintf(stderr, "System error while reading from Elographics touchscreen.\n"); +#endif + return 0; + } + + while (num_bytes) { + if ((*buffer_p == 0) && (buffer[0] != ELO_START_BYTE)) { + SDL_memcpy(&buffer[0], &buffer[1], num_bytes-1); + } + else { + if (*buffer_p < ELO_PACKET_SIZE-1) { + *checksum = *checksum + buffer[*buffer_p]; + *checksum = *checksum % 256; + } + (*buffer_p)++; + } + num_bytes--; + } + + if (*buffer_p == ELO_PACKET_SIZE) { + ok = (*checksum == buffer[ELO_PACKET_SIZE-1]); + *checksum = ELO_INIT_CHECKSUM; + *buffer_p = 0; + + if (!ok) { + return 0; + } + + return 1; + } + else { + return 0; + } +} + +/* eloSendPacket +*/ + +int eloSendPacket(unsigned char* packet, int fd) +{ + int i, result; + int sum = ELO_INIT_CHECKSUM; + + packet[0] = ELO_START_BYTE; + for (i = 0; i < ELO_PACKET_SIZE-1; i++) { + sum += packet[i]; + sum &= 0xFF; + } + packet[ELO_PACKET_SIZE-1] = sum; + + result = write(fd, packet, ELO_PACKET_SIZE); + + if (result != ELO_PACKET_SIZE) { +#ifdef DEBUG_MOUSE + printf("System error while sending to Elographics touchscreen.\n"); +#endif + return 0; + } + else { + return 1; + } +} + + +/* eloWaitForInput + */ +int eloWaitForInput(int fd, int timeout) +{ + fd_set readfds; + struct timeval to; + int r; + + FD_ZERO(&readfds); + FD_SET(fd, &readfds); + to.tv_sec = 0; + to.tv_usec = timeout; + + r = select(FD_SETSIZE, &readfds, NULL, NULL, &to); + return r; +} + +/* eloWaitReply + */ +int eloWaitReply(unsigned char type, unsigned char *reply, int fd) { + int ok; + int i, result; + int reply_p = 0; + int sum = ELO_INIT_CHECKSUM; + + i = ELO_MAX_TRIALS; + do { + ok = 0; + + result = eloWaitForInput(fd, ELO_MAX_WAIT); + + if (result > 0) { + ok = eloGetPacket(reply, &reply_p, &sum, fd); + + if (ok && reply[1] != type && type != ELO_PARAMETER) { +#ifdef DEBUG_MOUSE + fprintf(stderr, "Wrong reply received\n"); +#endif + ok = 0; + } + } + else { +#ifdef DEBUG_MOUSE + fprintf(stderr, "No input!\n"); +#endif + } + + if (result == 0) { + i--; + } + } while(!ok && (i>0)); + + return ok; +} + + +/* eloWaitAck + */ + +int eloWaitAck(int fd) { + unsigned char packet[ELO_PACKET_SIZE]; + int i, nb_errors; + + if (eloWaitReply(ELO_ACK, packet, fd)) { + for (i = 0, nb_errors = 0; i < 4; i++) { + if (packet[2 + i] != '0') { + nb_errors++; + } + } + + if (nb_errors != 0) { +#ifdef DEBUG_MOUSE + fprintf(stderr, "Elographics acknowledge packet reports %d errors\n", nb_errors); +#endif + } + return 1; + } + else { + return 0; + } +} + + +/* eloSendQuery -- +*/ +int eloSendQuery(unsigned char *request, unsigned char* reply, int fd) { + int ok; + + if (eloSendPacket(request, fd)) { + ok = eloWaitReply(toupper(request[1]), reply, fd); + if (ok) { + ok = eloWaitAck(fd); + } + return ok; + } + else { + return 0; + } +} + + +/* eloSendControl +*/ +int eloSendControl(unsigned char* control, int fd) { + if (eloSendPacket(control, fd)) { + return eloWaitAck(fd); + } + else { + return 0; + } +} + +/* eloInitController +*/ +int eloInitController(int fd) { + unsigned char req[ELO_PACKET_SIZE]; + unsigned char reply[ELO_PACKET_SIZE]; + const char *buffer = NULL; + int result = 0; + + struct termios mouse_termios; + + /* try to read the calibration values */ + buffer = SDL_getenv("SDL_ELO_MIN_X"); + if(buffer) { + ELO_MIN_X = SDL_atoi(buffer); + } + buffer = SDL_getenv("SDL_ELO_MAX_X"); + if(buffer) { + ELO_MAX_X = SDL_atoi(buffer); + } + buffer = SDL_getenv("SDL_ELO_MIN_Y"); + if(buffer) { + ELO_MIN_Y = SDL_atoi(buffer); + } + buffer = SDL_getenv("SDL_ELO_MAX_Y"); + if(buffer) { + ELO_MAX_Y = SDL_atoi(buffer); + } + +#ifdef DEBUG_MOUSE + fprintf( stderr, "ELO calibration values:\nmin_x: %i\nmax_x: %i\nmin_y: %i\nmax_y: %i\n", + ELO_MIN_X, + ELO_MAX_X, + ELO_MIN_Y, + ELO_MAX_Y); +#endif + + /* set comm params */ + SDL_memset(&mouse_termios, 0, sizeof(mouse_termios)); + mouse_termios.c_cflag = B9600 | CS8 | CREAD | CLOCAL; + mouse_termios.c_cc[VMIN] = 1; + result = tcsetattr(fd, TCSANOW, &mouse_termios); + + if (result < 0) { +#ifdef DEBUG_MOUSE + fprintf( stderr, "Unable to configure Elographics touchscreen port\n"); +#endif + return 0; + } + + SDL_memset(req, 0, ELO_PACKET_SIZE); + req[1] = tolower(ELO_PARAMETER); + if (!eloSendQuery(req, reply, fd)) { +#ifdef DEBUG_MOUSE + fprintf( stderr, "Not at the specified rate or model 2310, will continue\n"); +#endif + } + + SDL_memset(req, 0, ELO_PACKET_SIZE); + req[1] = tolower(ELO_ID); + if (eloSendQuery(req, reply, fd)) { +#ifdef DEBUG_MOUSE + fprintf(stderr, "Ok, controller configured!\n"); +#endif + } + else { +#ifdef DEBUG_MOUSE + fprintf( stderr, "Unable to ask Elographics touchscreen identification\n"); +#endif + return 0; + } + + SDL_memset(req, 0, ELO_PACKET_SIZE); + req[1] = ELO_MODE; + req[3] = ELO_TOUCH_MODE | ELO_STREAM_MODE | ELO_UNTOUCH_MODE; + req[4] = ELO_TRACKING_MODE; + if (!eloSendControl(req, fd)) { +#ifdef DEBUG_MOUSE + fprintf( stderr, "Unable to change Elographics touchscreen operating mode\n"); +#endif + return 0; + } + + SDL_memset(req, 0, ELO_PACKET_SIZE); + req[1] = ELO_REPORT; + req[2] = ELO_UNTOUCH_DELAY; + req[3] = ELO_REPORT_DELAY; + if (!eloSendControl(req, fd)) { +#ifdef DEBUG_MOUSE + fprintf( stderr, "Unable to change Elographics touchscreen reports timings\n"); +#endif + return 0; + } + + return 1; +} + +int eloReadPosition(_THIS, int fd, int* x, int* y, int* button_state, int* realx, int* realy) { + unsigned char buffer[ELO_PACKET_SIZE]; + int pointer = 0; + int checksum = ELO_INIT_CHECKSUM; + + while(pointer < ELO_PACKET_SIZE) { + if(eloGetPacket(buffer, &pointer, &checksum, fd)) { + break; + } + } + + if(!eloParsePacket(buffer, realx, realy, button_state)) { + return 0; + } + + *x = *realx; + *y = *realy; + + eloConvertXY(this, x, y); + + return 1; +} diff --git a/3rdparty/SDL/src/video/fbcon/SDL_fbelo.h b/3rdparty/SDL/src/video/fbcon/SDL_fbelo.h new file mode 100644 index 0000000..e7fde4f --- /dev/null +++ b/3rdparty/SDL/src/video/fbcon/SDL_fbelo.h @@ -0,0 +1,55 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#ifndef SDL_fbelo_h +#define SDL_fbelo_h + +#include "SDL_fbvideo.h" + +/* ELO */ +#define ELO_PACKET_SIZE 10 +#define ELO_START_BYTE 'U' + +/* eloConvertXY + Convert the raw coordinates from the ELO controller + to a screen position. +*/ +void eloConvertXY(_THIS, int *dx, int *dy); + +/* eloInitController(int fd) + Initialize the ELO serial touchscreen controller +*/ +int eloInitController(int fd); + +/* eloParsePacket + extract position and button state from a packet +*/ +int eloParsePacket(unsigned char* mousebuf, int* dx, int* dy, int* button_state); + +/* eloReadPosition + read a packet and get the cursor position +*/ + +int eloReadPosition(_THIS, int fd, int* x, int* y, int* button_state, int* realx, int* realy); + +#endif /* SDL_fbelo_h */ diff --git a/3rdparty/SDL/src/video/fbcon/SDL_fbevents.c b/3rdparty/SDL/src/video/fbcon/SDL_fbevents.c new file mode 100644 index 0000000..5e369a4 --- /dev/null +++ b/3rdparty/SDL/src/video/fbcon/SDL_fbevents.c @@ -0,0 +1,1254 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* Handle the event stream, converting console events into SDL events */ + +#include <stdio.h> +#include <sys/types.h> +#include <sys/time.h> +#include <sys/ioctl.h> +#include <unistd.h> +#include <fcntl.h> +#include <errno.h> +#include <limits.h> + +/* For parsing /proc */ +#include <dirent.h> +#include <ctype.h> + +#include <linux/vt.h> +#include <linux/kd.h> +#include <linux/keyboard.h> + +#include "SDL_timer.h" +#include "SDL_mutex.h" +#include "../SDL_sysvideo.h" +#include "../../events/SDL_sysevents.h" +#include "../../events/SDL_events_c.h" +#include "SDL_fbvideo.h" +#include "SDL_fbevents_c.h" +#include "SDL_fbkeys.h" + +#include "SDL_fbelo.h" + +#ifndef GPM_NODE_FIFO +#define GPM_NODE_FIFO "/dev/gpmdata" +#endif + +/*#define DEBUG_KEYBOARD*/ +/*#define DEBUG_MOUSE*/ + +/* The translation tables from a console scancode to a SDL keysym */ +#define NUM_VGAKEYMAPS (1<<KG_CAPSSHIFT) +static Uint16 vga_keymap[NUM_VGAKEYMAPS][NR_KEYS]; +static SDLKey keymap[128]; +static Uint16 keymap_temp[128]; /* only used at startup */ +static SDL_keysym *TranslateKey(int scancode, SDL_keysym *keysym); + +/* Ugh, we have to duplicate the kernel's keysym mapping code... + Oh, it's not so bad. :-) + + FIXME: Add keyboard LED handling code + */ +static void FB_vgainitkeymaps(int fd) +{ + struct kbentry entry; + int map, i; + + /* Don't do anything if we are passed a closed keyboard */ + if ( fd < 0 ) { + return; + } + + /* Load all the keysym mappings */ + for ( map=0; map<NUM_VGAKEYMAPS; ++map ) { + SDL_memset(vga_keymap[map], 0, NR_KEYS*sizeof(Uint16)); + for ( i=0; i<NR_KEYS; ++i ) { + entry.kb_table = map; + entry.kb_index = i; + if ( ioctl(fd, KDGKBENT, &entry) == 0 ) { + /* fill keytemp. This replaces SDL_fbkeys.h */ + if ( (map == 0) && (i<128) ) { + keymap_temp[i] = entry.kb_value; + } + /* The "Enter" key is a special case */ + if ( entry.kb_value == K_ENTER ) { + entry.kb_value = K(KT_ASCII,13); + } + /* Handle numpad specially as well */ + if ( KTYP(entry.kb_value) == KT_PAD ) { + switch ( entry.kb_value ) { + case K_P0: + case K_P1: + case K_P2: + case K_P3: + case K_P4: + case K_P5: + case K_P6: + case K_P7: + case K_P8: + case K_P9: + vga_keymap[map][i]=entry.kb_value; + vga_keymap[map][i]+= '0'; + break; + case K_PPLUS: + vga_keymap[map][i]=K(KT_ASCII,'+'); + break; + case K_PMINUS: + vga_keymap[map][i]=K(KT_ASCII,'-'); + break; + case K_PSTAR: + vga_keymap[map][i]=K(KT_ASCII,'*'); + break; + case K_PSLASH: + vga_keymap[map][i]=K(KT_ASCII,'/'); + break; + case K_PENTER: + vga_keymap[map][i]=K(KT_ASCII,'\r'); + break; + case K_PCOMMA: + vga_keymap[map][i]=K(KT_ASCII,','); + break; + case K_PDOT: + vga_keymap[map][i]=K(KT_ASCII,'.'); + break; + default: + break; + } + } + /* Do the normal key translation */ + if ( (KTYP(entry.kb_value) == KT_LATIN) || + (KTYP(entry.kb_value) == KT_ASCII) || + (KTYP(entry.kb_value) == KT_LETTER) ) { + vga_keymap[map][i] = entry.kb_value; + } + } + } + } +} + +int FB_InGraphicsMode(_THIS) +{ + return((keyboard_fd >= 0) && (saved_kbd_mode >= 0)); +} + +int FB_EnterGraphicsMode(_THIS) +{ + struct termios keyboard_termios; + + /* Set medium-raw keyboard mode */ + if ( (keyboard_fd >= 0) && !FB_InGraphicsMode(this) ) { + + /* Switch to the correct virtual terminal */ + if ( current_vt > 0 ) { + struct vt_stat vtstate; + + if ( ioctl(keyboard_fd, VT_GETSTATE, &vtstate) == 0 ) { + saved_vt = vtstate.v_active; + } + if ( ioctl(keyboard_fd, VT_ACTIVATE, current_vt) == 0 ) { + ioctl(keyboard_fd, VT_WAITACTIVE, current_vt); + } + } + + /* Set the terminal input mode */ + if ( tcgetattr(keyboard_fd, &saved_kbd_termios) < 0 ) { + SDL_SetError("Unable to get terminal attributes"); + if ( keyboard_fd > 0 ) { + close(keyboard_fd); + } + keyboard_fd = -1; + return(-1); + } + if ( ioctl(keyboard_fd, KDGKBMODE, &saved_kbd_mode) < 0 ) { + SDL_SetError("Unable to get current keyboard mode"); + if ( keyboard_fd > 0 ) { + close(keyboard_fd); + } + keyboard_fd = -1; + return(-1); + } + keyboard_termios = saved_kbd_termios; + keyboard_termios.c_lflag &= ~(ICANON | ECHO | ISIG); + keyboard_termios.c_iflag &= ~(ISTRIP | IGNCR | ICRNL | INLCR | IXOFF | IXON); + keyboard_termios.c_cc[VMIN] = 0; + keyboard_termios.c_cc[VTIME] = 0; + if (tcsetattr(keyboard_fd, TCSAFLUSH, &keyboard_termios) < 0) { + FB_CloseKeyboard(this); + SDL_SetError("Unable to set terminal attributes"); + return(-1); + } + /* This will fail if we aren't root or this isn't our tty */ + if ( ioctl(keyboard_fd, KDSKBMODE, K_MEDIUMRAW) < 0 ) { + FB_CloseKeyboard(this); + SDL_SetError("Unable to set keyboard in raw mode"); + return(-1); + } + if ( ioctl(keyboard_fd, KDSETMODE, KD_GRAPHICS) < 0 ) { + FB_CloseKeyboard(this); + SDL_SetError("Unable to set keyboard in graphics mode"); + return(-1); + } + /* Prevent switching the virtual terminal */ + ioctl(keyboard_fd, VT_LOCKSWITCH, 1); + } + return(keyboard_fd); +} + +void FB_LeaveGraphicsMode(_THIS) +{ + if ( FB_InGraphicsMode(this) ) { + ioctl(keyboard_fd, KDSETMODE, KD_TEXT); + ioctl(keyboard_fd, KDSKBMODE, saved_kbd_mode); + tcsetattr(keyboard_fd, TCSAFLUSH, &saved_kbd_termios); + saved_kbd_mode = -1; + + /* Head back over to the original virtual terminal */ + ioctl(keyboard_fd, VT_UNLOCKSWITCH, 1); + if ( saved_vt > 0 ) { + ioctl(keyboard_fd, VT_ACTIVATE, saved_vt); + } + } +} + +void FB_CloseKeyboard(_THIS) +{ + if ( keyboard_fd >= 0 ) { + FB_LeaveGraphicsMode(this); + if ( keyboard_fd > 0 ) { + close(keyboard_fd); + } + } + keyboard_fd = -1; +} + +int FB_OpenKeyboard(_THIS) +{ + /* Open only if not already opened */ + if ( keyboard_fd < 0 ) { + static const char * const tty0[] = { "/dev/tty0", "/dev/vc/0", NULL }; + static const char * const vcs[] = { "/dev/vc/%d", "/dev/tty%d", NULL }; + int i, tty0_fd; + + /* Try to query for a free virtual terminal */ + tty0_fd = -1; + for ( i=0; tty0[i] && (tty0_fd < 0); ++i ) { + tty0_fd = open(tty0[i], O_WRONLY, 0); + } + if ( tty0_fd < 0 ) { + tty0_fd = dup(0); /* Maybe stdin is a VT? */ + } + ioctl(tty0_fd, VT_OPENQRY, ¤t_vt); + close(tty0_fd); + if ( (geteuid() == 0) && (current_vt > 0) ) { + for ( i=0; vcs[i] && (keyboard_fd < 0); ++i ) { + char vtpath[12]; + + SDL_snprintf(vtpath, SDL_arraysize(vtpath), vcs[i], current_vt); + keyboard_fd = open(vtpath, O_RDWR, 0); +#ifdef DEBUG_KEYBOARD + fprintf(stderr, "vtpath = %s, fd = %d\n", + vtpath, keyboard_fd); +#endif /* DEBUG_KEYBOARD */ + + /* This needs to be our controlling tty + so that the kernel ioctl() calls work + */ + if ( keyboard_fd >= 0 ) { + tty0_fd = open("/dev/tty", O_RDWR, 0); + if ( tty0_fd >= 0 ) { + ioctl(tty0_fd, TIOCNOTTY, 0); + close(tty0_fd); + } + } + } + } + if ( keyboard_fd < 0 ) { + /* Last resort, maybe our tty is a usable VT */ + struct vt_stat vtstate; + + keyboard_fd = open("/dev/tty", O_RDWR); + + if ( ioctl(keyboard_fd, VT_GETSTATE, &vtstate) == 0 ) { + current_vt = vtstate.v_active; + } else { + current_vt = 0; + } + } +#ifdef DEBUG_KEYBOARD + fprintf(stderr, "Current VT: %d\n", current_vt); +#endif + saved_kbd_mode = -1; + + /* Make sure that our input is a console terminal */ + { int dummy; + if ( ioctl(keyboard_fd, KDGKBMODE, &dummy) < 0 ) { + close(keyboard_fd); + keyboard_fd = -1; + SDL_SetError("Unable to open a console terminal"); + } + } + + /* Set up keymap */ + FB_vgainitkeymaps(keyboard_fd); + } + return(keyboard_fd); +} + +static enum { + MOUSE_NONE = -1, + MOUSE_MSC, /* Note: GPM uses the MSC protocol */ + MOUSE_PS2, + MOUSE_IMPS2, + MOUSE_MS, + MOUSE_BM, + MOUSE_ELO, + MOUSE_TSLIB, + NUM_MOUSE_DRVS +} mouse_drv = MOUSE_NONE; + +void FB_CloseMouse(_THIS) +{ +#if SDL_INPUT_TSLIB + if (ts_dev != NULL) { + ts_close(ts_dev); + ts_dev = NULL; + mouse_fd = -1; + } +#endif /* SDL_INPUT_TSLIB */ + if ( mouse_fd > 0 ) { + close(mouse_fd); + } + mouse_fd = -1; +} + +/* Returns processes listed in /proc with the desired name */ +static int find_pid(DIR *proc, const char *wanted_name) +{ + struct dirent *entry; + int pid; + + /* First scan proc for the gpm process */ + pid = 0; + while ( (pid == 0) && ((entry=readdir(proc)) != NULL) ) { + if ( isdigit(entry->d_name[0]) ) { + FILE *status; + char path[PATH_MAX]; + char name[PATH_MAX]; + + SDL_snprintf(path, SDL_arraysize(path), "/proc/%s/status", entry->d_name); + status=fopen(path, "r"); + if ( status ) { + int matches = 0; + name[0] = '\0'; + matches = fscanf(status, "Name: %s", name); + if ( (matches == 1) && (SDL_strcmp(name, wanted_name) == 0) ) { + pid = SDL_atoi(entry->d_name); + } + fclose(status); + } + } + } + return pid; +} + +/* Returns true if /dev/gpmdata is being written to by gpm */ +static int gpm_available(char *proto, size_t protolen) +{ + int available; + DIR *proc; + int pid; + int cmdline, len, arglen; + char path[PATH_MAX]; + char args[PATH_MAX], *arg; + + /* Don't bother looking if the fifo isn't there */ +#ifdef DEBUG_MOUSE + fprintf(stderr,"testing gpm\n"); +#endif + if ( access(GPM_NODE_FIFO, F_OK) < 0 ) { + return(0); + } + + available = 0; + proc = opendir("/proc"); + if ( proc ) { + char raw_proto[10] = { '\0' }; + char repeat_proto[10] = { '\0' }; + while ( !available && (pid=find_pid(proc, "gpm")) > 0 ) { + SDL_snprintf(path, SDL_arraysize(path), "/proc/%d/cmdline", pid); + cmdline = open(path, O_RDONLY, 0); + if ( cmdline >= 0 ) { + len = read(cmdline, args, sizeof(args)); + arg = args; + while ( len > 0 ) { + arglen = SDL_strlen(arg)+1; +#ifdef DEBUG_MOUSE + fprintf(stderr,"gpm arg %s len %d\n",arg,arglen); +#endif + if ( SDL_strcmp(arg, "-t") == 0) { + /* protocol string, keep it for later */ + char *t, *s; + t = arg + arglen; + s = SDL_strchr(t, ' '); + if (s) *s = 0; + SDL_strlcpy(raw_proto, t, SDL_arraysize(raw_proto)); + if (s) *s = ' '; + } + if ( SDL_strncmp(arg, "-R", 2) == 0 ) { + char *t, *s; + available = 1; + t = arg + 2; + s = SDL_strchr(t, ' '); + if (s) *s = 0; + SDL_strlcpy(repeat_proto, t, SDL_arraysize(repeat_proto)); + if (s) *s = ' '; + } + len -= arglen; + arg += arglen; + } + close(cmdline); + } + } + closedir(proc); + + if ( available ) { + if ( SDL_strcmp(repeat_proto, "raw") == 0 ) { + SDL_strlcpy(proto, raw_proto, protolen); + } else if ( *repeat_proto ) { + SDL_strlcpy(proto, repeat_proto, protolen); + } else { + SDL_strlcpy(proto, "msc", protolen); + } + } + } + return available; +} + + +/* rcg06112001 Set up IMPS/2 mode, if possible. This gives + * us access to the mousewheel, etc. Returns zero if + * writes to device failed, but you still need to query the + * device to see which mode it's actually in. + */ +static int set_imps2_mode(int fd) +{ + /* If you wanted to control the mouse mode (and we do :) ) ... + Set IMPS/2 protocol: + {0xf3,200,0xf3,100,0xf3,80} + Reset mouse device: + {0xFF} + */ + Uint8 set_imps2[] = {0xf3, 200, 0xf3, 100, 0xf3, 80}; + /*Uint8 reset = 0xff;*/ + fd_set fdset; + struct timeval tv; + int retval = 0; + + if ( write(fd, &set_imps2, sizeof(set_imps2)) == sizeof(set_imps2) ) { + /* Don't reset it, that'll clear IMPS/2 mode on some mice + if (write(fd, &reset, sizeof (reset)) == sizeof (reset) ) { + retval = 1; + } + */ + } + + /* Get rid of any chatter from the above */ + FD_ZERO(&fdset); + FD_SET(fd, &fdset); + tv.tv_sec = 0; + tv.tv_usec = 0; + while ( select(fd+1, &fdset, 0, 0, &tv) > 0 ) { + char temp[32]; + if (read(fd, temp, sizeof(temp)) <= 0) { + break; + } + } + + return retval; +} + + +/* Returns true if the mouse uses the IMPS/2 protocol */ +static int detect_imps2(int fd) +{ + int imps2; + + imps2 = 0; + + if ( SDL_getenv("SDL_MOUSEDEV_IMPS2") ) { + imps2 = 1; + } + if ( ! imps2 ) { + Uint8 query_ps2 = 0xF2; + fd_set fdset; + struct timeval tv; + + /* Get rid of any mouse motion noise */ + FD_ZERO(&fdset); + FD_SET(fd, &fdset); + tv.tv_sec = 0; + tv.tv_usec = 0; + while ( select(fd+1, &fdset, 0, 0, &tv) > 0 ) { + char temp[32]; + if (read(fd, temp, sizeof(temp)) <= 0) { + break; + } + } + + /* Query for the type of mouse protocol */ + if ( write(fd, &query_ps2, sizeof (query_ps2)) == sizeof (query_ps2)) { + Uint8 ch = 0; + + /* Get the mouse protocol response */ + do { + FD_ZERO(&fdset); + FD_SET(fd, &fdset); + tv.tv_sec = 1; + tv.tv_usec = 0; + if ( select(fd+1, &fdset, 0, 0, &tv) < 1 ) { + break; + } + } while ( (read(fd, &ch, sizeof (ch)) == sizeof (ch)) && + ((ch == 0xFA) || (ch == 0xAA)) ); + + /* Experimental values (Logitech wheelmouse) */ +#ifdef DEBUG_MOUSE +fprintf(stderr, "Last mouse mode: 0x%x\n", ch); +#endif + if ( (ch == 3) || (ch == 4) ) { + imps2 = 1; + } + } + } + return imps2; +} + +int FB_OpenMouse(_THIS) +{ + int i; + const char *mousedev; + const char *mousedrv; + + mousedrv = SDL_getenv("SDL_MOUSEDRV"); + mousedev = SDL_getenv("SDL_MOUSEDEV"); + mouse_fd = -1; + +#if SDL_INPUT_TSLIB + if ( mousedrv && (SDL_strcmp(mousedrv, "TSLIB") == 0) ) { + if (mousedev == NULL) mousedev = SDL_getenv("TSLIB_TSDEVICE"); + if (mousedev != NULL) { + ts_dev = ts_open(mousedev, 1); + if ((ts_dev != NULL) && (ts_config(ts_dev) >= 0)) { +#ifdef DEBUG_MOUSE + fprintf(stderr, "Using tslib touchscreen\n"); +#endif + mouse_drv = MOUSE_TSLIB; + mouse_fd = ts_fd(ts_dev); + return mouse_fd; + } + } + mouse_drv = MOUSE_NONE; + return mouse_fd; + } +#endif /* SDL_INPUT_TSLIB */ + + /* ELO TOUCHSCREEN SUPPORT */ + + if ( mousedrv && (SDL_strcmp(mousedrv, "ELO") == 0) ) { + mouse_fd = open(mousedev, O_RDWR); + if ( mouse_fd >= 0 ) { + if(eloInitController(mouse_fd)) { +#ifdef DEBUG_MOUSE +fprintf(stderr, "Using ELO touchscreen\n"); +#endif + mouse_drv = MOUSE_ELO; + } + + } + else if ( mouse_fd < 0 ) { + mouse_drv = MOUSE_NONE; + } + + return(mouse_fd); + } + + /* STD MICE */ + + if ( mousedev == NULL ) { + /* FIXME someday... allow multiple mice in this driver */ + static const char *ps2mice[] = { + "/dev/input/mice", "/dev/usbmouse", "/dev/psaux", NULL + }; + /* First try to use GPM in repeater mode */ + if ( mouse_fd < 0 ) { + char proto[10]; + if ( gpm_available(proto, SDL_arraysize(proto)) ) { + mouse_fd = open(GPM_NODE_FIFO, O_RDONLY, 0); + if ( mouse_fd >= 0 ) { + if ( SDL_strcmp(proto, "msc") == 0 ) { + mouse_drv = MOUSE_MSC; + } else if ( SDL_strcmp(proto, "ps2") == 0 ) { + mouse_drv = MOUSE_PS2; + } else if ( SDL_strcmp(proto, "imps2") == 0 ) { + mouse_drv = MOUSE_IMPS2; + } else if ( SDL_strcmp(proto, "ms") == 0 || + SDL_strcmp(proto, "bare") == 0 ) { + mouse_drv = MOUSE_MS; + } else if ( SDL_strcmp(proto, "bm") == 0 ) { + mouse_drv = MOUSE_BM; + } else { + /* Unknown protocol... */ +#ifdef DEBUG_MOUSE + fprintf(stderr, "GPM mouse using unknown protocol = %s\n", proto); +#endif + close(mouse_fd); + mouse_fd = -1; + } + } +#ifdef DEBUG_MOUSE + if ( mouse_fd >= 0 ) { + fprintf(stderr, "Using GPM mouse, protocol = %s\n", proto); + } +#endif /* DEBUG_MOUSE */ + } + } + /* Now try to use a modern PS/2 mouse */ + for ( i=0; (mouse_fd < 0) && ps2mice[i]; ++i ) { + mouse_fd = open(ps2mice[i], O_RDWR, 0); + if (mouse_fd < 0) { + mouse_fd = open(ps2mice[i], O_RDONLY, 0); + } + if (mouse_fd >= 0) { + /* rcg06112001 Attempt to set IMPS/2 mode */ + set_imps2_mode(mouse_fd); + if (detect_imps2(mouse_fd)) { +#ifdef DEBUG_MOUSE +fprintf(stderr, "Using IMPS2 mouse\n"); +#endif + mouse_drv = MOUSE_IMPS2; + } else { +#ifdef DEBUG_MOUSE +fprintf(stderr, "Using PS2 mouse\n"); +#endif + mouse_drv = MOUSE_PS2; + } + } + } + /* Next try to use a PPC ADB port mouse */ + if ( mouse_fd < 0 ) { + mouse_fd = open("/dev/adbmouse", O_RDONLY, 0); + if ( mouse_fd >= 0 ) { +#ifdef DEBUG_MOUSE +fprintf(stderr, "Using ADB mouse\n"); +#endif + mouse_drv = MOUSE_BM; + } + } + } + /* Default to a serial Microsoft mouse */ + if ( mouse_fd < 0 ) { + if ( mousedev == NULL ) { + mousedev = "/dev/mouse"; + } + mouse_fd = open(mousedev, O_RDONLY, 0); + if ( mouse_fd >= 0 ) { + struct termios mouse_termios; + + /* Set the sampling speed to 1200 baud */ + tcgetattr(mouse_fd, &mouse_termios); + mouse_termios.c_iflag = IGNBRK | IGNPAR; + mouse_termios.c_oflag = 0; + mouse_termios.c_lflag = 0; + mouse_termios.c_line = 0; + mouse_termios.c_cc[VTIME] = 0; + mouse_termios.c_cc[VMIN] = 1; + mouse_termios.c_cflag = CREAD | CLOCAL | HUPCL; + mouse_termios.c_cflag |= CS8; + mouse_termios.c_cflag |= B1200; + tcsetattr(mouse_fd, TCSAFLUSH, &mouse_termios); + if ( mousedrv && (SDL_strcmp(mousedrv, "PS2") == 0) ) { +#ifdef DEBUG_MOUSE +fprintf(stderr, "Using (user specified) PS2 mouse on %s\n", mousedev); +#endif + mouse_drv = MOUSE_PS2; + } else { +#ifdef DEBUG_MOUSE +fprintf(stderr, "Using (default) MS mouse on %s\n", mousedev); +#endif + mouse_drv = MOUSE_MS; + } + } + } + if ( mouse_fd < 0 ) { + mouse_drv = MOUSE_NONE; + } + return(mouse_fd); +} + +static int posted = 0; + +void FB_vgamousecallback(int button, int relative, int dx, int dy) +{ + int button_1, button_3; + int button_state; + int state_changed; + int i; + Uint8 state; + + if ( dx || dy ) { + posted += SDL_PrivateMouseMotion(0, relative, dx, dy); + } + + /* Swap button 1 and 3 */ + button_1 = (button & 0x04) >> 2; + button_3 = (button & 0x01) << 2; + button &= ~0x05; + button |= (button_1|button_3); + + /* See what changed */ + button_state = SDL_GetMouseState(NULL, NULL); + state_changed = button_state ^ button; + for ( i=0; i<8; ++i ) { + if ( state_changed & (1<<i) ) { + if ( button & (1<<i) ) { + state = SDL_PRESSED; + } else { + state = SDL_RELEASED; + } + posted += SDL_PrivateMouseButton(state, i+1, 0, 0); + } + } +} + +/* Handle input from tslib */ +#if SDL_INPUT_TSLIB +static void handle_tslib(_THIS) +{ + struct ts_sample sample; + int button; + + while (ts_read(ts_dev, &sample, 1) > 0) { + button = (sample.pressure > 0) ? 1 : 0; + button <<= 2; /* must report it as button 3 */ + FB_vgamousecallback(button, 0, sample.x, sample.y); + } + return; +} +#endif /* SDL_INPUT_TSLIB */ + +/* For now, use MSC, PS/2, and MS protocols + Driver adapted from the SVGAlib mouse driver code (taken from gpm, etc.) + */ +static void handle_mouse(_THIS) +{ + static int start = 0; + static unsigned char mousebuf[BUFSIZ]; + static int relative = 1; + + int i, nread; + int button = 0; + int dx = 0, dy = 0; + int packetsize = 0; + int realx, realy; + + /* Figure out the mouse packet size */ + switch (mouse_drv) { + case MOUSE_NONE: + break; /* carry on to read from device and discard it. */ + case MOUSE_MSC: + packetsize = 5; + break; + case MOUSE_IMPS2: + packetsize = 4; + break; + case MOUSE_PS2: + case MOUSE_MS: + case MOUSE_BM: + packetsize = 3; + break; + case MOUSE_ELO: + /* try to read the next packet */ + if(eloReadPosition(this, mouse_fd, &dx, &dy, &button, &realx, &realy)) { + button = (button & 0x01) << 2; + FB_vgamousecallback(button, 0, dx, dy); + } + return; /* nothing left to do */ + case MOUSE_TSLIB: +#if SDL_INPUT_TSLIB + handle_tslib(this); +#endif + return; /* nothing left to do */ + default: + /* Uh oh.. */ + packetsize = 0; + break; + } + + /* Special handling for the quite sensitive ELO controller */ + if (mouse_drv == MOUSE_ELO) { + + } + + /* Read as many packets as possible */ + nread = read(mouse_fd, &mousebuf[start], BUFSIZ-start); + if ( nread < 0 ) { + return; + } + + if (mouse_drv == MOUSE_NONE) { + return; /* we're done; just draining the input queue. */ + } + + nread += start; +#ifdef DEBUG_MOUSE + fprintf(stderr, "Read %d bytes from mouse, start = %d\n", nread, start); +#endif + + for ( i=0; i<(nread-(packetsize-1)); i += packetsize ) { + switch (mouse_drv) { + case MOUSE_NONE: /* shouldn't actually hit this. */ + break; /* just throw everything away. */ + case MOUSE_MSC: + /* MSC protocol has 0x80 in high byte */ + if ( (mousebuf[i] & 0xF8) != 0x80 ) { + /* Go to next byte */ + i -= (packetsize-1); + continue; + } + /* Get current mouse state */ + button = (~mousebuf[i]) & 0x07; + dx = (signed char)(mousebuf[i+1]) + + (signed char)(mousebuf[i+3]); + dy = -((signed char)(mousebuf[i+2]) + + (signed char)(mousebuf[i+4])); + break; + case MOUSE_PS2: + /* PS/2 protocol has nothing in high byte */ + if ( (mousebuf[i] & 0xC0) != 0 ) { + /* Go to next byte */ + i -= (packetsize-1); + continue; + } + /* Get current mouse state */ + button = (mousebuf[i] & 0x04) >> 1 | /*Middle*/ + (mousebuf[i] & 0x02) >> 1 | /*Right*/ + (mousebuf[i] & 0x01) << 2; /*Left*/ + dx = (mousebuf[i] & 0x10) ? + mousebuf[i+1] - 256 : mousebuf[i+1]; + dy = (mousebuf[i] & 0x20) ? + -(mousebuf[i+2] - 256) : -mousebuf[i+2]; + break; + case MOUSE_IMPS2: + /* Get current mouse state */ + button = (mousebuf[i] & 0x04) >> 1 | /*Middle*/ + (mousebuf[i] & 0x02) >> 1 | /*Right*/ + (mousebuf[i] & 0x01) << 2 | /*Left*/ + (mousebuf[i] & 0x40) >> 3 | /* 4 */ + (mousebuf[i] & 0x80) >> 3; /* 5 */ + dx = (mousebuf[i] & 0x10) ? + mousebuf[i+1] - 256 : mousebuf[i+1]; + dy = (mousebuf[i] & 0x20) ? + -(mousebuf[i+2] - 256) : -mousebuf[i+2]; + switch (mousebuf[i+3]&0x0F) { + case 0x0E: /* DX = +1 */ + case 0x02: /* DX = -1 */ + break; + case 0x0F: /* DY = +1 (map button 4) */ + FB_vgamousecallback(button | (1<<3), + 1, 0, 0); + break; + case 0x01: /* DY = -1 (map button 5) */ + FB_vgamousecallback(button | (1<<4), + 1, 0, 0); + break; + } + break; + case MOUSE_MS: + /* Microsoft protocol has 0x40 in high byte */ + if ( (mousebuf[i] & 0x40) != 0x40 ) { + /* Go to next byte */ + i -= (packetsize-1); + continue; + } + /* Get current mouse state */ + button = ((mousebuf[i] & 0x20) >> 3) | + ((mousebuf[i] & 0x10) >> 4); + dx = (signed char)(((mousebuf[i] & 0x03) << 6) | + (mousebuf[i + 1] & 0x3F)); + dy = (signed char)(((mousebuf[i] & 0x0C) << 4) | + (mousebuf[i + 2] & 0x3F)); + break; + case MOUSE_BM: + /* BusMouse protocol has 0xF8 in high byte */ + if ( (mousebuf[i] & 0xF8) != 0x80 ) { + /* Go to next byte */ + i -= (packetsize-1); + continue; + } + /* Get current mouse state */ + button = (~mousebuf[i]) & 0x07; + dx = (signed char)mousebuf[i+1]; + dy = -(signed char)mousebuf[i+2]; + break; + default: + /* Uh oh.. */ + dx = 0; + dy = 0; + break; + } + FB_vgamousecallback(button, relative, dx, dy); + } + if ( i < nread ) { + SDL_memcpy(mousebuf, &mousebuf[i], (nread-i)); + start = (nread-i); + } else { + start = 0; + } + return; +} + +/* Handle switching to another VC, returns when our VC is back */ +static void switch_vt_prep(_THIS) +{ + SDL_Surface *screen = SDL_VideoSurface; + + SDL_PrivateAppActive(0, (SDL_APPACTIVE|SDL_APPINPUTFOCUS|SDL_APPMOUSEFOCUS)); + + /* Save the contents of the screen, and go to text mode */ + wait_idle(this); + screen_arealen = ((screen->h + (2*this->offset_y)) * screen->pitch); + screen_contents = (Uint8 *)SDL_malloc(screen_arealen); + if ( screen_contents ) { + SDL_memcpy(screen_contents, screen->pixels, screen_arealen); + } + FB_SavePaletteTo(this, 256, screen_palette); + ioctl(console_fd, FBIOGET_VSCREENINFO, &screen_vinfo); + ioctl(keyboard_fd, KDSETMODE, KD_TEXT); + ioctl(keyboard_fd, VT_UNLOCKSWITCH, 1); +} +static void switch_vt_done(_THIS) +{ + SDL_Surface *screen = SDL_VideoSurface; + + /* Restore graphics mode and the contents of the screen */ + ioctl(keyboard_fd, VT_LOCKSWITCH, 1); + ioctl(keyboard_fd, KDSETMODE, KD_GRAPHICS); + ioctl(console_fd, FBIOPUT_VSCREENINFO, &screen_vinfo); + FB_RestorePaletteFrom(this, 256, screen_palette); + if ( screen_contents ) { + SDL_memcpy(screen->pixels, screen_contents, screen_arealen); + SDL_free(screen_contents); + screen_contents = NULL; + } + + /* Get updates to the shadow surface while switched away */ + if ( SDL_ShadowSurface ) { + SDL_UpdateRect(SDL_ShadowSurface, 0, 0, 0, 0); + } + + SDL_PrivateAppActive(1, (SDL_APPACTIVE|SDL_APPINPUTFOCUS|SDL_APPMOUSEFOCUS)); +} +static void switch_vt(_THIS, unsigned short which) +{ + struct vt_stat vtstate; + + /* Figure out whether or not we're switching to a new console */ + if ( (ioctl(keyboard_fd, VT_GETSTATE, &vtstate) < 0) || + (which == vtstate.v_active) ) { + return; + } + + /* New console, switch to it */ + SDL_mutexP(hw_lock); + switch_vt_prep(this); + if ( ioctl(keyboard_fd, VT_ACTIVATE, which) == 0 ) { + ioctl(keyboard_fd, VT_WAITACTIVE, which); + switched_away = 1; + } else { + switch_vt_done(this); + } + SDL_mutexV(hw_lock); +} + +static void handle_keyboard(_THIS) +{ + unsigned char keybuf[BUFSIZ]; + int i, nread; + int pressed; + int scancode; + SDL_keysym keysym; + + nread = read(keyboard_fd, keybuf, BUFSIZ); + for ( i=0; i<nread; ++i ) { + scancode = keybuf[i] & 0x7F; + if ( keybuf[i] & 0x80 ) { + pressed = SDL_RELEASED; + } else { + pressed = SDL_PRESSED; + } + TranslateKey(scancode, &keysym); + /* Handle Ctrl-Alt-FN for vt switch */ + switch (keysym.sym) { + case SDLK_F1: + case SDLK_F2: + case SDLK_F3: + case SDLK_F4: + case SDLK_F5: + case SDLK_F6: + case SDLK_F7: + case SDLK_F8: + case SDLK_F9: + case SDLK_F10: + case SDLK_F11: + case SDLK_F12: + if ( (SDL_GetModState() & KMOD_CTRL) && + (SDL_GetModState() & KMOD_ALT) ) { + if ( pressed ) { + switch_vt(this, (keysym.sym-SDLK_F1)+1); + } + break; + } + /* Fall through to normal processing */ + default: + posted += SDL_PrivateKeyboard(pressed, &keysym); + break; + } + } +} + +void FB_PumpEvents(_THIS) +{ + fd_set fdset; + int max_fd; + static struct timeval zero; + + do { + if ( switched_away ) { + struct vt_stat vtstate; + + SDL_mutexP(hw_lock); + if ( (ioctl(keyboard_fd, VT_GETSTATE, &vtstate) == 0) && + vtstate.v_active == current_vt ) { + switched_away = 0; + switch_vt_done(this); + } + SDL_mutexV(hw_lock); + } + + posted = 0; + + FD_ZERO(&fdset); + max_fd = 0; + if ( keyboard_fd >= 0 ) { + FD_SET(keyboard_fd, &fdset); + if ( max_fd < keyboard_fd ) { + max_fd = keyboard_fd; + } + } + if ( mouse_fd >= 0 ) { + FD_SET(mouse_fd, &fdset); + if ( max_fd < mouse_fd ) { + max_fd = mouse_fd; + } + } + if ( select(max_fd+1, &fdset, NULL, NULL, &zero) > 0 ) { + if ( keyboard_fd >= 0 ) { + if ( FD_ISSET(keyboard_fd, &fdset) ) { + handle_keyboard(this); + } + } + if ( mouse_fd >= 0 ) { + if ( FD_ISSET(mouse_fd, &fdset) ) { + handle_mouse(this); + } + } + } + } while ( posted ); +} + +void FB_InitOSKeymap(_THIS) +{ + int i; + + /* Initialize the Linux key translation table */ + + /* First get the ascii keys and others not well handled */ + for (i=0; i<SDL_arraysize(keymap); ++i) { + switch(i) { + /* These aren't handled by the x86 kernel keymapping (?) */ + case SCANCODE_PRINTSCREEN: + keymap[i] = SDLK_PRINT; + break; + case SCANCODE_BREAK: + keymap[i] = SDLK_BREAK; + break; + case SCANCODE_BREAK_ALTERNATIVE: + keymap[i] = SDLK_PAUSE; + break; + case SCANCODE_LEFTSHIFT: + keymap[i] = SDLK_LSHIFT; + break; + case SCANCODE_RIGHTSHIFT: + keymap[i] = SDLK_RSHIFT; + break; + case SCANCODE_LEFTCONTROL: + keymap[i] = SDLK_LCTRL; + break; + case SCANCODE_RIGHTCONTROL: + keymap[i] = SDLK_RCTRL; + break; + case SCANCODE_RIGHTWIN: + keymap[i] = SDLK_RSUPER; + break; + case SCANCODE_LEFTWIN: + keymap[i] = SDLK_LSUPER; + break; + case SCANCODE_LEFTALT: + keymap[i] = SDLK_LALT; + break; + case SCANCODE_RIGHTALT: + keymap[i] = SDLK_RALT; + break; + case 127: + keymap[i] = SDLK_MENU; + break; + /* this should take care of all standard ascii keys */ + default: + keymap[i] = KVAL(vga_keymap[0][i]); + break; + } + } + for (i=0; i<SDL_arraysize(keymap); ++i) { + switch(keymap_temp[i]) { + case K_F1: keymap[i] = SDLK_F1; break; + case K_F2: keymap[i] = SDLK_F2; break; + case K_F3: keymap[i] = SDLK_F3; break; + case K_F4: keymap[i] = SDLK_F4; break; + case K_F5: keymap[i] = SDLK_F5; break; + case K_F6: keymap[i] = SDLK_F6; break; + case K_F7: keymap[i] = SDLK_F7; break; + case K_F8: keymap[i] = SDLK_F8; break; + case K_F9: keymap[i] = SDLK_F9; break; + case K_F10: keymap[i] = SDLK_F10; break; + case K_F11: keymap[i] = SDLK_F11; break; + case K_F12: keymap[i] = SDLK_F12; break; + + case K_DOWN: keymap[i] = SDLK_DOWN; break; + case K_LEFT: keymap[i] = SDLK_LEFT; break; + case K_RIGHT: keymap[i] = SDLK_RIGHT; break; + case K_UP: keymap[i] = SDLK_UP; break; + + case K_P0: keymap[i] = SDLK_KP0; break; + case K_P1: keymap[i] = SDLK_KP1; break; + case K_P2: keymap[i] = SDLK_KP2; break; + case K_P3: keymap[i] = SDLK_KP3; break; + case K_P4: keymap[i] = SDLK_KP4; break; + case K_P5: keymap[i] = SDLK_KP5; break; + case K_P6: keymap[i] = SDLK_KP6; break; + case K_P7: keymap[i] = SDLK_KP7; break; + case K_P8: keymap[i] = SDLK_KP8; break; + case K_P9: keymap[i] = SDLK_KP9; break; + case K_PPLUS: keymap[i] = SDLK_KP_PLUS; break; + case K_PMINUS: keymap[i] = SDLK_KP_MINUS; break; + case K_PSTAR: keymap[i] = SDLK_KP_MULTIPLY; break; + case K_PSLASH: keymap[i] = SDLK_KP_DIVIDE; break; + case K_PENTER: keymap[i] = SDLK_KP_ENTER; break; + case K_PDOT: keymap[i] = SDLK_KP_PERIOD; break; + + case K_SHIFT: if ( keymap[i] != SDLK_RSHIFT ) + keymap[i] = SDLK_LSHIFT; + break; + case K_SHIFTL: keymap[i] = SDLK_LSHIFT; break; + case K_SHIFTR: keymap[i] = SDLK_RSHIFT; break; + case K_CTRL: if ( keymap[i] != SDLK_RCTRL ) + keymap[i] = SDLK_LCTRL; + break; + case K_CTRLL: keymap[i] = SDLK_LCTRL; break; + case K_CTRLR: keymap[i] = SDLK_RCTRL; break; + case K_ALT: keymap[i] = SDLK_LALT; break; + case K_ALTGR: keymap[i] = SDLK_RALT; break; + + case K_INSERT: keymap[i] = SDLK_INSERT; break; + case K_REMOVE: keymap[i] = SDLK_DELETE; break; + case K_PGUP: keymap[i] = SDLK_PAGEUP; break; + case K_PGDN: keymap[i] = SDLK_PAGEDOWN; break; + case K_FIND: keymap[i] = SDLK_HOME; break; + case K_SELECT: keymap[i] = SDLK_END; break; + + case K_NUM: keymap[i] = SDLK_NUMLOCK; break; + case K_CAPS: keymap[i] = SDLK_CAPSLOCK; break; + + case K_F13: keymap[i] = SDLK_PRINT; break; + case K_HOLD: keymap[i] = SDLK_SCROLLOCK; break; + case K_PAUSE: keymap[i] = SDLK_PAUSE; break; + + case 127: keymap[i] = SDLK_BACKSPACE; break; + + default: break; + } + } +} + +static SDL_keysym *TranslateKey(int scancode, SDL_keysym *keysym) +{ + /* Set the keysym information */ + keysym->scancode = scancode; + keysym->sym = keymap[scancode]; + keysym->mod = KMOD_NONE; + + /* If UNICODE is on, get the UNICODE value for the key */ + keysym->unicode = 0; + if ( SDL_TranslateUNICODE ) { + int map; + SDLMod modstate; + + modstate = SDL_GetModState(); + map = 0; + if ( modstate & KMOD_SHIFT ) { + map |= (1<<KG_SHIFT); + } + if ( modstate & KMOD_CTRL ) { + map |= (1<<KG_CTRL); + } + if ( modstate & KMOD_LALT ) { + map |= (1<<KG_ALT); + } + if ( modstate & KMOD_RALT ) { + map |= (1<<KG_ALTGR); + } + if ( KTYP(vga_keymap[map][scancode]) == KT_LETTER ) { + if ( modstate & KMOD_CAPS ) { + map ^= (1<<KG_SHIFT); + } + } + if ( KTYP(vga_keymap[map][scancode]) == KT_PAD ) { + if ( modstate & KMOD_NUM ) { + keysym->unicode=KVAL(vga_keymap[map][scancode]); + } + } else { + keysym->unicode = KVAL(vga_keymap[map][scancode]); + } + } + return(keysym); +} diff --git a/3rdparty/SDL/src/video/fbcon/SDL_fbevents_c.h b/3rdparty/SDL/src/video/fbcon/SDL_fbevents_c.h new file mode 100644 index 0000000..fe8b09c --- /dev/null +++ b/3rdparty/SDL/src/video/fbcon/SDL_fbevents_c.h @@ -0,0 +1,38 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#include "SDL_fbvideo.h" + +/* Variables and functions exported by SDL_sysevents.c to other parts + of the native video subsystem (SDL_sysvideo.c) +*/ +extern int FB_OpenKeyboard(_THIS); +extern void FB_CloseKeyboard(_THIS); +extern int FB_OpenMouse(_THIS); +extern void FB_CloseMouse(_THIS); +extern int FB_EnterGraphicsMode(_THIS); +extern int FB_InGraphicsMode(_THIS); +extern void FB_LeaveGraphicsMode(_THIS); + +extern void FB_InitOSKeymap(_THIS); +extern void FB_PumpEvents(_THIS); diff --git a/3rdparty/SDL/src/video/fbcon/SDL_fbkeys.h b/3rdparty/SDL/src/video/fbcon/SDL_fbkeys.h new file mode 100644 index 0000000..2b01b6b --- /dev/null +++ b/3rdparty/SDL/src/video/fbcon/SDL_fbkeys.h @@ -0,0 +1,139 @@ + +/* Scancodes for the Linux framebuffer console + - Taken with thanks from SVGAlib 1.4.0 +*/ + +#define SCANCODE_ESCAPE 1 + +#define SCANCODE_1 2 +#define SCANCODE_2 3 +#define SCANCODE_3 4 +#define SCANCODE_4 5 +#define SCANCODE_5 6 +#define SCANCODE_6 7 +#define SCANCODE_7 8 +#define SCANCODE_8 9 +#define SCANCODE_9 10 +#define SCANCODE_0 11 + +#define SCANCODE_MINUS 12 +#define SCANCODE_EQUAL 13 + +#define SCANCODE_BACKSPACE 14 +#define SCANCODE_TAB 15 + +#define SCANCODE_Q 16 +#define SCANCODE_W 17 +#define SCANCODE_E 18 +#define SCANCODE_R 19 +#define SCANCODE_T 20 +#define SCANCODE_Y 21 +#define SCANCODE_U 22 +#define SCANCODE_I 23 +#define SCANCODE_O 24 +#define SCANCODE_P 25 +#define SCANCODE_BRACKET_LEFT 26 +#define SCANCODE_BRACKET_RIGHT 27 + +#define SCANCODE_ENTER 28 + +#define SCANCODE_LEFTCONTROL 29 + +#define SCANCODE_A 30 +#define SCANCODE_S 31 +#define SCANCODE_D 32 +#define SCANCODE_F 33 +#define SCANCODE_G 34 +#define SCANCODE_H 35 +#define SCANCODE_J 36 +#define SCANCODE_K 37 +#define SCANCODE_L 38 +#define SCANCODE_SEMICOLON 39 +#define SCANCODE_APOSTROPHE 40 +#define SCANCODE_GRAVE 41 + +#define SCANCODE_LEFTSHIFT 42 +#define SCANCODE_BACKSLASH 43 + +#define SCANCODE_Z 44 +#define SCANCODE_X 45 +#define SCANCODE_C 46 +#define SCANCODE_V 47 +#define SCANCODE_B 48 +#define SCANCODE_N 49 +#define SCANCODE_M 50 +#define SCANCODE_COMMA 51 +#define SCANCODE_PERIOD 52 +#define SCANCODE_SLASH 53 + +#define SCANCODE_RIGHTSHIFT 54 +#define SCANCODE_KEYPADMULTIPLY 55 + +#define SCANCODE_LEFTALT 56 +#define SCANCODE_SPACE 57 +#define SCANCODE_CAPSLOCK 58 + +#define SCANCODE_F1 59 +#define SCANCODE_F2 60 +#define SCANCODE_F3 61 +#define SCANCODE_F4 62 +#define SCANCODE_F5 63 +#define SCANCODE_F6 64 +#define SCANCODE_F7 65 +#define SCANCODE_F8 66 +#define SCANCODE_F9 67 +#define SCANCODE_F10 68 + +#define SCANCODE_NUMLOCK 69 +#define SCANCODE_SCROLLLOCK 70 + +#define SCANCODE_KEYPAD7 71 +#define SCANCODE_CURSORUPLEFT 71 +#define SCANCODE_KEYPAD8 72 +#define SCANCODE_CURSORUP 72 +#define SCANCODE_KEYPAD9 73 +#define SCANCODE_CURSORUPRIGHT 73 +#define SCANCODE_KEYPADMINUS 74 +#define SCANCODE_KEYPAD4 75 +#define SCANCODE_CURSORLEFT 75 +#define SCANCODE_KEYPAD5 76 +#define SCANCODE_KEYPAD6 77 +#define SCANCODE_CURSORRIGHT 77 +#define SCANCODE_KEYPADPLUS 78 +#define SCANCODE_KEYPAD1 79 +#define SCANCODE_CURSORDOWNLEFT 79 +#define SCANCODE_KEYPAD2 80 +#define SCANCODE_CURSORDOWN 80 +#define SCANCODE_KEYPAD3 81 +#define SCANCODE_CURSORDOWNRIGHT 81 +#define SCANCODE_KEYPAD0 82 +#define SCANCODE_KEYPADPERIOD 83 + +#define SCANCODE_LESS 86 + +#define SCANCODE_F11 87 +#define SCANCODE_F12 88 + +#define SCANCODE_KEYPADENTER 96 +#define SCANCODE_RIGHTCONTROL 97 +#define SCANCODE_CONTROL 97 +#define SCANCODE_KEYPADDIVIDE 98 +#define SCANCODE_PRINTSCREEN 99 +#define SCANCODE_RIGHTALT 100 +#define SCANCODE_BREAK 101 /* Beware: is 119 */ +#define SCANCODE_BREAK_ALTERNATIVE 119 /* on some keyboards! */ + +#define SCANCODE_HOME 102 +#define SCANCODE_CURSORBLOCKUP 103 /* Cursor key block */ +#define SCANCODE_PAGEUP 104 +#define SCANCODE_CURSORBLOCKLEFT 105 /* Cursor key block */ +#define SCANCODE_CURSORBLOCKRIGHT 106 /* Cursor key block */ +#define SCANCODE_END 107 +#define SCANCODE_CURSORBLOCKDOWN 108 /* Cursor key block */ +#define SCANCODE_PAGEDOWN 109 +#define SCANCODE_INSERT 110 +#define SCANCODE_REMOVE 111 + +#define SCANCODE_RIGHTWIN 126 +#define SCANCODE_LEFTWIN 125 + diff --git a/3rdparty/SDL/src/video/fbcon/SDL_fbmatrox.c b/3rdparty/SDL/src/video/fbcon/SDL_fbmatrox.c new file mode 100644 index 0000000..04b90b0 --- /dev/null +++ b/3rdparty/SDL/src/video/fbcon/SDL_fbmatrox.c @@ -0,0 +1,280 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#include "SDL_video.h" +#include "../SDL_blit.h" +#include "SDL_fbmatrox.h" +#include "matrox_mmio.h" + + +/* Wait for vertical retrace - taken from the XFree86 Matrox driver */ +static void WaitVBL(_THIS) +{ + int count; + + /* find start of retrace */ + mga_waitidle(); + while ( (mga_in8(0x1FDA) & 0x08) ) + ; + while ( !(mga_in8(0x1FDA) & 0x08) ) + ; + /* wait until we're past the start */ + count = mga_in32(0x1E20) + 2; + while ( mga_in32(0x1E20) < count ) + ; +} +static void WaitIdle(_THIS) +{ + mga_waitidle(); +} + +/* Sets video mem colorkey and accelerated blit function */ +static int SetHWColorKey(_THIS, SDL_Surface *surface, Uint32 key) +{ + return(0); +} + +/* Sets per surface hardware alpha value */ +#if 0 +static int SetHWAlpha(_THIS, SDL_Surface *surface, Uint8 value) +{ + return(0); +} +#endif + +static int FillHWRect(_THIS, SDL_Surface *dst, SDL_Rect *rect, Uint32 color) +{ + int dstX, dstY; + Uint32 fxbndry; + Uint32 ydstlen; + Uint32 fillop; + + /* Don't blit to the display surface when switched away */ + if ( switched_away ) { + return -2; /* no hardware access */ + } + if ( dst == this->screen ) { + SDL_mutexP(hw_lock); + } + + switch (dst->format->BytesPerPixel) { + case 1: + color |= (color<<8); + case 2: + color |= (color<<16); + break; + } + + /* Set up the X/Y base coordinates */ + FB_dst_to_xy(this, dst, &dstX, &dstY); + + /* Adjust for the current rectangle */ + dstX += rect->x; + dstY += rect->y; + + /* Set up the X boundaries */ + fxbndry = (dstX | ((dstX+rect->w) << 16)); + + /* Set up the Y boundaries */ + ydstlen = (rect->h | (dstY << 16)); + + /* Set up for color fill operation */ + fillop = MGADWG_TRAP | MGADWG_SOLID | + MGADWG_ARZERO | MGADWG_SGNZERO | MGADWG_SHIFTZERO; + + /* Execute the operations! */ + mga_wait(5); + mga_out32(MGAREG_DWGCTL, fillop | MGADWG_REPLACE); + mga_out32(MGAREG_FCOL, color); + mga_out32(MGAREG_FXBNDRY, fxbndry); + mga_out32(MGAREG_YDSTLEN + MGAREG_EXEC, ydstlen); + + FB_AddBusySurface(dst); + + if ( dst == this->screen ) { + SDL_mutexV(hw_lock); + } + return(0); +} + +static int HWAccelBlit(SDL_Surface *src, SDL_Rect *srcrect, + SDL_Surface *dst, SDL_Rect *dstrect) +{ + SDL_VideoDevice *this = current_video; + int pitch, w, h; + int srcX, srcY; + int dstX, dstY; + Uint32 sign; + Uint32 start, stop; + int skip; + Uint32 blitop; + + /* FIXME: For now, only blit to display surface */ + if ( dst->pitch != SDL_VideoSurface->pitch ) { + return(src->map->sw_blit(src, srcrect, dst, dstrect)); + } + + /* Don't blit to the display surface when switched away */ + if ( switched_away ) { + return -2; /* no hardware access */ + } + if ( dst == this->screen ) { + SDL_mutexP(hw_lock); + } + + /* Calculate source and destination base coordinates (in pixels) */ + w = dstrect->w; + h = dstrect->h; + FB_dst_to_xy(this, src, &srcX, &srcY); + FB_dst_to_xy(this, dst, &dstX, &dstY); + + /* Adjust for the current blit rectangles */ + srcX += srcrect->x; + srcY += srcrect->y; + dstX += dstrect->x; + dstY += dstrect->y; + pitch = dst->pitch/dst->format->BytesPerPixel; + + /* Set up the blit direction (sign) flags */ + sign = 0; + if ( srcX < dstX ) { + sign |= 1; + } + if ( srcY < dstY ) { + sign |= 4; + srcY += (h - 1); + dstY += (h - 1); + } + + /* Set up the blit source row start, end, and skip (in pixels) */ + stop = start = (srcY * pitch) + srcX; + if ( srcX < dstX ) { + start += (w - 1); + } else { + stop += (w - 1); + } + if ( srcY < dstY ) { + skip = -pitch; + } else { + skip = pitch; + } + + /* Set up the blit operation */ + if ( (src->flags & SDL_SRCCOLORKEY) == SDL_SRCCOLORKEY ) { + Uint32 colorkey; + + blitop = MGADWG_BFCOL | MGADWG_BITBLT | + MGADWG_SHIFTZERO | MGADWG_RSTR | (0x0C << 16) | + MGADWG_TRANSC; + + colorkey = src->format->colorkey; + switch (dst->format->BytesPerPixel) { + case 1: + colorkey |= (colorkey<<8); + case 2: + colorkey |= (colorkey<<16); + break; + } + mga_wait(2); + mga_out32(MGAREG_FCOL, colorkey); + mga_out32(MGAREG_BCOL, 0xFFFFFFFF); + } else { + blitop = MGADWG_BFCOL | MGADWG_BITBLT | + MGADWG_SHIFTZERO | MGADWG_RSTR | (0x0C << 16); + } + mga_wait(7); + mga_out32(MGAREG_SGN, sign); + mga_out32(MGAREG_AR3, start); + mga_out32(MGAREG_AR0, stop); + mga_out32(MGAREG_AR5, skip); + mga_out32(MGAREG_FXBNDRY, (dstX | ((dstX + w-1) << 16))); + mga_out32(MGAREG_YDSTLEN, (dstY << 16) | h); + mga_out32(MGAREG_DWGCTL + MGAREG_EXEC, blitop); + + FB_AddBusySurface(src); + FB_AddBusySurface(dst); + + if ( dst == this->screen ) { + SDL_mutexV(hw_lock); + } + return(0); +} + +static int CheckHWBlit(_THIS, SDL_Surface *src, SDL_Surface *dst) +{ + int accelerated; + + /* Set initial acceleration on */ + src->flags |= SDL_HWACCEL; + + /* Set the surface attributes */ + if ( (src->flags & SDL_SRCALPHA) == SDL_SRCALPHA ) { + if ( ! this->info.blit_hw_A ) { + src->flags &= ~SDL_HWACCEL; + } + } + if ( (src->flags & SDL_SRCCOLORKEY) == SDL_SRCCOLORKEY ) { + if ( ! this->info.blit_hw_CC ) { + src->flags &= ~SDL_HWACCEL; + } + } + + /* Check to see if final surface blit is accelerated */ + accelerated = !!(src->flags & SDL_HWACCEL); + if ( accelerated ) { + src->map->hw_blit = HWAccelBlit; + } + return(accelerated); +} + +void FB_MatroxAccel(_THIS, __u32 card) +{ + /* We have hardware accelerated surface functions */ + this->CheckHWBlit = CheckHWBlit; + wait_vbl = WaitVBL; + wait_idle = WaitIdle; + + /* The Matrox has an accelerated color fill */ + this->info.blit_fill = 1; + this->FillHWRect = FillHWRect; + + /* The Matrox has accelerated normal and colorkey blits. */ + this->info.blit_hw = 1; + /* The Millenium I appears to do the colorkey test a word + at a time, and the transparency is intverted. (?) + */ + if ( card != FB_ACCEL_MATROX_MGA2064W ) { + this->info.blit_hw_CC = 1; + this->SetHWColorKey = SetHWColorKey; + } + +#if 0 /* Not yet implemented? */ + /* The Matrox G200/G400 has an accelerated alpha blit */ + if ( (card == FB_ACCEL_MATROX_MGAG200) + || (card == FB_ACCEL_MATROX_MGAG400) + ) { + this->info.blit_hw_A = 1; + this->SetHWAlpha = SetHWAlpha; + } +#endif +} diff --git a/3rdparty/SDL/src/video/fbcon/SDL_fbmatrox.h b/3rdparty/SDL/src/video/fbcon/SDL_fbmatrox.h new file mode 100644 index 0000000..f7d41b0 --- /dev/null +++ b/3rdparty/SDL/src/video/fbcon/SDL_fbmatrox.h @@ -0,0 +1,29 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* Matrox hardware acceleration for the SDL framebuffer console driver */ + +#include "SDL_fbvideo.h" + +/* Set up the driver for Matrox acceleration */ +extern void FB_MatroxAccel(_THIS, __u32 card); diff --git a/3rdparty/SDL/src/video/fbcon/SDL_fbmouse.c b/3rdparty/SDL/src/video/fbcon/SDL_fbmouse.c new file mode 100644 index 0000000..d65f27e --- /dev/null +++ b/3rdparty/SDL/src/video/fbcon/SDL_fbmouse.c @@ -0,0 +1,33 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#include "SDL_mouse.h" +#include "../../events/SDL_events_c.h" +#include "SDL_fbvideo.h" +#include "SDL_fbmouse_c.h" + + +/* The implementation dependent data for the window manager cursor */ +struct WMcursor { + int unused; +}; diff --git a/3rdparty/SDL/src/video/fbcon/SDL_fbmouse_c.h b/3rdparty/SDL/src/video/fbcon/SDL_fbmouse_c.h new file mode 100644 index 0000000..fbb031d --- /dev/null +++ b/3rdparty/SDL/src/video/fbcon/SDL_fbmouse_c.h @@ -0,0 +1,26 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#include "SDL_fbvideo.h" + +/* Functions to be exported */ diff --git a/3rdparty/SDL/src/video/fbcon/SDL_fbriva.c b/3rdparty/SDL/src/video/fbcon/SDL_fbriva.c new file mode 100644 index 0000000..eb4b71f --- /dev/null +++ b/3rdparty/SDL/src/video/fbcon/SDL_fbriva.c @@ -0,0 +1,222 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#include "SDL_video.h" +#include "../SDL_blit.h" +#include "SDL_fbriva.h" +#include "riva_mmio.h" +#include "riva_regs.h" + + +static int FifoEmptyCount = 0; +static int FifoFreeCount = 0; + +/* Wait for vertical retrace */ +static void WaitVBL(_THIS) +{ + volatile Uint8 *port = (Uint8 *)(mapped_io + PCIO_OFFSET + 0x3DA); + + while ( (*port & 0x08) ) + ; + while ( !(*port & 0x08) ) + ; +} +static void NV3WaitIdle(_THIS) +{ + RivaRop *Rop = (RivaRop *)(mapped_io + ROP_OFFSET); + while ( (Rop->FifoFree < FifoEmptyCount) || + (*(mapped_io + PGRAPH_OFFSET + 0x000006B0) & 0x01) ) + ; +} +static void NV4WaitIdle(_THIS) +{ + RivaRop *Rop = (RivaRop *)(mapped_io + ROP_OFFSET); + while ( (Rop->FifoFree < FifoEmptyCount) || + (*(mapped_io + PGRAPH_OFFSET + 0x00000700) & 0x01) ) + ; +} + +#if 0 /* Not yet implemented? */ +/* Sets video mem colorkey and accelerated blit function */ +static int SetHWColorKey(_THIS, SDL_Surface *surface, Uint32 key) +{ + return(0); +} + +/* Sets per surface hardware alpha value */ +static int SetHWAlpha(_THIS, SDL_Surface *surface, Uint8 value) +{ + return(0); +} +#endif /* Not yet implemented */ + +static int FillHWRect(_THIS, SDL_Surface *dst, SDL_Rect *rect, Uint32 color) +{ + int dstX, dstY; + int dstW, dstH; + RivaBitmap *Bitmap = (RivaBitmap *)(mapped_io + BITMAP_OFFSET); + + /* Don't blit to the display surface when switched away */ + if ( switched_away ) { + return -2; /* no hardware access */ + } + if ( dst == this->screen ) { + SDL_mutexP(hw_lock); + } + + /* Set up the X/Y base coordinates */ + dstW = rect->w; + dstH = rect->h; + FB_dst_to_xy(this, dst, &dstX, &dstY); + + /* Adjust for the current rectangle */ + dstX += rect->x; + dstY += rect->y; + + RIVA_FIFO_FREE(Bitmap, 1); + Bitmap->Color1A = color; + + RIVA_FIFO_FREE(Bitmap, 2); + Bitmap->UnclippedRectangle[0].TopLeft = (dstX << 16) | dstY; + Bitmap->UnclippedRectangle[0].WidthHeight = (dstW << 16) | dstH; + + FB_AddBusySurface(dst); + + if ( dst == this->screen ) { + SDL_mutexV(hw_lock); + } + return(0); +} + +static int HWAccelBlit(SDL_Surface *src, SDL_Rect *srcrect, + SDL_Surface *dst, SDL_Rect *dstrect) +{ + SDL_VideoDevice *this = current_video; + int srcX, srcY; + int dstX, dstY; + int dstW, dstH; + RivaScreenBlt *Blt = (RivaScreenBlt *)(mapped_io + BLT_OFFSET); + + /* FIXME: For now, only blit to display surface */ + if ( dst->pitch != SDL_VideoSurface->pitch ) { + return(src->map->sw_blit(src, srcrect, dst, dstrect)); + } + + /* Don't blit to the display surface when switched away */ + if ( switched_away ) { + return -2; /* no hardware access */ + } + if ( dst == this->screen ) { + SDL_mutexP(hw_lock); + } + + /* Calculate source and destination base coordinates (in pixels) */ + dstW = dstrect->w; + dstH = dstrect->h; + FB_dst_to_xy(this, src, &srcX, &srcY); + FB_dst_to_xy(this, dst, &dstX, &dstY); + + /* Adjust for the current blit rectangles */ + srcX += srcrect->x; + srcY += srcrect->y; + dstX += dstrect->x; + dstY += dstrect->y; + + RIVA_FIFO_FREE(Blt, 3); + Blt->TopLeftSrc = (srcY << 16) | srcX; + Blt->TopLeftDst = (dstY << 16) | dstX; + Blt->WidthHeight = (dstH << 16) | dstW; + + FB_AddBusySurface(src); + FB_AddBusySurface(dst); + + if ( dst == this->screen ) { + SDL_mutexV(hw_lock); + } + return(0); +} + +static int CheckHWBlit(_THIS, SDL_Surface *src, SDL_Surface *dst) +{ + int accelerated; + + /* Set initial acceleration on */ + src->flags |= SDL_HWACCEL; + + /* Set the surface attributes */ + if ( (src->flags & SDL_SRCALPHA) == SDL_SRCALPHA ) { + if ( ! this->info.blit_hw_A ) { + src->flags &= ~SDL_HWACCEL; + } + } + if ( (src->flags & SDL_SRCCOLORKEY) == SDL_SRCCOLORKEY ) { + if ( ! this->info.blit_hw_CC ) { + src->flags &= ~SDL_HWACCEL; + } + } + + /* Check to see if final surface blit is accelerated */ + accelerated = !!(src->flags & SDL_HWACCEL); + if ( accelerated ) { + src->map->hw_blit = HWAccelBlit; + } + return(accelerated); +} + +void FB_RivaAccel(_THIS, __u32 card) +{ + RivaRop *Rop = (RivaRop *)(mapped_io + ROP_OFFSET); + + /* We have hardware accelerated surface functions */ + this->CheckHWBlit = CheckHWBlit; + wait_vbl = WaitVBL; + switch (card) { + case FB_ACCEL_NV3: + wait_idle = NV3WaitIdle; + break; + case FB_ACCEL_NV4: + wait_idle = NV4WaitIdle; + break; + default: + /* Hmm... FIXME */ + break; + } + FifoEmptyCount = Rop->FifoFree; + + /* The Riva has an accelerated color fill */ + this->info.blit_fill = 1; + this->FillHWRect = FillHWRect; + + /* The Riva has accelerated normal and colorkey blits. */ + this->info.blit_hw = 1; +#if 0 /* Not yet implemented? */ + this->info.blit_hw_CC = 1; + this->SetHWColorKey = SetHWColorKey; +#endif + +#if 0 /* Not yet implemented? */ + /* The Riva has an accelerated alpha blit */ + this->info.blit_hw_A = 1; + this->SetHWAlpha = SetHWAlpha; +#endif +} diff --git a/3rdparty/SDL/src/video/fbcon/SDL_fbriva.h b/3rdparty/SDL/src/video/fbcon/SDL_fbriva.h new file mode 100644 index 0000000..c78682e --- /dev/null +++ b/3rdparty/SDL/src/video/fbcon/SDL_fbriva.h @@ -0,0 +1,36 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* Riva hardware acceleration for the SDL framebuffer console driver */ + +#include "SDL_fbvideo.h" + +#ifndef FB_ACCEL_NV3 +#define FB_ACCEL_NV3 27 +#endif +#ifndef FB_ACCEL_NV4 +#define FB_ACCEL_NV4 28 +#endif + +/* Set up the driver for Riva acceleration */ +extern void FB_RivaAccel(_THIS, __u32 card); diff --git a/3rdparty/SDL/src/video/fbcon/SDL_fbvideo.c b/3rdparty/SDL/src/video/fbcon/SDL_fbvideo.c new file mode 100644 index 0000000..5e58809 --- /dev/null +++ b/3rdparty/SDL/src/video/fbcon/SDL_fbvideo.c @@ -0,0 +1,1982 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* Framebuffer console based SDL video driver implementation. +*/ + +#include <stdio.h> +#include <fcntl.h> +#include <unistd.h> +#include <sys/ioctl.h> +#include <sys/mman.h> + +#ifndef HAVE_GETPAGESIZE +#include <asm/page.h> /* For definition of PAGE_SIZE */ +#endif + +#include <linux/vt.h> + +#include "SDL_video.h" +#include "SDL_mouse.h" +#include "../SDL_sysvideo.h" +#include "../SDL_pixels_c.h" +#include "../../events/SDL_events_c.h" +#include "SDL_fbvideo.h" +#include "SDL_fbmouse_c.h" +#include "SDL_fbevents_c.h" +#include "SDL_fb3dfx.h" +#include "SDL_fbmatrox.h" +#include "SDL_fbriva.h" + +/*#define FBCON_DEBUG*/ + +#if defined(i386) && defined(FB_TYPE_VGA_PLANES) +#define VGA16_FBCON_SUPPORT +#include <sys/io.h> /* For ioperm() */ +#ifndef FB_AUX_VGA_PLANES_VGA4 +#define FB_AUX_VGA_PLANES_VGA4 0 +#endif +/* +static inline void outb (unsigned char value, unsigned short port) +{ + __asm__ __volatile__ ("outb %b0,%w1"::"a" (value), "Nd" (port)); +} +*/ +#endif /* FB_TYPE_VGA_PLANES */ + +/* A list of video resolutions that we query for (sorted largest to smallest) */ +static const SDL_Rect checkres[] = { + { 0, 0, 1600, 1200 }, /* 16 bpp: 0x11E, or 286 */ + { 0, 0, 1408, 1056 }, /* 16 bpp: 0x19A, or 410 */ + { 0, 0, 1280, 1024 }, /* 16 bpp: 0x11A, or 282 */ + { 0, 0, 1152, 864 }, /* 16 bpp: 0x192, or 402 */ + { 0, 0, 1024, 768 }, /* 16 bpp: 0x117, or 279 */ + { 0, 0, 960, 720 }, /* 16 bpp: 0x18A, or 394 */ + { 0, 0, 800, 600 }, /* 16 bpp: 0x114, or 276 */ + { 0, 0, 768, 576 }, /* 16 bpp: 0x182, or 386 */ + { 0, 0, 720, 576 }, /* PAL */ + { 0, 0, 720, 480 }, /* NTSC */ + { 0, 0, 640, 480 }, /* 16 bpp: 0x111, or 273 */ + { 0, 0, 640, 400 }, /* 8 bpp: 0x100, or 256 */ + { 0, 0, 512, 384 }, + { 0, 0, 320, 240 }, + { 0, 0, 320, 200 } +}; +static const struct { + int xres; + int yres; + int pixclock; + int left; + int right; + int upper; + int lower; + int hslen; + int vslen; + int sync; + int vmode; +} vesa_timings[] = { +#ifdef USE_VESA_TIMINGS /* Only tested on Matrox Millenium I */ + { 640, 400, 39771, 48, 16, 39, 8, 96, 2, 2, 0 }, /* 70 Hz */ + { 640, 480, 39683, 48, 16, 33, 10, 96, 2, 0, 0 }, /* 60 Hz */ + { 768, 576, 26101, 144, 16, 28, 6, 112, 4, 0, 0 }, /* 60 Hz */ + { 800, 600, 24038, 144, 24, 28, 8, 112, 6, 0, 0 }, /* 60 Hz */ + { 960, 720, 17686, 144, 24, 28, 8, 112, 4, 0, 0 }, /* 60 Hz */ + { 1024, 768, 15386, 160, 32, 30, 4, 128, 4, 0, 0 }, /* 60 Hz */ + { 1152, 864, 12286, 192, 32, 30, 4, 128, 4, 0, 0 }, /* 60 Hz */ + { 1280, 1024, 9369, 224, 32, 32, 4, 136, 4, 0, 0 }, /* 60 Hz */ + { 1408, 1056, 8214, 256, 40, 32, 5, 144, 5, 0, 0 }, /* 60 Hz */ + { 1600, 1200,/*?*/0, 272, 48, 32, 5, 152, 5, 0, 0 }, /* 60 Hz */ +#else + /* You can generate these timings from your XF86Config file using + the 'modeline2fb' perl script included with the fbset package. + These timings were generated for Matrox Millenium I, 15" monitor. + */ + { 320, 200, 79440, 16, 16, 20, 4, 48, 1, 0, 2 }, /* 70 Hz */ + { 320, 240, 63492, 16, 16, 16, 4, 48, 2, 0, 2 }, /* 72 Hz */ + { 512, 384, 49603, 48, 16, 16, 1, 64, 3, 0, 0 }, /* 78 Hz */ + { 640, 400, 31746, 96, 32, 41, 1, 64, 3, 2, 0 }, /* 85 Hz */ + { 640, 480, 31746, 120, 16, 16, 1, 64, 3, 0, 0 }, /* 75 Hz */ + { 768, 576, 26101, 144, 16, 28, 6, 112, 4, 0, 0 }, /* 60 Hz */ + { 800, 600, 20000, 64, 56, 23, 37, 120, 6, 3, 0 }, /* 72 Hz */ + { 960, 720, 17686, 144, 24, 28, 8, 112, 4, 0, 0 }, /* 60 Hz */ + { 1024, 768, 13333, 144, 24, 29, 3, 136, 6, 0, 0 }, /* 70 Hz */ + { 1152, 864, 12286, 192, 32, 30, 4, 128, 4, 0, 0 }, /* 60 Hz */ + { 1280, 1024, 9369, 224, 32, 32, 4, 136, 4, 0, 0 }, /* 60 Hz */ + { 1408, 1056, 8214, 256, 40, 32, 5, 144, 5, 0, 0 }, /* 60 Hz */ + { 1600, 1200,/*?*/0, 272, 48, 32, 5, 152, 5, 0, 0 }, /* 60 Hz */ +#endif +}; +enum { + FBCON_ROTATE_NONE = 0, + FBCON_ROTATE_CCW = 90, + FBCON_ROTATE_UD = 180, + FBCON_ROTATE_CW = 270 +}; + +#define min(a,b) ((a)<(b)?(a):(b)) + +/* Initialization/Query functions */ +static int FB_VideoInit(_THIS, SDL_PixelFormat *vformat); +static SDL_Rect **FB_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags); +static SDL_Surface *FB_SetVideoMode(_THIS, SDL_Surface *current, int width, int height, int bpp, Uint32 flags); +#ifdef VGA16_FBCON_SUPPORT +static SDL_Surface *FB_SetVGA16Mode(_THIS, SDL_Surface *current, int width, int height, int bpp, Uint32 flags); +#endif +static int FB_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors); +static void FB_VideoQuit(_THIS); + +/* Hardware surface functions */ +static int FB_InitHWSurfaces(_THIS, SDL_Surface *screen, char *base, int size); +static void FB_FreeHWSurfaces(_THIS); +static int FB_AllocHWSurface(_THIS, SDL_Surface *surface); +static int FB_LockHWSurface(_THIS, SDL_Surface *surface); +static void FB_UnlockHWSurface(_THIS, SDL_Surface *surface); +static void FB_FreeHWSurface(_THIS, SDL_Surface *surface); +static void FB_WaitVBL(_THIS); +static void FB_WaitIdle(_THIS); +static int FB_FlipHWSurface(_THIS, SDL_Surface *surface); + +/* Internal palette functions */ +static void FB_SavePalette(_THIS, struct fb_fix_screeninfo *finfo, + struct fb_var_screeninfo *vinfo); +static void FB_RestorePalette(_THIS); + +/* Shadow buffer functions */ +static FB_bitBlit FB_blit16; +static FB_bitBlit FB_blit16blocked; + +static int SDL_getpagesize(void) +{ +#ifdef HAVE_GETPAGESIZE + return getpagesize(); +#elif defined(PAGE_SIZE) + return PAGE_SIZE; +#else +#error Can not determine system page size. + return 4096; /* this is what it USED to be in Linux... */ +#endif +} + + +/* Small wrapper for mmap() so we can play nicely with no-mmu hosts + * (non-mmu hosts disallow the MAP_SHARED flag) */ + +static void *do_mmap(void *start, size_t length, int prot, int flags, int fd, off_t offset) +{ + void *ret; + ret = mmap(start, length, prot, flags, fd, offset); + if ( ret == (char *)-1 && (flags & MAP_SHARED) ) { + ret = mmap(start, length, prot, + (flags & ~MAP_SHARED) | MAP_PRIVATE, fd, offset); + } + return ret; +} + +/* FB driver bootstrap functions */ + +static int FB_Available(void) +{ + int console = -1; + /* Added check for /fb/0 (devfs) */ + /* but - use environment variable first... if it fails, still check defaults */ + int idx = 0; + const char *SDL_fbdevs[4] = { NULL, "/dev/fb0", "/dev/fb/0", NULL }; + + SDL_fbdevs[0] = SDL_getenv("SDL_FBDEV"); + if( !SDL_fbdevs[0] ) + idx++; + for( ; SDL_fbdevs[idx]; idx++ ) + { + console = open(SDL_fbdevs[idx], O_RDWR, 0); + if ( console >= 0 ) { + close(console); + break; + } + } + return(console >= 0); +} + +static void FB_DeleteDevice(SDL_VideoDevice *device) +{ + SDL_free(device->hidden); + SDL_free(device); +} + +static SDL_VideoDevice *FB_CreateDevice(int devindex) +{ + SDL_VideoDevice *this; + + /* Initialize all variables that we clean on shutdown */ + this = (SDL_VideoDevice *)SDL_malloc(sizeof(SDL_VideoDevice)); + if ( this ) { + SDL_memset(this, 0, (sizeof *this)); + this->hidden = (struct SDL_PrivateVideoData *) + SDL_malloc((sizeof *this->hidden)); + } + if ( (this == NULL) || (this->hidden == NULL) ) { + SDL_OutOfMemory(); + if ( this ) { + SDL_free(this); + } + return(0); + } + SDL_memset(this->hidden, 0, (sizeof *this->hidden)); + wait_vbl = FB_WaitVBL; + wait_idle = FB_WaitIdle; + mouse_fd = -1; + keyboard_fd = -1; + + /* Set the function pointers */ + this->VideoInit = FB_VideoInit; + this->ListModes = FB_ListModes; + this->SetVideoMode = FB_SetVideoMode; + this->SetColors = FB_SetColors; + this->UpdateRects = NULL; + this->VideoQuit = FB_VideoQuit; + this->AllocHWSurface = FB_AllocHWSurface; + this->CheckHWBlit = NULL; + this->FillHWRect = NULL; + this->SetHWColorKey = NULL; + this->SetHWAlpha = NULL; + this->LockHWSurface = FB_LockHWSurface; + this->UnlockHWSurface = FB_UnlockHWSurface; + this->FlipHWSurface = FB_FlipHWSurface; + this->FreeHWSurface = FB_FreeHWSurface; + this->SetCaption = NULL; + this->SetIcon = NULL; + this->IconifyWindow = NULL; + this->GrabInput = NULL; + this->GetWMInfo = NULL; + this->InitOSKeymap = FB_InitOSKeymap; + this->PumpEvents = FB_PumpEvents; + + this->free = FB_DeleteDevice; + + return this; +} + +VideoBootStrap FBCON_bootstrap = { + "fbcon", "Linux Framebuffer Console", + FB_Available, FB_CreateDevice +}; + +#define FB_MODES_DB "/etc/fb.modes" + +static int read_fbmodes_line(FILE*f, char* line, int length) +{ + int blank; + char* c; + int i; + + blank=0; + /* find a relevant line */ + do + { + if (!fgets(line,length,f)) + return 0; + c=line; + while(((*c=='\t')||(*c==' '))&&(*c!=0)) + c++; + + if ((*c=='\n')||(*c=='#')||(*c==0)) + blank=1; + else + blank=0; + } + while(blank); + /* remove whitespace at the begining of the string */ + i=0; + do + { + line[i]=c[i]; + i++; + } + while(c[i]!=0); + return 1; +} + +static int read_fbmodes_mode(FILE *f, struct fb_var_screeninfo *vinfo) +{ + char line[1024]; + char option[256]; + + /* Find a "geometry" */ + do { + if (read_fbmodes_line(f, line, sizeof(line))==0) + return 0; + if (SDL_strncmp(line,"geometry",8)==0) + break; + } + while(1); + + SDL_sscanf(line, "geometry %d %d %d %d %d", &vinfo->xres, &vinfo->yres, + &vinfo->xres_virtual, &vinfo->yres_virtual, &vinfo->bits_per_pixel); + if (read_fbmodes_line(f, line, sizeof(line))==0) + return 0; + + SDL_sscanf(line, "timings %d %d %d %d %d %d %d", &vinfo->pixclock, + &vinfo->left_margin, &vinfo->right_margin, &vinfo->upper_margin, + &vinfo->lower_margin, &vinfo->hsync_len, &vinfo->vsync_len); + + vinfo->sync=0; + vinfo->vmode=FB_VMODE_NONINTERLACED; + + /* Parse misc options */ + do { + if (read_fbmodes_line(f, line, sizeof(line))==0) + return 0; + + if (SDL_strncmp(line,"hsync",5)==0) { + SDL_sscanf(line,"hsync %s",option); + if (SDL_strncmp(option,"high",4)==0) + vinfo->sync |= FB_SYNC_HOR_HIGH_ACT; + } + else if (SDL_strncmp(line,"vsync",5)==0) { + SDL_sscanf(line,"vsync %s",option); + if (SDL_strncmp(option,"high",4)==0) + vinfo->sync |= FB_SYNC_VERT_HIGH_ACT; + } + else if (SDL_strncmp(line,"csync",5)==0) { + SDL_sscanf(line,"csync %s",option); + if (SDL_strncmp(option,"high",4)==0) + vinfo->sync |= FB_SYNC_COMP_HIGH_ACT; + } + else if (SDL_strncmp(line,"extsync",5)==0) { + SDL_sscanf(line,"extsync %s",option); + if (SDL_strncmp(option,"true",4)==0) + vinfo->sync |= FB_SYNC_EXT; + } + else if (SDL_strncmp(line,"laced",5)==0) { + SDL_sscanf(line,"laced %s",option); + if (SDL_strncmp(option,"true",4)==0) + vinfo->vmode |= FB_VMODE_INTERLACED; + } + else if (SDL_strncmp(line,"double",6)==0) { + SDL_sscanf(line,"double %s",option); + if (SDL_strncmp(option,"true",4)==0) + vinfo->vmode |= FB_VMODE_DOUBLE; + } + } + while(SDL_strncmp(line,"endmode",7)!=0); + + return 1; +} + +static int FB_CheckMode(_THIS, struct fb_var_screeninfo *vinfo, + int index, unsigned int *w, unsigned int *h) +{ + int mode_okay; + + mode_okay = 0; + vinfo->bits_per_pixel = (index+1)*8; + vinfo->xres = *w; + vinfo->xres_virtual = *w; + vinfo->yres = *h; + vinfo->yres_virtual = *h; + vinfo->activate = FB_ACTIVATE_TEST; + if ( ioctl(console_fd, FBIOPUT_VSCREENINFO, vinfo) == 0 ) { +#ifdef FBCON_DEBUG + fprintf(stderr, "Checked mode %dx%d at %d bpp, got mode %dx%d at %d bpp\n", *w, *h, (index+1)*8, vinfo->xres, vinfo->yres, vinfo->bits_per_pixel); +#endif + if ( (((vinfo->bits_per_pixel+7)/8)-1) == index ) { + *w = vinfo->xres; + *h = vinfo->yres; + mode_okay = 1; + } + } + return mode_okay; +} + +static int FB_AddMode(_THIS, int index, unsigned int w, unsigned int h, int check_timings) +{ + SDL_Rect *mode; + int i; + int next_mode; + + /* Check to see if we already have this mode */ + if ( SDL_nummodes[index] > 0 ) { + mode = SDL_modelist[index][SDL_nummodes[index]-1]; + if ( (mode->w == w) && (mode->h == h) ) { +#ifdef FBCON_DEBUG + fprintf(stderr, "We already have mode %dx%d at %d bytes per pixel\n", w, h, index+1); +#endif + return(0); + } + } + + /* Only allow a mode if we have a valid timing for it */ + if ( check_timings ) { + int found_timing = 0; + for ( i=0; i<(sizeof(vesa_timings)/sizeof(vesa_timings[0])); ++i ) { + if ( (w == vesa_timings[i].xres) && + (h == vesa_timings[i].yres) && vesa_timings[i].pixclock ) { + found_timing = 1; + break; + } + } + if ( !found_timing ) { +#ifdef FBCON_DEBUG + fprintf(stderr, "No valid timing line for mode %dx%d\n", w, h); +#endif + return(0); + } + } + + /* Set up the new video mode rectangle */ + mode = (SDL_Rect *)SDL_malloc(sizeof *mode); + if ( mode == NULL ) { + SDL_OutOfMemory(); + return(-1); + } + mode->x = 0; + mode->y = 0; + mode->w = w; + mode->h = h; +#ifdef FBCON_DEBUG + fprintf(stderr, "Adding mode %dx%d at %d bytes per pixel\n", w, h, index+1); +#endif + + /* Allocate the new list of modes, and fill in the new mode */ + next_mode = SDL_nummodes[index]; + SDL_modelist[index] = (SDL_Rect **) + SDL_realloc(SDL_modelist[index], (1+next_mode+1)*sizeof(SDL_Rect *)); + if ( SDL_modelist[index] == NULL ) { + SDL_OutOfMemory(); + SDL_nummodes[index] = 0; + SDL_free(mode); + return(-1); + } + SDL_modelist[index][next_mode] = mode; + SDL_modelist[index][next_mode+1] = NULL; + SDL_nummodes[index]++; + + return(0); +} + +static int cmpmodes(const void *va, const void *vb) +{ + const SDL_Rect *a = *(const SDL_Rect**)va; + const SDL_Rect *b = *(const SDL_Rect**)vb; + if ( a->h == b->h ) + return b->w - a->w; + else + return b->h - a->h; +} + +static void FB_SortModes(_THIS) +{ + int i; + for ( i=0; i<NUM_MODELISTS; ++i ) { + if ( SDL_nummodes[i] > 0 ) { + SDL_qsort(SDL_modelist[i], SDL_nummodes[i], sizeof *SDL_modelist[i], cmpmodes); + } + } +} + +static int FB_VideoInit(_THIS, SDL_PixelFormat *vformat) +{ + const int pagesize = SDL_getpagesize(); + struct fb_fix_screeninfo finfo; + struct fb_var_screeninfo vinfo; + int i, j; + int current_index; + unsigned int current_w; + unsigned int current_h; + const char *SDL_fbdev; + const char *rotation; + FILE *modesdb; + + /* Initialize the library */ + SDL_fbdev = SDL_getenv("SDL_FBDEV"); + if ( SDL_fbdev == NULL ) { + SDL_fbdev = "/dev/fb0"; + } + console_fd = open(SDL_fbdev, O_RDWR, 0); + if ( console_fd < 0 ) { + SDL_SetError("Unable to open %s", SDL_fbdev); + return(-1); + } + +#if !SDL_THREADS_DISABLED + /* Create the hardware surface lock mutex */ + hw_lock = SDL_CreateMutex(); + if ( hw_lock == NULL ) { + SDL_SetError("Unable to create lock mutex"); + FB_VideoQuit(this); + return(-1); + } +#endif + + /* Get the type of video hardware */ + if ( ioctl(console_fd, FBIOGET_FSCREENINFO, &finfo) < 0 ) { + SDL_SetError("Couldn't get console hardware info"); + FB_VideoQuit(this); + return(-1); + } + switch (finfo.type) { + case FB_TYPE_PACKED_PIXELS: + /* Supported, no worries.. */ + break; +#ifdef VGA16_FBCON_SUPPORT + case FB_TYPE_VGA_PLANES: + /* VGA16 is supported, but that's it */ + if ( finfo.type_aux == FB_AUX_VGA_PLANES_VGA4 ) { + if ( ioperm(0x3b4, 0x3df - 0x3b4 + 1, 1) < 0 ) { + SDL_SetError("No I/O port permissions"); + FB_VideoQuit(this); + return(-1); + } + this->SetVideoMode = FB_SetVGA16Mode; + break; + } + /* Fall through to unsupported case */ +#endif /* VGA16_FBCON_SUPPORT */ + default: + SDL_SetError("Unsupported console hardware"); + FB_VideoQuit(this); + return(-1); + } + switch (finfo.visual) { + case FB_VISUAL_TRUECOLOR: + case FB_VISUAL_PSEUDOCOLOR: + case FB_VISUAL_STATIC_PSEUDOCOLOR: + case FB_VISUAL_DIRECTCOLOR: + break; + default: + SDL_SetError("Unsupported console hardware"); + FB_VideoQuit(this); + return(-1); + } + + /* Check if the user wants to disable hardware acceleration */ + { const char *fb_accel; + fb_accel = SDL_getenv("SDL_FBACCEL"); + if ( fb_accel ) { + finfo.accel = SDL_atoi(fb_accel); + } + } + + /* Memory map the device, compensating for buggy PPC mmap() */ + mapped_offset = (((long)finfo.smem_start) - + (((long)finfo.smem_start)&~(pagesize-1))); + mapped_memlen = finfo.smem_len+mapped_offset; + mapped_mem = do_mmap(NULL, mapped_memlen, + PROT_READ|PROT_WRITE, MAP_SHARED, console_fd, 0); + if ( mapped_mem == (char *)-1 ) { + SDL_SetError("Unable to memory map the video hardware"); + mapped_mem = NULL; + FB_VideoQuit(this); + return(-1); + } + + /* Determine the current screen depth */ + if ( ioctl(console_fd, FBIOGET_VSCREENINFO, &vinfo) < 0 ) { + SDL_SetError("Couldn't get console pixel format"); + FB_VideoQuit(this); + return(-1); + } + vformat->BitsPerPixel = vinfo.bits_per_pixel; + if ( vformat->BitsPerPixel < 8 ) { + /* Assuming VGA16, we handle this via a shadow framebuffer */ + vformat->BitsPerPixel = 8; + } + for ( i=0; i<vinfo.red.length; ++i ) { + vformat->Rmask <<= 1; + vformat->Rmask |= (0x00000001<<vinfo.red.offset); + } + for ( i=0; i<vinfo.green.length; ++i ) { + vformat->Gmask <<= 1; + vformat->Gmask |= (0x00000001<<vinfo.green.offset); + } + for ( i=0; i<vinfo.blue.length; ++i ) { + vformat->Bmask <<= 1; + vformat->Bmask |= (0x00000001<<vinfo.blue.offset); + } + saved_vinfo = vinfo; + + /* Save hardware palette, if needed */ + FB_SavePalette(this, &finfo, &vinfo); + + /* If the I/O registers are available, memory map them so we + can take advantage of any supported hardware acceleration. + */ + vinfo.accel_flags = 0; /* Temporarily reserve registers */ + ioctl(console_fd, FBIOPUT_VSCREENINFO, &vinfo); + if ( finfo.accel && finfo.mmio_len ) { + mapped_iolen = finfo.mmio_len; + mapped_io = do_mmap(NULL, mapped_iolen, PROT_READ|PROT_WRITE, + MAP_SHARED, console_fd, mapped_memlen); + if ( mapped_io == (char *)-1 ) { + /* Hmm, failed to memory map I/O registers */ + mapped_io = NULL; + } + } + + rotate = FBCON_ROTATE_NONE; + rotation = SDL_getenv("SDL_VIDEO_FBCON_ROTATION"); + if (rotation != NULL) { + if (SDL_strlen(rotation) == 0) { + shadow_fb = 0; + rotate = FBCON_ROTATE_NONE; +#ifdef FBCON_DEBUG + printf("Not rotating, no shadow\n"); +#endif + } else if (!SDL_strcmp(rotation, "NONE")) { + shadow_fb = 1; + rotate = FBCON_ROTATE_NONE; +#ifdef FBCON_DEBUG + printf("Not rotating, but still using shadow\n"); +#endif + } else if (!SDL_strcmp(rotation, "CW")) { + shadow_fb = 1; + rotate = FBCON_ROTATE_CW; +#ifdef FBCON_DEBUG + printf("Rotating screen clockwise\n"); +#endif + } else if (!SDL_strcmp(rotation, "CCW")) { + shadow_fb = 1; + rotate = FBCON_ROTATE_CCW; +#ifdef FBCON_DEBUG + printf("Rotating screen counter clockwise\n"); +#endif + } else if (!SDL_strcmp(rotation, "UD")) { + shadow_fb = 1; + rotate = FBCON_ROTATE_UD; +#ifdef FBCON_DEBUG + printf("Rotating screen upside down\n"); +#endif + } else { + SDL_SetError("\"%s\" is not a valid value for " + "SDL_VIDEO_FBCON_ROTATION", rotation); + return(-1); + } + } + + if (rotate == FBCON_ROTATE_CW || rotate == FBCON_ROTATE_CCW) { + current_w = vinfo.yres; + current_h = vinfo.xres; + } else { + current_w = vinfo.xres; + current_h = vinfo.yres; + } + + /* Query for the list of available video modes */ + current_index = ((vinfo.bits_per_pixel+7)/8)-1; + modesdb = fopen(FB_MODES_DB, "r"); + for ( i=0; i<NUM_MODELISTS; ++i ) { + SDL_nummodes[i] = 0; + SDL_modelist[i] = NULL; + } + if ( SDL_getenv("SDL_FB_BROKEN_MODES") != NULL ) { + FB_AddMode(this, current_index, current_w, current_h, 0); + } else if(modesdb) { + while ( read_fbmodes_mode(modesdb, &vinfo) ) { + for ( i=0; i<NUM_MODELISTS; ++i ) { + unsigned int w, h; + + if (rotate == FBCON_ROTATE_CW || rotate == FBCON_ROTATE_CCW) { + w = vinfo.yres; + h = vinfo.xres; + } else { + w = vinfo.xres; + h = vinfo.yres; + } + /* See if we are querying for the current mode */ + if ( i == current_index ) { + if ( (current_w > w) || (current_h > h) ) { + /* Only check once */ + FB_AddMode(this, i, current_w, current_h, 0); + current_index = -1; + } + } + if ( FB_CheckMode(this, &vinfo, i, &w, &h) ) { + FB_AddMode(this, i, w, h, 0); + } + } + } + fclose(modesdb); + FB_SortModes(this); + } else { + for ( i=0; i<NUM_MODELISTS; ++i ) { + for ( j=0; j<(sizeof(checkres)/sizeof(checkres[0])); ++j ) { + unsigned int w, h; + + if (rotate == FBCON_ROTATE_CW || rotate == FBCON_ROTATE_CCW) { + w = checkres[j].h; + h = checkres[j].w; + } else { + w = checkres[j].w; + h = checkres[j].h; + } + /* See if we are querying for the current mode */ + if ( i == current_index ) { + if ( (current_w > w) || (current_h > h) ) { + /* Only check once */ + FB_AddMode(this, i, current_w, current_h, 0); + current_index = -1; + } + } + if ( FB_CheckMode(this, &vinfo, i, &w, &h) ) { + FB_AddMode(this, i, w, h, 1); + } + } + } + } + + this->info.current_w = current_w; + this->info.current_h = current_h; + this->info.wm_available = 0; + this->info.hw_available = !shadow_fb; + this->info.video_mem = shadow_fb ? 0 : finfo.smem_len/1024; + /* Fill in our hardware acceleration capabilities */ + if ( mapped_io ) { + switch (finfo.accel) { + case FB_ACCEL_MATROX_MGA2064W: + case FB_ACCEL_MATROX_MGA1064SG: + case FB_ACCEL_MATROX_MGA2164W: + case FB_ACCEL_MATROX_MGA2164W_AGP: + case FB_ACCEL_MATROX_MGAG100: + /*case FB_ACCEL_MATROX_MGAG200: G200 acceleration broken! */ + case FB_ACCEL_MATROX_MGAG400: +#ifdef FBACCEL_DEBUG + printf("Matrox hardware accelerator!\n"); +#endif + FB_MatroxAccel(this, finfo.accel); + break; + case FB_ACCEL_3DFX_BANSHEE: +#ifdef FBACCEL_DEBUG + printf("3DFX hardware accelerator!\n"); +#endif + FB_3DfxAccel(this, finfo.accel); + break; + case FB_ACCEL_NV3: + case FB_ACCEL_NV4: +#ifdef FBACCEL_DEBUG + printf("NVidia hardware accelerator!\n"); +#endif + FB_RivaAccel(this, finfo.accel); + break; + default: +#ifdef FBACCEL_DEBUG + printf("Unknown hardware accelerator.\n"); +#endif + break; + } + } + + if (shadow_fb) { + shadow_mem = (char *)SDL_malloc(mapped_memlen); + if (shadow_mem == NULL) { + SDL_SetError("No memory for shadow"); + return (-1); + } + } + + /* Enable mouse and keyboard support */ + if ( FB_OpenKeyboard(this) < 0 ) { + FB_VideoQuit(this); + return(-1); + } + if ( FB_OpenMouse(this) < 0 ) { + const char *sdl_nomouse; + + sdl_nomouse = SDL_getenv("SDL_NOMOUSE"); + if ( ! sdl_nomouse ) { + SDL_SetError("Unable to open mouse"); + FB_VideoQuit(this); + return(-1); + } + } + + /* We're done! */ + return(0); +} + +static SDL_Rect **FB_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags) +{ + return(SDL_modelist[((format->BitsPerPixel+7)/8)-1]); +} + +/* Various screen update functions available */ +static void FB_DirectUpdate(_THIS, int numrects, SDL_Rect *rects); +#ifdef VGA16_FBCON_SUPPORT +static void FB_VGA16Update(_THIS, int numrects, SDL_Rect *rects); +#endif + +#ifdef FBCON_DEBUG +static void print_vinfo(struct fb_var_screeninfo *vinfo) +{ + fprintf(stderr, "Printing vinfo:\n"); + fprintf(stderr, "\txres: %d\n", vinfo->xres); + fprintf(stderr, "\tyres: %d\n", vinfo->yres); + fprintf(stderr, "\txres_virtual: %d\n", vinfo->xres_virtual); + fprintf(stderr, "\tyres_virtual: %d\n", vinfo->yres_virtual); + fprintf(stderr, "\txoffset: %d\n", vinfo->xoffset); + fprintf(stderr, "\tyoffset: %d\n", vinfo->yoffset); + fprintf(stderr, "\tbits_per_pixel: %d\n", vinfo->bits_per_pixel); + fprintf(stderr, "\tgrayscale: %d\n", vinfo->grayscale); + fprintf(stderr, "\tnonstd: %d\n", vinfo->nonstd); + fprintf(stderr, "\tactivate: %d\n", vinfo->activate); + fprintf(stderr, "\theight: %d\n", vinfo->height); + fprintf(stderr, "\twidth: %d\n", vinfo->width); + fprintf(stderr, "\taccel_flags: %d\n", vinfo->accel_flags); + fprintf(stderr, "\tpixclock: %d\n", vinfo->pixclock); + fprintf(stderr, "\tleft_margin: %d\n", vinfo->left_margin); + fprintf(stderr, "\tright_margin: %d\n", vinfo->right_margin); + fprintf(stderr, "\tupper_margin: %d\n", vinfo->upper_margin); + fprintf(stderr, "\tlower_margin: %d\n", vinfo->lower_margin); + fprintf(stderr, "\thsync_len: %d\n", vinfo->hsync_len); + fprintf(stderr, "\tvsync_len: %d\n", vinfo->vsync_len); + fprintf(stderr, "\tsync: %d\n", vinfo->sync); + fprintf(stderr, "\tvmode: %d\n", vinfo->vmode); + fprintf(stderr, "\tred: %d/%d\n", vinfo->red.length, vinfo->red.offset); + fprintf(stderr, "\tgreen: %d/%d\n", vinfo->green.length, vinfo->green.offset); + fprintf(stderr, "\tblue: %d/%d\n", vinfo->blue.length, vinfo->blue.offset); + fprintf(stderr, "\talpha: %d/%d\n", vinfo->transp.length, vinfo->transp.offset); +} +static void print_finfo(struct fb_fix_screeninfo *finfo) +{ + fprintf(stderr, "Printing finfo:\n"); + fprintf(stderr, "\tsmem_start = %p\n", (char *)finfo->smem_start); + fprintf(stderr, "\tsmem_len = %d\n", finfo->smem_len); + fprintf(stderr, "\ttype = %d\n", finfo->type); + fprintf(stderr, "\ttype_aux = %d\n", finfo->type_aux); + fprintf(stderr, "\tvisual = %d\n", finfo->visual); + fprintf(stderr, "\txpanstep = %d\n", finfo->xpanstep); + fprintf(stderr, "\typanstep = %d\n", finfo->ypanstep); + fprintf(stderr, "\tywrapstep = %d\n", finfo->ywrapstep); + fprintf(stderr, "\tline_length = %d\n", finfo->line_length); + fprintf(stderr, "\tmmio_start = %p\n", (char *)finfo->mmio_start); + fprintf(stderr, "\tmmio_len = %d\n", finfo->mmio_len); + fprintf(stderr, "\taccel = %d\n", finfo->accel); +} +#endif + +static int choose_fbmodes_mode(struct fb_var_screeninfo *vinfo) +{ + int matched; + FILE *modesdb; + struct fb_var_screeninfo cinfo; + + matched = 0; + modesdb = fopen(FB_MODES_DB, "r"); + if ( modesdb ) { + /* Parse the mode definition file */ + while ( read_fbmodes_mode(modesdb, &cinfo) ) { + if ( (vinfo->xres == cinfo.xres && vinfo->yres == cinfo.yres) && + (!matched || (vinfo->bits_per_pixel == cinfo.bits_per_pixel)) ) { + vinfo->pixclock = cinfo.pixclock; + vinfo->left_margin = cinfo.left_margin; + vinfo->right_margin = cinfo.right_margin; + vinfo->upper_margin = cinfo.upper_margin; + vinfo->lower_margin = cinfo.lower_margin; + vinfo->hsync_len = cinfo.hsync_len; + vinfo->vsync_len = cinfo.vsync_len; + if ( matched ) { + break; + } + matched = 1; + } + } + fclose(modesdb); + } + return(matched); +} + +static int choose_vesa_mode(struct fb_var_screeninfo *vinfo) +{ + int matched; + int i; + + /* Check for VESA timings */ + matched = 0; + for ( i=0; i<(sizeof(vesa_timings)/sizeof(vesa_timings[0])); ++i ) { + if ( (vinfo->xres == vesa_timings[i].xres) && + (vinfo->yres == vesa_timings[i].yres) ) { +#ifdef FBCON_DEBUG + fprintf(stderr, "Using VESA timings for %dx%d\n", + vinfo->xres, vinfo->yres); +#endif + if ( vesa_timings[i].pixclock ) { + vinfo->pixclock = vesa_timings[i].pixclock; + } + vinfo->left_margin = vesa_timings[i].left; + vinfo->right_margin = vesa_timings[i].right; + vinfo->upper_margin = vesa_timings[i].upper; + vinfo->lower_margin = vesa_timings[i].lower; + vinfo->hsync_len = vesa_timings[i].hslen; + vinfo->vsync_len = vesa_timings[i].vslen; + vinfo->sync = vesa_timings[i].sync; + vinfo->vmode = vesa_timings[i].vmode; + matched = 1; + break; + } + } + return(matched); +} + +#ifdef VGA16_FBCON_SUPPORT +static SDL_Surface *FB_SetVGA16Mode(_THIS, SDL_Surface *current, + int width, int height, int bpp, Uint32 flags) +{ + struct fb_fix_screeninfo finfo; + struct fb_var_screeninfo vinfo; + + /* Set the terminal into graphics mode */ + if ( FB_EnterGraphicsMode(this) < 0 ) { + return(NULL); + } + + /* Restore the original palette */ + FB_RestorePalette(this); + + /* Set the video mode and get the final screen format */ + if ( ioctl(console_fd, FBIOGET_VSCREENINFO, &vinfo) < 0 ) { + SDL_SetError("Couldn't get console screen info"); + return(NULL); + } + cache_vinfo = vinfo; +#ifdef FBCON_DEBUG + fprintf(stderr, "Printing actual vinfo:\n"); + print_vinfo(&vinfo); +#endif + if ( ! SDL_ReallocFormat(current, bpp, 0, 0, 0, 0) ) { + return(NULL); + } + current->format->palette->ncolors = 16; + + /* Get the fixed information about the console hardware. + This is necessary since finfo.line_length changes. + */ + if ( ioctl(console_fd, FBIOGET_FSCREENINFO, &finfo) < 0 ) { + SDL_SetError("Couldn't get console hardware info"); + return(NULL); + } +#ifdef FBCON_DEBUG + fprintf(stderr, "Printing actual finfo:\n"); + print_finfo(&finfo); +#endif + + /* Save hardware palette, if needed */ + FB_SavePalette(this, &finfo, &vinfo); + + /* Set up the new mode framebuffer */ + current->flags = SDL_FULLSCREEN; + current->w = vinfo.xres; + current->h = vinfo.yres; + current->pitch = current->w; + current->pixels = SDL_malloc(current->h*current->pitch); + + /* Set the update rectangle function */ + this->UpdateRects = FB_VGA16Update; + + /* We're done */ + return(current); +} +#endif /* VGA16_FBCON_SUPPORT */ + +static SDL_Surface *FB_SetVideoMode(_THIS, SDL_Surface *current, + int width, int height, int bpp, Uint32 flags) +{ + struct fb_fix_screeninfo finfo; + struct fb_var_screeninfo vinfo; + int i; + Uint32 Rmask; + Uint32 Gmask; + Uint32 Bmask; + char *surfaces_mem; + int surfaces_len; + + /* Set the terminal into graphics mode */ + if ( FB_EnterGraphicsMode(this) < 0 ) { + return(NULL); + } + + /* Restore the original palette */ + FB_RestorePalette(this); + + /* Set the video mode and get the final screen format */ + if ( ioctl(console_fd, FBIOGET_VSCREENINFO, &vinfo) < 0 ) { + SDL_SetError("Couldn't get console screen info"); + return(NULL); + } +#ifdef FBCON_DEBUG + fprintf(stderr, "Printing original vinfo:\n"); + print_vinfo(&vinfo); +#endif + /* Do not use double buffering with shadow buffer */ + if (shadow_fb) { + flags &= ~SDL_DOUBLEBUF; + } + + if ( (vinfo.xres != width) || (vinfo.yres != height) || + (vinfo.bits_per_pixel != bpp) || (flags & SDL_DOUBLEBUF) ) { + vinfo.activate = FB_ACTIVATE_NOW; + vinfo.accel_flags = 0; + vinfo.bits_per_pixel = bpp; + vinfo.xres = width; + vinfo.xres_virtual = width; + vinfo.yres = height; + if ( flags & SDL_DOUBLEBUF ) { + vinfo.yres_virtual = height*2; + } else { + vinfo.yres_virtual = height; + } + vinfo.xoffset = 0; + vinfo.yoffset = 0; + vinfo.red.length = vinfo.red.offset = 0; + vinfo.green.length = vinfo.green.offset = 0; + vinfo.blue.length = vinfo.blue.offset = 0; + vinfo.transp.length = vinfo.transp.offset = 0; + if ( ! choose_fbmodes_mode(&vinfo) ) { + choose_vesa_mode(&vinfo); + } +#ifdef FBCON_DEBUG + fprintf(stderr, "Printing wanted vinfo:\n"); + print_vinfo(&vinfo); +#endif + if ( !shadow_fb && + ioctl(console_fd, FBIOPUT_VSCREENINFO, &vinfo) < 0 ) { + vinfo.yres_virtual = height; + if ( ioctl(console_fd, FBIOPUT_VSCREENINFO, &vinfo) < 0 ) { + SDL_SetError("Couldn't set console screen info"); + return(NULL); + } + } + } else { + int maxheight; + + /* Figure out how much video memory is available */ + if ( flags & SDL_DOUBLEBUF ) { + maxheight = height*2; + } else { + maxheight = height; + } + if ( vinfo.yres_virtual > maxheight ) { + vinfo.yres_virtual = maxheight; + } + } + cache_vinfo = vinfo; +#ifdef FBCON_DEBUG + fprintf(stderr, "Printing actual vinfo:\n"); + print_vinfo(&vinfo); +#endif + Rmask = 0; + for ( i=0; i<vinfo.red.length; ++i ) { + Rmask <<= 1; + Rmask |= (0x00000001<<vinfo.red.offset); + } + Gmask = 0; + for ( i=0; i<vinfo.green.length; ++i ) { + Gmask <<= 1; + Gmask |= (0x00000001<<vinfo.green.offset); + } + Bmask = 0; + for ( i=0; i<vinfo.blue.length; ++i ) { + Bmask <<= 1; + Bmask |= (0x00000001<<vinfo.blue.offset); + } + if ( ! SDL_ReallocFormat(current, vinfo.bits_per_pixel, + Rmask, Gmask, Bmask, 0) ) { + return(NULL); + } + + /* Get the fixed information about the console hardware. + This is necessary since finfo.line_length changes. + */ + if ( ioctl(console_fd, FBIOGET_FSCREENINFO, &finfo) < 0 ) { + SDL_SetError("Couldn't get console hardware info"); + return(NULL); + } + + /* Save hardware palette, if needed */ + FB_SavePalette(this, &finfo, &vinfo); + + if (shadow_fb) { + if (vinfo.bits_per_pixel == 16) { + blitFunc = (rotate == FBCON_ROTATE_NONE || + rotate == FBCON_ROTATE_UD) ? + FB_blit16 : FB_blit16blocked; + } else { +#ifdef FBCON_DEBUG + fprintf(stderr, "Init vinfo:\n"); + print_vinfo(&vinfo); +#endif + SDL_SetError("Using software buffer, but no blitter " + "function is available for %d bpp.", + vinfo.bits_per_pixel); + return(NULL); + } + } + + /* Set up the new mode framebuffer */ + current->flags &= SDL_FULLSCREEN; + if (shadow_fb) { + current->flags |= SDL_SWSURFACE; + } else { + current->flags |= SDL_HWSURFACE; + } + current->w = vinfo.xres; + current->h = vinfo.yres; + if (shadow_fb) { + current->pitch = current->w * ((vinfo.bits_per_pixel + 7) / 8); + current->pixels = shadow_mem; + physlinebytes = finfo.line_length; + } else { + current->pitch = finfo.line_length; + current->pixels = mapped_mem+mapped_offset; + } + + /* Set up the information for hardware surfaces */ + surfaces_mem = (char *)current->pixels + + vinfo.yres_virtual*current->pitch; + surfaces_len = (shadow_fb) ? + 0 : (mapped_memlen-(surfaces_mem-mapped_mem)); + + FB_FreeHWSurfaces(this); + FB_InitHWSurfaces(this, current, surfaces_mem, surfaces_len); + + /* Let the application know we have a hardware palette */ + switch (finfo.visual) { + case FB_VISUAL_PSEUDOCOLOR: + current->flags |= SDL_HWPALETTE; + break; + default: + break; + } + + /* Update for double-buffering, if we can */ + if ( flags & SDL_DOUBLEBUF ) { + if ( vinfo.yres_virtual == (height*2) ) { + current->flags |= SDL_DOUBLEBUF; + flip_page = 0; + flip_address[0] = (char *)current->pixels; + flip_address[1] = (char *)current->pixels+ + current->h*current->pitch; + this->screen = current; + FB_FlipHWSurface(this, current); + this->screen = NULL; + } + } + + /* Set the update rectangle function */ + this->UpdateRects = FB_DirectUpdate; + + /* We're done */ + return(current); +} + +#ifdef FBCON_DEBUG +void FB_DumpHWSurfaces(_THIS) +{ + vidmem_bucket *bucket; + + printf("Memory left: %d (%d total)\n", surfaces_memleft, surfaces_memtotal); + printf("\n"); + printf(" Base Size\n"); + for ( bucket=&surfaces; bucket; bucket=bucket->next ) { + printf("Bucket: %p, %d (%s)\n", bucket->base, bucket->size, bucket->used ? "used" : "free"); + if ( bucket->prev ) { + if ( bucket->base != bucket->prev->base+bucket->prev->size ) { + printf("Warning, corrupt bucket list! (prev)\n"); + } + } else { + if ( bucket != &surfaces ) { + printf("Warning, corrupt bucket list! (!prev)\n"); + } + } + if ( bucket->next ) { + if ( bucket->next->base != bucket->base+bucket->size ) { + printf("Warning, corrupt bucket list! (next)\n"); + } + } + } + printf("\n"); +} +#endif + +static int FB_InitHWSurfaces(_THIS, SDL_Surface *screen, char *base, int size) +{ + vidmem_bucket *bucket; + + surfaces_memtotal = size; + surfaces_memleft = size; + + if ( surfaces_memleft > 0 ) { + bucket = (vidmem_bucket *)SDL_malloc(sizeof(*bucket)); + if ( bucket == NULL ) { + SDL_OutOfMemory(); + return(-1); + } + bucket->prev = &surfaces; + bucket->used = 0; + bucket->dirty = 0; + bucket->base = base; + bucket->size = size; + bucket->next = NULL; + } else { + bucket = NULL; + } + + surfaces.prev = NULL; + surfaces.used = 1; + surfaces.dirty = 0; + surfaces.base = screen->pixels; + surfaces.size = (unsigned int)((long)base - (long)surfaces.base); + surfaces.next = bucket; + screen->hwdata = (struct private_hwdata *)&surfaces; + return(0); +} +static void FB_FreeHWSurfaces(_THIS) +{ + vidmem_bucket *bucket, *freeable; + + bucket = surfaces.next; + while ( bucket ) { + freeable = bucket; + bucket = bucket->next; + SDL_free(freeable); + } + surfaces.next = NULL; +} + +static int FB_AllocHWSurface(_THIS, SDL_Surface *surface) +{ + vidmem_bucket *bucket; + int size; + int extra; + +/* Temporarily, we only allow surfaces the same width as display. + Some blitters require the pitch between two hardware surfaces + to be the same. Others have interesting alignment restrictions. + Until someone who knows these details looks at the code... +*/ +if ( surface->pitch > SDL_VideoSurface->pitch ) { + SDL_SetError("Surface requested wider than screen"); + return(-1); +} +surface->pitch = SDL_VideoSurface->pitch; + size = surface->h * surface->pitch; +#ifdef FBCON_DEBUG + fprintf(stderr, "Allocating bucket of %d bytes\n", size); +#endif + + /* Quick check for available mem */ + if ( size > surfaces_memleft ) { + SDL_SetError("Not enough video memory"); + return(-1); + } + + /* Search for an empty bucket big enough */ + for ( bucket=&surfaces; bucket; bucket=bucket->next ) { + if ( ! bucket->used && (size <= bucket->size) ) { + break; + } + } + if ( bucket == NULL ) { + SDL_SetError("Video memory too fragmented"); + return(-1); + } + + /* Create a new bucket for left-over memory */ + extra = (bucket->size - size); + if ( extra ) { + vidmem_bucket *newbucket; + +#ifdef FBCON_DEBUG + fprintf(stderr, "Adding new free bucket of %d bytes\n", extra); +#endif + newbucket = (vidmem_bucket *)SDL_malloc(sizeof(*newbucket)); + if ( newbucket == NULL ) { + SDL_OutOfMemory(); + return(-1); + } + newbucket->prev = bucket; + newbucket->used = 0; + newbucket->base = bucket->base+size; + newbucket->size = extra; + newbucket->next = bucket->next; + if ( bucket->next ) { + bucket->next->prev = newbucket; + } + bucket->next = newbucket; + } + + /* Set the current bucket values and return it! */ + bucket->used = 1; + bucket->size = size; + bucket->dirty = 0; +#ifdef FBCON_DEBUG + fprintf(stderr, "Allocated %d bytes at %p\n", bucket->size, bucket->base); +#endif + surfaces_memleft -= size; + surface->flags |= SDL_HWSURFACE; + surface->pixels = bucket->base; + surface->hwdata = (struct private_hwdata *)bucket; + return(0); +} +static void FB_FreeHWSurface(_THIS, SDL_Surface *surface) +{ + vidmem_bucket *bucket, *freeable; + + /* Look for the bucket in the current list */ + for ( bucket=&surfaces; bucket; bucket=bucket->next ) { + if ( bucket == (vidmem_bucket *)surface->hwdata ) { + break; + } + } + if ( bucket && bucket->used ) { + /* Add the memory back to the total */ +#ifdef DGA_DEBUG + printf("Freeing bucket of %d bytes\n", bucket->size); +#endif + surfaces_memleft += bucket->size; + + /* Can we merge the space with surrounding buckets? */ + bucket->used = 0; + if ( bucket->next && ! bucket->next->used ) { +#ifdef DGA_DEBUG + printf("Merging with next bucket, for %d total bytes\n", bucket->size+bucket->next->size); +#endif + freeable = bucket->next; + bucket->size += bucket->next->size; + bucket->next = bucket->next->next; + if ( bucket->next ) { + bucket->next->prev = bucket; + } + SDL_free(freeable); + } + if ( bucket->prev && ! bucket->prev->used ) { +#ifdef DGA_DEBUG + printf("Merging with previous bucket, for %d total bytes\n", bucket->prev->size+bucket->size); +#endif + freeable = bucket; + bucket->prev->size += bucket->size; + bucket->prev->next = bucket->next; + if ( bucket->next ) { + bucket->next->prev = bucket->prev; + } + SDL_free(freeable); + } + } + surface->pixels = NULL; + surface->hwdata = NULL; +} + +static int FB_LockHWSurface(_THIS, SDL_Surface *surface) +{ + if ( switched_away ) { + return -2; /* no hardware access */ + } + if ( surface == this->screen ) { + SDL_mutexP(hw_lock); + if ( FB_IsSurfaceBusy(surface) ) { + FB_WaitBusySurfaces(this); + } + } else { + if ( FB_IsSurfaceBusy(surface) ) { + FB_WaitBusySurfaces(this); + } + } + return(0); +} +static void FB_UnlockHWSurface(_THIS, SDL_Surface *surface) +{ + if ( surface == this->screen ) { + SDL_mutexV(hw_lock); + } +} + +static void FB_WaitVBL(_THIS) +{ +#ifdef FBIOWAITRETRACE /* Heheh, this didn't make it into the main kernel */ + ioctl(console_fd, FBIOWAITRETRACE, 0); +#endif + return; +} + +static void FB_WaitIdle(_THIS) +{ + return; +} + +static int FB_FlipHWSurface(_THIS, SDL_Surface *surface) +{ + if ( switched_away ) { + return -2; /* no hardware access */ + } + + /* Wait for vertical retrace and then flip display */ + cache_vinfo.yoffset = flip_page*surface->h; + if ( FB_IsSurfaceBusy(this->screen) ) { + FB_WaitBusySurfaces(this); + } + wait_vbl(this); + if ( ioctl(console_fd, FBIOPAN_DISPLAY, &cache_vinfo) < 0 ) { + SDL_SetError("ioctl(FBIOPAN_DISPLAY) failed"); + return(-1); + } + flip_page = !flip_page; + + surface->pixels = flip_address[flip_page]; + return(0); +} + +static void FB_blit16(Uint8 *byte_src_pos, int src_right_delta, int src_down_delta, + Uint8 *byte_dst_pos, int dst_linebytes, int width, int height) +{ + int w; + Uint16 *src_pos = (Uint16 *)byte_src_pos; + Uint16 *dst_pos = (Uint16 *)byte_dst_pos; + + while (height) { + Uint16 *src = src_pos; + Uint16 *dst = dst_pos; + for (w = width; w != 0; w--) { + *dst = *src; + src += src_right_delta; + dst++; + } + dst_pos = (Uint16 *)((Uint8 *)dst_pos + dst_linebytes); + src_pos += src_down_delta; + height--; + } +} + +#define BLOCKSIZE_W 32 +#define BLOCKSIZE_H 32 + +static void FB_blit16blocked(Uint8 *byte_src_pos, int src_right_delta, int src_down_delta, + Uint8 *byte_dst_pos, int dst_linebytes, int width, int height) +{ + int w; + Uint16 *src_pos = (Uint16 *)byte_src_pos; + Uint16 *dst_pos = (Uint16 *)byte_dst_pos; + + while (height > 0) { + Uint16 *src = src_pos; + Uint16 *dst = dst_pos; + for (w = width; w > 0; w -= BLOCKSIZE_W) { + FB_blit16((Uint8 *)src, + src_right_delta, + src_down_delta, + (Uint8 *)dst, + dst_linebytes, + min(w, BLOCKSIZE_W), + min(height, BLOCKSIZE_H)); + src += src_right_delta * BLOCKSIZE_W; + dst += BLOCKSIZE_W; + } + dst_pos = (Uint16 *)((Uint8 *)dst_pos + dst_linebytes * BLOCKSIZE_H); + src_pos += src_down_delta * BLOCKSIZE_H; + height -= BLOCKSIZE_H; + } +} + +static void FB_DirectUpdate(_THIS, int numrects, SDL_Rect *rects) +{ + int width = cache_vinfo.xres; + int height = cache_vinfo.yres; + int bytes_per_pixel = (cache_vinfo.bits_per_pixel + 7) / 8; + int i; + + if (!shadow_fb) { + /* The application is already updating the visible video memory */ + return; + } + + if (cache_vinfo.bits_per_pixel != 16) { + SDL_SetError("Shadow copy only implemented for 16 bpp"); + return; + } + + for (i = 0; i < numrects; i++) { + int x1, y1, x2, y2; + int scr_x1, scr_y1, scr_x2, scr_y2; + int sha_x1, sha_y1; + int shadow_right_delta; /* Address change when moving right in dest */ + int shadow_down_delta; /* Address change when moving down in dest */ + char *src_start; + char *dst_start; + + x1 = rects[i].x; + y1 = rects[i].y; + x2 = x1 + rects[i].w; + y2 = y1 + rects[i].h; + + if (x1 < 0) { + x1 = 0; + } else if (x1 > width) { + x1 = width; + } + if (x2 < 0) { + x2 = 0; + } else if (x2 > width) { + x2 = width; + } + if (y1 < 0) { + y1 = 0; + } else if (y1 > height) { + y1 = height; + } + if (y2 < 0) { + y2 = 0; + } else if (y2 > height) { + y2 = height; + } + if (x2 <= x1 || y2 <= y1) { + continue; + } + + switch (rotate) { + case FBCON_ROTATE_NONE: + sha_x1 = scr_x1 = x1; + sha_y1 = scr_y1 = y1; + scr_x2 = x2; + scr_y2 = y2; + shadow_right_delta = 1; + shadow_down_delta = width; + break; + case FBCON_ROTATE_CCW: + scr_x1 = y1; + scr_y1 = width - x2; + scr_x2 = y2; + scr_y2 = width - x1; + sha_x1 = x2 - 1; + sha_y1 = y1; + shadow_right_delta = width; + shadow_down_delta = -1; + break; + case FBCON_ROTATE_UD: + scr_x1 = width - x2; + scr_y1 = height - y2; + scr_x2 = width - x1; + scr_y2 = height - y1; + sha_x1 = x2 - 1; + sha_y1 = y2 - 1; + shadow_right_delta = -1; + shadow_down_delta = -width; + break; + case FBCON_ROTATE_CW: + scr_x1 = height - y2; + scr_y1 = x1; + scr_x2 = height - y1; + scr_y2 = x2; + sha_x1 = x1; + sha_y1 = y2 - 1; + shadow_right_delta = -width; + shadow_down_delta = 1; + break; + default: + SDL_SetError("Unknown rotation"); + return; + } + + src_start = shadow_mem + + (sha_y1 * width + sha_x1) * bytes_per_pixel; + dst_start = mapped_mem + mapped_offset + scr_y1 * physlinebytes + + scr_x1 * bytes_per_pixel; + + blitFunc((Uint8 *) src_start, + shadow_right_delta, + shadow_down_delta, + (Uint8 *) dst_start, + physlinebytes, + scr_x2 - scr_x1, + scr_y2 - scr_y1); + } +} + +#ifdef VGA16_FBCON_SUPPORT +/* Code adapted with thanks from the XFree86 VGA16 driver! :) */ +#define writeGr(index, value) \ +outb(index, 0x3CE); \ +outb(value, 0x3CF); +#define writeSeq(index, value) \ +outb(index, 0x3C4); \ +outb(value, 0x3C5); + +static void FB_VGA16Update(_THIS, int numrects, SDL_Rect *rects) +{ + SDL_Surface *screen; + int width, height, FBPitch, left, i, j, SRCPitch, phase; + register Uint32 m; + Uint8 s1, s2, s3, s4; + Uint32 *src, *srcPtr; + Uint8 *dst, *dstPtr; + + if ( switched_away ) { + return; /* no hardware access */ + } + + screen = this->screen; + FBPitch = screen->w >> 3; + SRCPitch = screen->pitch >> 2; + + writeGr(0x03, 0x00); + writeGr(0x05, 0x00); + writeGr(0x01, 0x00); + writeGr(0x08, 0xFF); + + while(numrects--) { + left = rects->x & ~7; + width = (rects->w + 7) >> 3; + height = rects->h; + src = (Uint32*)screen->pixels + (rects->y * SRCPitch) + (left >> 2); + dst = (Uint8*)mapped_mem + (rects->y * FBPitch) + (left >> 3); + + if((phase = (long)dst & 3L)) { + phase = 4 - phase; + if(phase > width) phase = width; + width -= phase; + } + + while(height--) { + writeSeq(0x02, 1 << 0); + dstPtr = dst; + srcPtr = src; + i = width; + j = phase; + while(j--) { + m = (srcPtr[1] & 0x01010101) | ((srcPtr[0] & 0x01010101) << 4); + *dstPtr++ = (m >> 24) | (m >> 15) | (m >> 6) | (m << 3); + srcPtr += 2; + } + while(i >= 4) { + m = (srcPtr[1] & 0x01010101) | ((srcPtr[0] & 0x01010101) << 4); + s1 = (m >> 24) | (m >> 15) | (m >> 6) | (m << 3); + m = (srcPtr[3] & 0x01010101) | ((srcPtr[2] & 0x01010101) << 4); + s2 = (m >> 24) | (m >> 15) | (m >> 6) | (m << 3); + m = (srcPtr[5] & 0x01010101) | ((srcPtr[4] & 0x01010101) << 4); + s3 = (m >> 24) | (m >> 15) | (m >> 6) | (m << 3); + m = (srcPtr[7] & 0x01010101) | ((srcPtr[6] & 0x01010101) << 4); + s4 = (m >> 24) | (m >> 15) | (m >> 6) | (m << 3); + *((Uint32*)dstPtr) = s1 | (s2 << 8) | (s3 << 16) | (s4 << 24); + srcPtr += 8; + dstPtr += 4; + i -= 4; + } + while(i--) { + m = (srcPtr[1] & 0x01010101) | ((srcPtr[0] & 0x01010101) << 4); + *dstPtr++ = (m >> 24) | (m >> 15) | (m >> 6) | (m << 3); + srcPtr += 2; + } + + writeSeq(0x02, 1 << 1); + dstPtr = dst; + srcPtr = src; + i = width; + j = phase; + while(j--) { + m = (srcPtr[1] & 0x02020202) | ((srcPtr[0] & 0x02020202) << 4); + *dstPtr++ = (m >> 25) | (m >> 16) | (m >> 7) | (m << 2); + srcPtr += 2; + } + while(i >= 4) { + m = (srcPtr[1] & 0x02020202) | ((srcPtr[0] & 0x02020202) << 4); + s1 = (m >> 25) | (m >> 16) | (m >> 7) | (m << 2); + m = (srcPtr[3] & 0x02020202) | ((srcPtr[2] & 0x02020202) << 4); + s2 = (m >> 25) | (m >> 16) | (m >> 7) | (m << 2); + m = (srcPtr[5] & 0x02020202) | ((srcPtr[4] & 0x02020202) << 4); + s3 = (m >> 25) | (m >> 16) | (m >> 7) | (m << 2); + m = (srcPtr[7] & 0x02020202) | ((srcPtr[6] & 0x02020202) << 4); + s4 = (m >> 25) | (m >> 16) | (m >> 7) | (m << 2); + *((Uint32*)dstPtr) = s1 | (s2 << 8) | (s3 << 16) | (s4 << 24); + srcPtr += 8; + dstPtr += 4; + i -= 4; + } + while(i--) { + m = (srcPtr[1] & 0x02020202) | ((srcPtr[0] & 0x02020202) << 4); + *dstPtr++ = (m >> 25) | (m >> 16) | (m >> 7) | (m << 2); + srcPtr += 2; + } + + writeSeq(0x02, 1 << 2); + dstPtr = dst; + srcPtr = src; + i = width; + j = phase; + while(j--) { + m = (srcPtr[1] & 0x04040404) | ((srcPtr[0] & 0x04040404) << 4); + *dstPtr++ = (m >> 26) | (m >> 17) | (m >> 8) | (m << 1); + srcPtr += 2; + } + while(i >= 4) { + m = (srcPtr[1] & 0x04040404) | ((srcPtr[0] & 0x04040404) << 4); + s1 = (m >> 26) | (m >> 17) | (m >> 8) | (m << 1); + m = (srcPtr[3] & 0x04040404) | ((srcPtr[2] & 0x04040404) << 4); + s2 = (m >> 26) | (m >> 17) | (m >> 8) | (m << 1); + m = (srcPtr[5] & 0x04040404) | ((srcPtr[4] & 0x04040404) << 4); + s3 = (m >> 26) | (m >> 17) | (m >> 8) | (m << 1); + m = (srcPtr[7] & 0x04040404) | ((srcPtr[6] & 0x04040404) << 4); + s4 = (m >> 26) | (m >> 17) | (m >> 8) | (m << 1); + *((Uint32*)dstPtr) = s1 | (s2 << 8) | (s3 << 16) | (s4 << 24); + srcPtr += 8; + dstPtr += 4; + i -= 4; + } + while(i--) { + m = (srcPtr[1] & 0x04040404) | ((srcPtr[0] & 0x04040404) << 4); + *dstPtr++ = (m >> 26) | (m >> 17) | (m >> 8) | (m << 1); + srcPtr += 2; + } + + writeSeq(0x02, 1 << 3); + dstPtr = dst; + srcPtr = src; + i = width; + j = phase; + while(j--) { + m = (srcPtr[1] & 0x08080808) | ((srcPtr[0] & 0x08080808) << 4); + *dstPtr++ = (m >> 27) | (m >> 18) | (m >> 9) | m; + srcPtr += 2; + } + while(i >= 4) { + m = (srcPtr[1] & 0x08080808) | ((srcPtr[0] & 0x08080808) << 4); + s1 = (m >> 27) | (m >> 18) | (m >> 9) | m; + m = (srcPtr[3] & 0x08080808) | ((srcPtr[2] & 0x08080808) << 4); + s2 = (m >> 27) | (m >> 18) | (m >> 9) | m; + m = (srcPtr[5] & 0x08080808) | ((srcPtr[4] & 0x08080808) << 4); + s3 = (m >> 27) | (m >> 18) | (m >> 9) | m; + m = (srcPtr[7] & 0x08080808) | ((srcPtr[6] & 0x08080808) << 4); + s4 = (m >> 27) | (m >> 18) | (m >> 9) | m; + *((Uint32*)dstPtr) = s1 | (s2 << 8) | (s3 << 16) | (s4 << 24); + srcPtr += 8; + dstPtr += 4; + i -= 4; + } + while(i--) { + m = (srcPtr[1] & 0x08080808) | ((srcPtr[0] & 0x08080808) << 4); + *dstPtr++ = (m >> 27) | (m >> 18) | (m >> 9) | m; + srcPtr += 2; + } + + dst += FBPitch; + src += SRCPitch; + } + rects++; + } +} +#endif /* VGA16_FBCON_SUPPORT */ + +void FB_SavePaletteTo(_THIS, int palette_len, __u16 *area) +{ + struct fb_cmap cmap; + + cmap.start = 0; + cmap.len = palette_len; + cmap.red = &area[0*palette_len]; + cmap.green = &area[1*palette_len]; + cmap.blue = &area[2*palette_len]; + cmap.transp = NULL; + ioctl(console_fd, FBIOGETCMAP, &cmap); +} + +void FB_RestorePaletteFrom(_THIS, int palette_len, __u16 *area) +{ + struct fb_cmap cmap; + + cmap.start = 0; + cmap.len = palette_len; + cmap.red = &area[0*palette_len]; + cmap.green = &area[1*palette_len]; + cmap.blue = &area[2*palette_len]; + cmap.transp = NULL; + ioctl(console_fd, FBIOPUTCMAP, &cmap); +} + +static void FB_SavePalette(_THIS, struct fb_fix_screeninfo *finfo, + struct fb_var_screeninfo *vinfo) +{ + int i; + + /* Save hardware palette, if needed */ + if ( finfo->visual == FB_VISUAL_PSEUDOCOLOR ) { + saved_cmaplen = 1<<vinfo->bits_per_pixel; + saved_cmap=(__u16 *)SDL_malloc(3*saved_cmaplen*sizeof(*saved_cmap)); + if ( saved_cmap != NULL ) { + FB_SavePaletteTo(this, saved_cmaplen, saved_cmap); + } + } + + /* Added support for FB_VISUAL_DIRECTCOLOR. + With this mode pixel information is passed through the palette... + Neat fading and gamma correction effects can be had by simply + fooling around with the palette instead of changing the pixel + values themselves... Very neat! + + Adam Meyerowitz 1/19/2000 + ameyerow@optonline.com + */ + if ( finfo->visual == FB_VISUAL_DIRECTCOLOR ) { + __u16 new_entries[3*256]; + + /* Save the colormap */ + saved_cmaplen = 256; + saved_cmap=(__u16 *)SDL_malloc(3*saved_cmaplen*sizeof(*saved_cmap)); + if ( saved_cmap != NULL ) { + FB_SavePaletteTo(this, saved_cmaplen, saved_cmap); + } + + /* Allocate new identity colormap */ + for ( i=0; i<256; ++i ) { + new_entries[(0*256)+i] = + new_entries[(1*256)+i] = + new_entries[(2*256)+i] = (i<<8)|i; + } + FB_RestorePaletteFrom(this, 256, new_entries); + } +} + +static void FB_RestorePalette(_THIS) +{ + /* Restore the original palette */ + if ( saved_cmap ) { + FB_RestorePaletteFrom(this, saved_cmaplen, saved_cmap); + SDL_free(saved_cmap); + saved_cmap = NULL; + } +} + +static int FB_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors) +{ + int i; + __u16 r[256]; + __u16 g[256]; + __u16 b[256]; + struct fb_cmap cmap; + + /* Set up the colormap */ + for (i = 0; i < ncolors; i++) { + r[i] = colors[i].r << 8; + g[i] = colors[i].g << 8; + b[i] = colors[i].b << 8; + } + cmap.start = firstcolor; + cmap.len = ncolors; + cmap.red = r; + cmap.green = g; + cmap.blue = b; + cmap.transp = NULL; + + if( (ioctl(console_fd, FBIOPUTCMAP, &cmap) < 0) || + !(this->screen->flags & SDL_HWPALETTE) ) { + colors = this->screen->format->palette->colors; + ncolors = this->screen->format->palette->ncolors; + cmap.start = 0; + cmap.len = ncolors; + SDL_memset(r, 0, sizeof(r)); + SDL_memset(g, 0, sizeof(g)); + SDL_memset(b, 0, sizeof(b)); + if ( ioctl(console_fd, FBIOGETCMAP, &cmap) == 0 ) { + for ( i=ncolors-1; i>=0; --i ) { + colors[i].r = (r[i]>>8); + colors[i].g = (g[i]>>8); + colors[i].b = (b[i]>>8); + } + } + return(0); + } + return(1); +} + +/* Note: If we are terminated, this could be called in the middle of + another SDL video routine -- notably UpdateRects. +*/ +static void FB_VideoQuit(_THIS) +{ + int i, j; + + if ( this->screen ) { + /* Clear screen and tell SDL not to free the pixels */ + + const char *dontClearPixels = SDL_getenv("SDL_FBCON_DONT_CLEAR"); + + /* If the framebuffer is not to be cleared, make sure that we won't + * display the previous frame when disabling double buffering. */ + if ( dontClearPixels && flip_page == 0 ) { + SDL_memcpy(flip_address[0], flip_address[1], this->screen->pitch * this->screen->h); + } + + if ( !dontClearPixels && this->screen->pixels && FB_InGraphicsMode(this) ) { +#if defined(__powerpc__) || defined(__ia64__) /* SIGBUS when using SDL_memset() ?? */ + Uint8 *rowp = (Uint8 *)this->screen->pixels; + int left = this->screen->pitch*this->screen->h; + while ( left-- ) { *rowp++ = 0; } +#else + SDL_memset(this->screen->pixels,0,this->screen->h*this->screen->pitch); +#endif + } + /* This test fails when using the VGA16 shadow memory */ + if ( ((char *)this->screen->pixels >= mapped_mem) && + ((char *)this->screen->pixels < (mapped_mem+mapped_memlen)) ) { + this->screen->pixels = NULL; + } + } + + /* Clear the lock mutex */ + if ( hw_lock ) { + SDL_DestroyMutex(hw_lock); + hw_lock = NULL; + } + + /* Clean up defined video modes */ + for ( i=0; i<NUM_MODELISTS; ++i ) { + if ( SDL_modelist[i] != NULL ) { + for ( j=0; SDL_modelist[i][j]; ++j ) { + SDL_free(SDL_modelist[i][j]); + } + SDL_free(SDL_modelist[i]); + SDL_modelist[i] = NULL; + } + } + + /* Clean up the memory bucket list */ + FB_FreeHWSurfaces(this); + + /* Close console and input file descriptors */ + if ( console_fd > 0 ) { + /* Unmap the video framebuffer and I/O registers */ + if ( mapped_mem ) { + munmap(mapped_mem, mapped_memlen); + mapped_mem = NULL; + } + if ( mapped_io ) { + munmap(mapped_io, mapped_iolen); + mapped_io = NULL; + } + + /* Restore the original video mode and palette */ + if ( FB_InGraphicsMode(this) ) { + FB_RestorePalette(this); + ioctl(console_fd, FBIOPUT_VSCREENINFO, &saved_vinfo); + } + + /* We're all done with the framebuffer */ + close(console_fd); + console_fd = -1; + } + FB_CloseMouse(this); + FB_CloseKeyboard(this); +} diff --git a/3rdparty/SDL/src/video/fbcon/SDL_fbvideo.h b/3rdparty/SDL/src/video/fbcon/SDL_fbvideo.h new file mode 100644 index 0000000..1443d2b --- /dev/null +++ b/3rdparty/SDL/src/video/fbcon/SDL_fbvideo.h @@ -0,0 +1,200 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#ifndef _SDL_fbvideo_h +#define _SDL_fbvideo_h + +#include <sys/types.h> +#include <termios.h> +#include <linux/fb.h> + +#include "SDL_mouse.h" +#include "SDL_mutex.h" +#include "../SDL_sysvideo.h" +#if SDL_INPUT_TSLIB +#include "tslib.h" +#endif + +/* Hidden "this" pointer for the video functions */ +#define _THIS SDL_VideoDevice *this + +typedef void FB_bitBlit( + Uint8 *src_pos, + int src_right_delta, /* pixels, not bytes */ + int src_down_delta, /* pixels, not bytes */ + Uint8 *dst_pos, + int dst_linebytes, + int width, + int height); + +/* This is the structure we use to keep track of video memory */ +typedef struct vidmem_bucket { + struct vidmem_bucket *prev; + int used; + int dirty; + char *base; + unsigned int size; + struct vidmem_bucket *next; +} vidmem_bucket; + +/* Private display data */ +struct SDL_PrivateVideoData { + int console_fd; + struct fb_var_screeninfo cache_vinfo; + struct fb_var_screeninfo saved_vinfo; + int saved_cmaplen; + __u16 *saved_cmap; + + int current_vt; + int saved_vt; + int keyboard_fd; + int saved_kbd_mode; + struct termios saved_kbd_termios; + + int mouse_fd; +#if SDL_INPUT_TSLIB + struct tsdev *ts_dev; +#endif + + char *mapped_mem; + char *shadow_mem; + int mapped_memlen; + int mapped_offset; + char *mapped_io; + long mapped_iolen; + int flip_page; + char *flip_address[2]; + int rotate; + int shadow_fb; /* Tells whether a shadow is being used. */ + FB_bitBlit *blitFunc; + int physlinebytes; /* Length of a line in bytes in physical fb */ + +#define NUM_MODELISTS 4 /* 8, 16, 24, and 32 bits-per-pixel */ + int SDL_nummodes[NUM_MODELISTS]; + SDL_Rect **SDL_modelist[NUM_MODELISTS]; + + vidmem_bucket surfaces; + int surfaces_memtotal; + int surfaces_memleft; + + SDL_mutex *hw_lock; + int switched_away; + struct fb_var_screeninfo screen_vinfo; + Uint32 screen_arealen; + Uint8 *screen_contents; + __u16 screen_palette[3*256]; + + void (*wait_vbl)(_THIS); + void (*wait_idle)(_THIS); +}; +/* Old variable names */ +#define console_fd (this->hidden->console_fd) +#define current_vt (this->hidden->current_vt) +#define saved_vt (this->hidden->saved_vt) +#define keyboard_fd (this->hidden->keyboard_fd) +#define saved_kbd_mode (this->hidden->saved_kbd_mode) +#define saved_kbd_termios (this->hidden->saved_kbd_termios) +#define mouse_fd (this->hidden->mouse_fd) +#if SDL_INPUT_TSLIB +#define ts_dev (this->hidden->ts_dev) +#endif +#define cache_vinfo (this->hidden->cache_vinfo) +#define saved_vinfo (this->hidden->saved_vinfo) +#define saved_cmaplen (this->hidden->saved_cmaplen) +#define saved_cmap (this->hidden->saved_cmap) +#define mapped_mem (this->hidden->mapped_mem) +#define shadow_mem (this->hidden->shadow_mem) +#define mapped_memlen (this->hidden->mapped_memlen) +#define mapped_offset (this->hidden->mapped_offset) +#define mapped_io (this->hidden->mapped_io) +#define mapped_iolen (this->hidden->mapped_iolen) +#define flip_page (this->hidden->flip_page) +#define flip_address (this->hidden->flip_address) +#define rotate (this->hidden->rotate) +#define shadow_fb (this->hidden->shadow_fb) +#define blitFunc (this->hidden->blitFunc) +#define physlinebytes (this->hidden->physlinebytes) +#define SDL_nummodes (this->hidden->SDL_nummodes) +#define SDL_modelist (this->hidden->SDL_modelist) +#define surfaces (this->hidden->surfaces) +#define surfaces_memtotal (this->hidden->surfaces_memtotal) +#define surfaces_memleft (this->hidden->surfaces_memleft) +#define hw_lock (this->hidden->hw_lock) +#define switched_away (this->hidden->switched_away) +#define screen_vinfo (this->hidden->screen_vinfo) +#define screen_arealen (this->hidden->screen_arealen) +#define screen_contents (this->hidden->screen_contents) +#define screen_palette (this->hidden->screen_palette) +#define wait_vbl (this->hidden->wait_vbl) +#define wait_idle (this->hidden->wait_idle) + +/* Accelerator types that are supported by the driver, but are not + necessarily in the kernel headers on the system we compile on. +*/ +#ifndef FB_ACCEL_MATROX_MGAG400 +#define FB_ACCEL_MATROX_MGAG400 26 /* Matrox G400 */ +#endif +#ifndef FB_ACCEL_3DFX_BANSHEE +#define FB_ACCEL_3DFX_BANSHEE 31 /* 3Dfx Banshee */ +#endif + +/* These functions are defined in SDL_fbvideo.c */ +extern void FB_SavePaletteTo(_THIS, int palette_len, __u16 *area); +extern void FB_RestorePaletteFrom(_THIS, int palette_len, __u16 *area); + +/* These are utility functions for working with video surfaces */ + +static __inline__ void FB_AddBusySurface(SDL_Surface *surface) +{ + ((vidmem_bucket *)surface->hwdata)->dirty = 1; +} + +static __inline__ int FB_IsSurfaceBusy(SDL_Surface *surface) +{ + return ((vidmem_bucket *)surface->hwdata)->dirty; +} + +static __inline__ void FB_WaitBusySurfaces(_THIS) +{ + vidmem_bucket *bucket; + + /* Wait for graphic operations to complete */ + wait_idle(this); + + /* Clear all surface dirty bits */ + for ( bucket=&surfaces; bucket; bucket=bucket->next ) { + bucket->dirty = 0; + } +} + +static __inline__ void FB_dst_to_xy(_THIS, SDL_Surface *dst, int *x, int *y) +{ + *x = (long)((char *)dst->pixels - mapped_mem)%this->screen->pitch; + *y = (long)((char *)dst->pixels - mapped_mem)/this->screen->pitch; + if ( dst == this->screen ) { + *x += this->offset_x; + *y += this->offset_y; + } +} + +#endif /* _SDL_fbvideo_h */ diff --git a/3rdparty/SDL/src/video/fbcon/matrox_mmio.h b/3rdparty/SDL/src/video/fbcon/matrox_mmio.h new file mode 100644 index 0000000..a1cf203 --- /dev/null +++ b/3rdparty/SDL/src/video/fbcon/matrox_mmio.h @@ -0,0 +1,51 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* MGA register definitions */ + +#include "matrox_regs.h" + +/* MGA control macros */ + +#define mga_in8(reg) *(volatile Uint8 *)(mapped_io + (reg)) +#define mga_in32(reg) *(volatile Uint32 *)(mapped_io + (reg)) + +#define mga_out8(reg,v) *(volatile Uint8 *)(mapped_io + (reg)) = v; +#define mga_out32(reg,v) *(volatile Uint32 *)(mapped_io + (reg)) = v; + + +/* Wait for fifo space */ +#define mga_wait(space) \ +{ \ + while ( mga_in8(MGAREG_FIFOSTATUS) < space ) \ + ; \ +} + + +/* Wait for idle accelerator */ +#define mga_waitidle() \ +{ \ + while ( mga_in32(MGAREG_STATUS) & 0x10000 ) \ + ; \ +} + diff --git a/3rdparty/SDL/src/video/fbcon/matrox_regs.h b/3rdparty/SDL/src/video/fbcon/matrox_regs.h new file mode 100644 index 0000000..d570b0c --- /dev/null +++ b/3rdparty/SDL/src/video/fbcon/matrox_regs.h @@ -0,0 +1,376 @@ + +/* + * MGA Millennium (MGA2064W) functions + * MGA Mystique (MGA1064SG) functions + * + * Copyright 1996 The XFree86 Project, Inc. + * + * Authors + * Dirk Hohndel + * hohndel@XFree86.Org + * David Dawes + * dawes@XFree86.Org + * Contributors: + * Guy DESBIEF, Aix-en-provence, France + * g.desbief@aix.pacwan.net + * MGA1064SG Mystique register file + */ + + +#ifndef _MGA_REG_H_ +#define _MGA_REG_H_ + +#define MGAREG_DWGCTL 0x1c00 +#define MGAREG_MACCESS 0x1c04 +/* the following is a mystique only register */ +#define MGAREG_MCTLWTST 0x1c08 +#define MGAREG_ZORG 0x1c0c + +#define MGAREG_PAT0 0x1c10 +#define MGAREG_PAT1 0x1c14 +#define MGAREG_PLNWT 0x1c1c + +#define MGAREG_BCOL 0x1c20 +#define MGAREG_FCOL 0x1c24 + +#define MGAREG_SRC0 0x1c30 +#define MGAREG_SRC1 0x1c34 +#define MGAREG_SRC2 0x1c38 +#define MGAREG_SRC3 0x1c3c + +#define MGAREG_XYSTRT 0x1c40 +#define MGAREG_XYEND 0x1c44 + +#define MGAREG_SHIFT 0x1c50 +/* the following is a mystique only register */ +#define MGAREG_DMAPAD 0x1c54 +#define MGAREG_SGN 0x1c58 +#define MGAREG_LEN 0x1c5c + +#define MGAREG_AR0 0x1c60 +#define MGAREG_AR1 0x1c64 +#define MGAREG_AR2 0x1c68 +#define MGAREG_AR3 0x1c6c +#define MGAREG_AR4 0x1c70 +#define MGAREG_AR5 0x1c74 +#define MGAREG_AR6 0x1c78 + +#define MGAREG_CXBNDRY 0x1c80 +#define MGAREG_FXBNDRY 0x1c84 +#define MGAREG_YDSTLEN 0x1c88 +#define MGAREG_PITCH 0x1c8c + +#define MGAREG_YDST 0x1c90 +#define MGAREG_YDSTORG 0x1c94 +#define MGAREG_YTOP 0x1c98 +#define MGAREG_YBOT 0x1c9c + +#define MGAREG_CXLEFT 0x1ca0 +#define MGAREG_CXRIGHT 0x1ca4 +#define MGAREG_FXLEFT 0x1ca8 +#define MGAREG_FXRIGHT 0x1cac + +#define MGAREG_XDST 0x1cb0 + +#define MGAREG_DR0 0x1cc0 +#define MGAREG_DR1 0x1cc4 +#define MGAREG_DR2 0x1cc8 +#define MGAREG_DR3 0x1ccc + +#define MGAREG_DR4 0x1cd0 +#define MGAREG_DR5 0x1cd4 +#define MGAREG_DR6 0x1cd8 +#define MGAREG_DR7 0x1cdc + +#define MGAREG_DR8 0x1ce0 +#define MGAREG_DR9 0x1ce4 +#define MGAREG_DR10 0x1ce8 +#define MGAREG_DR11 0x1cec + +#define MGAREG_DR12 0x1cf0 +#define MGAREG_DR13 0x1cf4 +#define MGAREG_DR14 0x1cf8 +#define MGAREG_DR15 0x1cfc + +#define MGAREG_SRCORG 0x2cb4 +#define MGAREG_DSTORG 0x2cb8 + +/* add or or this to one of the previous "power registers" to start + the drawing engine */ + +#define MGAREG_EXEC 0x0100 + +#define MGAREG_FIFOSTATUS 0x1e10 +#define MGAREG_STATUS 0x1e14 +#define MGAREG_ICLEAR 0x1e18 +#define MGAREG_IEN 0x1e1c + +#define MGAREG_VCOUNT 0x1e20 + +#define MGAREG_Reset 0x1e40 + +#define MGAREG_OPMODE 0x1e54 + +/* OPMODE register additives */ + +#define MGAOPM_DMA_GENERAL (0x00 << 2) +#define MGAOPM_DMA_BLIT (0x01 << 2) +#define MGAOPM_DMA_VECTOR (0x10 << 2) + +/* DWGCTL register additives */ + +/* Lines */ + +#define MGADWG_LINE_OPEN 0x00 +#define MGADWG_AUTOLINE_OPEN 0x01 +#define MGADWG_LINE_CLOSE 0x02 +#define MGADWG_AUTOLINE_CLOSE 0x03 + +/* Trapezoids */ +#define MGADWG_TRAP 0x04 +#define MGADWG_TEXTURE_TRAP 0x05 + +/* BitBlts */ + +#define MGADWG_BITBLT 0x08 +#define MGADWG_FBITBLT 0x0c +#define MGADWG_ILOAD 0x09 +#define MGADWG_ILOAD_SCALE 0x0d +#define MGADWG_ILOAD_FILTER 0x0f +#define MGADWG_IDUMP 0x0a + +/* atype access to WRAM */ + +#define MGADWG_RPL ( 0x00 << 4 ) +#define MGADWG_RSTR ( 0x01 << 4 ) +#define MGADWG_ZI ( 0x03 << 4 ) +#define MGADWG_BLK ( 0x04 << 4 ) +#define MGADWG_I ( 0x07 << 4 ) + +/* specifies whether bit blits are linear or xy */ +#define MGADWG_LINEAR ( 0x01 << 7 ) + +/* z drawing mode. use MGADWG_NOZCMP for always */ + +#define MGADWG_NOZCMP ( 0x00 << 8 ) +#define MGADWG_ZE ( 0x02 << 8 ) +#define MGADWG_ZNE ( 0x03 << 8 ) +#define MGADWG_ZLT ( 0x04 << 8 ) +#define MGADWG_ZLTE ( 0x05 << 8 ) +#define MGADWG_GT ( 0x06 << 8 ) +#define MGADWG_GTE ( 0x07 << 8 ) + +/* use this to force colour expansion circuitry to do its stuff */ + +#define MGADWG_SOLID ( 0x01 << 11 ) + +/* ar register at zero */ + +#define MGADWG_ARZERO ( 0x01 << 12 ) + +#define MGADWG_SGNZERO ( 0x01 << 13 ) + +#define MGADWG_SHIFTZERO ( 0x01 << 14 ) + +/* See table on 4-43 for bop ALU operations */ + +/* See table on 4-44 for translucidity masks */ + +#define MGADWG_BMONOLEF ( 0x00 << 25 ) +#define MGADWG_BMONOWF ( 0x04 << 25 ) +#define MGADWG_BPLAN ( 0x01 << 25 ) + +/* note that if bfcol is specified and you're doing a bitblt, it causes + a fbitblt to be performed, so check that you obey the fbitblt rules */ + +#define MGADWG_BFCOL ( 0x02 << 25 ) +#define MGADWG_BUYUV ( 0x0e << 25 ) +#define MGADWG_BU32BGR ( 0x03 << 25 ) +#define MGADWG_BU32RGB ( 0x07 << 25 ) +#define MGADWG_BU24BGR ( 0x0b << 25 ) +#define MGADWG_BU24RGB ( 0x0f << 25 ) + +#define MGADWG_REPLACE 0x000C0000 /* From Linux kernel sources */ +#define MGADWG_PATTERN ( 0x01 << 29 ) +#define MGADWG_TRANSC ( 0x01 << 30 ) +#define MGADWG_NOCLIP ( 0x01 << 31 ) +#define MGAREG_MISC_WRITE 0x3c2 +#define MGAREG_MISC_READ 0x3cc +#define MGAREG_MISC_IOADSEL (0x1 << 0) +#define MGAREG_MISC_RAMMAPEN (0x1 << 1) +#define MGAREG_MISC_CLK_SEL_VGA25 (0x0 << 2) +#define MGAREG_MISC_CLK_SEL_VGA28 (0x1 << 2) +#define MGAREG_MISC_CLK_SEL_MGA_PIX (0x2 << 2) +#define MGAREG_MISC_CLK_SEL_MGA_MSK (0x3 << 2) +#define MGAREG_MISC_VIDEO_DIS (0x1 << 4) +#define MGAREG_MISC_HIGH_PG_SEL (0x1 << 5) + +/* MMIO VGA registers */ +#define MGAREG_CRTC_INDEX 0x1fd4 +#define MGAREG_CRTC_DATA 0x1fd5 +#define MGAREG_CRTCEXT_INDEX 0x1fde +#define MGAREG_CRTCEXT_DATA 0x1fdf + + +/* MGA bits for registers PCI_OPTION_REG */ +#define MGA1064_OPT_SYS_CLK_PCI ( 0x00 << 0 ) +#define MGA1064_OPT_SYS_CLK_PLL ( 0x01 << 0 ) +#define MGA1064_OPT_SYS_CLK_EXT ( 0x02 << 0 ) +#define MGA1064_OPT_SYS_CLK_MSK ( 0x03 << 0 ) + +#define MGA1064_OPT_SYS_CLK_DIS ( 0x01 << 2 ) +#define MGA1064_OPT_G_CLK_DIV_1 ( 0x01 << 3 ) +#define MGA1064_OPT_M_CLK_DIV_1 ( 0x01 << 4 ) + +#define MGA1064_OPT_SYS_PLL_PDN ( 0x01 << 5 ) +#define MGA1064_OPT_VGA_ION ( 0x01 << 8 ) + +/* MGA registers in PCI config space */ +#define PCI_MGA_INDEX 0x44 +#define PCI_MGA_DATA 0x48 +#define PCI_MGA_OPTION2 0x50 +#define PCI_MGA_OPTION3 0x54 + +#define RAMDAC_OFFSET 0x3c00 + +/* TVP3026 direct registers */ + +#define TVP3026_INDEX 0x00 +#define TVP3026_WADR_PAL 0x00 +#define TVP3026_COL_PAL 0x01 +#define TVP3026_PIX_RD_MSK 0x02 +#define TVP3026_RADR_PAL 0x03 +#define TVP3026_CUR_COL_ADDR 0x04 +#define TVP3026_CUR_COL_DATA 0x05 +#define TVP3026_DATA 0x0a +#define TVP3026_CUR_RAM 0x0b +#define TVP3026_CUR_XLOW 0x0c +#define TVP3026_CUR_XHI 0x0d +#define TVP3026_CUR_YLOW 0x0e +#define TVP3026_CUR_YHI 0x0f + +/* TVP3026 indirect registers */ + +#define TVP3026_SILICON_REV 0x01 +#define TVP3026_CURSOR_CTL 0x06 +#define TVP3026_LATCH_CTL 0x0f +#define TVP3026_TRUE_COLOR_CTL 0x18 +#define TVP3026_MUX_CTL 0x19 +#define TVP3026_CLK_SEL 0x1a +#define TVP3026_PAL_PAGE 0x1c +#define TVP3026_GEN_CTL 0x1d +#define TVP3026_MISC_CTL 0x1e +#define TVP3026_GEN_IO_CTL 0x2a +#define TVP3026_GEN_IO_DATA 0x2b +#define TVP3026_PLL_ADDR 0x2c +#define TVP3026_PIX_CLK_DATA 0x2d +#define TVP3026_MEM_CLK_DATA 0x2e +#define TVP3026_LOAD_CLK_DATA 0x2f +#define TVP3026_KEY_RED_LOW 0x32 +#define TVP3026_KEY_RED_HI 0x33 +#define TVP3026_KEY_GREEN_LOW 0x34 +#define TVP3026_KEY_GREEN_HI 0x35 +#define TVP3026_KEY_BLUE_LOW 0x36 +#define TVP3026_KEY_BLUE_HI 0x37 +#define TVP3026_KEY_CTL 0x38 +#define TVP3026_MCLK_CTL 0x39 +#define TVP3026_SENSE_TEST 0x3a +#define TVP3026_TEST_DATA 0x3b +#define TVP3026_CRC_LSB 0x3c +#define TVP3026_CRC_MSB 0x3d +#define TVP3026_CRC_CTL 0x3e +#define TVP3026_ID 0x3f +#define TVP3026_RESET 0xff + + +/* MGA1064 DAC Register file */ +/* MGA1064 direct registers */ + +#define MGA1064_INDEX 0x00 +#define MGA1064_WADR_PAL 0x00 +#define MGA1064_COL_PAL 0x01 +#define MGA1064_PIX_RD_MSK 0x02 +#define MGA1064_RADR_PAL 0x03 +#define MGA1064_DATA 0x0a + +#define MGA1064_CUR_XLOW 0x0c +#define MGA1064_CUR_XHI 0x0d +#define MGA1064_CUR_YLOW 0x0e +#define MGA1064_CUR_YHI 0x0f + +/* MGA1064 indirect registers */ +#define MGA1064_CURSOR_BASE_ADR_LOW 0x04 +#define MGA1064_CURSOR_BASE_ADR_HI 0x05 +#define MGA1064_CURSOR_CTL 0x06 +#define MGA1064_CURSOR_COL0_RED 0x08 +#define MGA1064_CURSOR_COL0_GREEN 0x09 +#define MGA1064_CURSOR_COL0_BLUE 0x0a + +#define MGA1064_CURSOR_COL1_RED 0x0c +#define MGA1064_CURSOR_COL1_GREEN 0x0d +#define MGA1064_CURSOR_COL1_BLUE 0x0e + +#define MGA1064_CURSOR_COL2_RED 0x010 +#define MGA1064_CURSOR_COL2_GREEN 0x011 +#define MGA1064_CURSOR_COL2_BLUE 0x012 + +#define MGA1064_VREF_CTL 0x018 + +#define MGA1064_MUL_CTL 0x19 +#define MGA1064_MUL_CTL_8bits 0x0 +#define MGA1064_MUL_CTL_15bits 0x01 +#define MGA1064_MUL_CTL_16bits 0x02 +#define MGA1064_MUL_CTL_24bits 0x03 +#define MGA1064_MUL_CTL_32bits 0x04 +#define MGA1064_MUL_CTL_2G8V16bits 0x05 +#define MGA1064_MUL_CTL_G16V16bits 0x06 +#define MGA1064_MUL_CTL_32_24bits 0x07 + +#define MGAGDAC_XVREFCTRL 0x18 +#define MGA1064_PIX_CLK_CTL 0x1a +#define MGA1064_PIX_CLK_CTL_CLK_DIS ( 0x01 << 2 ) +#define MGA1064_PIX_CLK_CTL_CLK_POW_DOWN ( 0x01 << 3 ) +#define MGA1064_PIX_CLK_CTL_SEL_PCI ( 0x00 << 0 ) +#define MGA1064_PIX_CLK_CTL_SEL_PLL ( 0x01 << 0 ) +#define MGA1064_PIX_CLK_CTL_SEL_EXT ( 0x02 << 0 ) +#define MGA1064_PIX_CLK_CTL_SEL_MSK ( 0x03 << 0 ) + +#define MGA1064_GEN_CTL 0x1d +#define MGA1064_MISC_CTL 0x1e +#define MGA1064_MISC_CTL_DAC_POW_DN ( 0x01 << 0 ) +#define MGA1064_MISC_CTL_VGA ( 0x01 << 1 ) +#define MGA1064_MISC_CTL_DIS_CON ( 0x03 << 1 ) +#define MGA1064_MISC_CTL_MAFC ( 0x02 << 1 ) +#define MGA1064_MISC_CTL_VGA8 ( 0x01 << 3 ) +#define MGA1064_MISC_CTL_DAC_RAM_CS ( 0x01 << 4 ) + +#define MGA1064_GEN_IO_CTL 0x2a +#define MGA1064_GEN_IO_DATA 0x2b +#define MGA1064_SYS_PLL_M 0x2c +#define MGA1064_SYS_PLL_N 0x2d +#define MGA1064_SYS_PLL_P 0x2e +#define MGA1064_SYS_PLL_STAT 0x2f +#define MGA1064_ZOOM_CTL 0x38 +#define MGA1064_SENSE_TST 0x3a + +#define MGA1064_CRC_LSB 0x3c +#define MGA1064_CRC_MSB 0x3d +#define MGA1064_CRC_CTL 0x3e +#define MGA1064_COL_KEY_MSK_LSB 0x40 +#define MGA1064_COL_KEY_MSK_MSB 0x41 +#define MGA1064_COL_KEY_LSB 0x42 +#define MGA1064_COL_KEY_MSB 0x43 +#define MGA1064_PIX_PLLA_M 0x44 +#define MGA1064_PIX_PLLA_N 0x45 +#define MGA1064_PIX_PLLA_P 0x46 +#define MGA1064_PIX_PLLB_M 0x48 +#define MGA1064_PIX_PLLB_N 0x49 +#define MGA1064_PIX_PLLB_P 0x4a +#define MGA1064_PIX_PLLC_M 0x4c +#define MGA1064_PIX_PLLC_N 0x4d +#define MGA1064_PIX_PLLC_P 0x4e + +#define MGA1064_PIX_PLL_STAT 0x4f + +#endif + diff --git a/3rdparty/SDL/src/video/fbcon/riva_mmio.h b/3rdparty/SDL/src/video/fbcon/riva_mmio.h new file mode 100644 index 0000000..e926167 --- /dev/null +++ b/3rdparty/SDL/src/video/fbcon/riva_mmio.h @@ -0,0 +1,449 @@ +/***************************************************************************\ +|* *| +|* Copyright 1993-1999 NVIDIA, Corporation. All rights reserved. *| +|* *| +|* NOTICE TO USER: The source code is copyrighted under U.S. and *| +|* international laws. Users and possessors of this source code are *| +|* hereby granted a nonexclusive, royalty-free copyright license to *| +|* use this code in individual and commercial software. *| +|* *| +|* Any use of this source code must include, in the user documenta- *| +|* tion and internal comments to the code, notices to the end user *| +|* as follows: *| +|* *| +|* Copyright 1993-1999 NVIDIA, Corporation. All rights reserved. *| +|* *| +|* NVIDIA, CORPORATION MAKES NO REPRESENTATION ABOUT THE SUITABILITY *| +|* OF THIS SOURCE CODE FOR ANY PURPOSE. IT IS PROVIDED "AS IS" *| +|* WITHOUT EXPRESS OR IMPLIED WARRANTY OF ANY KIND. NVIDIA, CORPOR- *| +|* ATION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOURCE CODE, *| +|* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGE- *| +|* MENT, AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL *| +|* NVIDIA, CORPORATION BE LIABLE FOR ANY SPECIAL, INDIRECT, INCI- *| +|* DENTAL, OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RE- *| +|* SULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION *| +|* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF *| +|* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOURCE CODE. *| +|* *| +|* U.S. Government End Users. This source code is a "commercial *| +|* item," as that term is defined at 48 C.F.R. 2.101 (OCT 1995), *| +|* consisting of "commercial computer software" and "commercial *| +|* computer software documentation," as such terms are used in *| +|* 48 C.F.R. 12.212 (SEPT 1995) and is provided to the U.S. Govern- *| +|* ment only as a commercial end item. Consistent with 48 C.F.R. *| +|* 12.212 and 48 C.F.R. 227.7202-1 through 227.7202-4 (JUNE 1995), *| +|* all U.S. Government End Users acquire the source code with only *| +|* those rights set forth herein. *| +|* *| +\***************************************************************************/ + +#ifndef __RIVA_HW_H__ +#define __RIVA_HW_H__ +#define RIVA_SW_VERSION 0x00010003 + +/* + * Typedefs to force certain sized values. + */ +typedef Uint8 U008; +typedef Uint16 U016; +typedef Uint32 U032; + +/* + * HW access macros. + */ +#define NV_WR08(p,i,d) (((U008 *)(p))[i]=(d)) +#define NV_RD08(p,i) (((U008 *)(p))[i]) +#define NV_WR16(p,i,d) (((U016 *)(p))[(i)/2]=(d)) +#define NV_RD16(p,i) (((U016 *)(p))[(i)/2]) +#define NV_WR32(p,i,d) (((U032 *)(p))[(i)/4]=(d)) +#define NV_RD32(p,i) (((U032 *)(p))[(i)/4]) +#define VGA_WR08(p,i,d) NV_WR08(p,i,d) +#define VGA_RD08(p,i) NV_RD08(p,i) + +/* + * Define supported architectures. + */ +#define NV_ARCH_03 0x03 +#define NV_ARCH_04 0x04 +#define NV_ARCH_10 0x10 +/***************************************************************************\ +* * +* FIFO registers. * +* * +\***************************************************************************/ + +/* + * Raster OPeration. Windows style ROP3. + */ +typedef volatile struct +{ + U032 reserved00[4]; + U016 FifoFree; + U016 Nop; + U032 reserved01[0x0BB]; + U032 Rop3; +} RivaRop; +/* + * 8X8 Monochrome pattern. + */ +typedef volatile struct +{ + U032 reserved00[4]; + U016 FifoFree; + U016 Nop; + U032 reserved01[0x0BD]; + U032 Shape; + U032 reserved03[0x001]; + U032 Color0; + U032 Color1; + U032 Monochrome[2]; +} RivaPattern; +/* + * Scissor clip rectangle. + */ +typedef volatile struct +{ + U032 reserved00[4]; + U016 FifoFree; + U016 Nop; + U032 reserved01[0x0BB]; + U032 TopLeft; + U032 WidthHeight; +} RivaClip; +/* + * 2D filled rectangle. + */ +typedef volatile struct +{ + U032 reserved00[4]; + U016 FifoFree; + U016 Nop[1]; + U032 reserved01[0x0BC]; + U032 Color; + U032 reserved03[0x03E]; + U032 TopLeft; + U032 WidthHeight; +} RivaRectangle; +/* + * 2D screen-screen BLT. + */ +typedef volatile struct +{ + U032 reserved00[4]; + U016 FifoFree; + U016 Nop; + U032 reserved01[0x0BB]; + U032 TopLeftSrc; + U032 TopLeftDst; + U032 WidthHeight; +} RivaScreenBlt; +/* + * 2D pixel BLT. + */ +typedef volatile struct +{ + U032 reserved00[4]; + U016 FifoFree; + U016 Nop[1]; + U032 reserved01[0x0BC]; + U032 TopLeft; + U032 WidthHeight; + U032 WidthHeightIn; + U032 reserved02[0x03C]; + U032 Pixels; +} RivaPixmap; +/* + * Filled rectangle combined with monochrome expand. Useful for glyphs. + */ +typedef volatile struct +{ + U032 reserved00[4]; + U016 FifoFree; + U016 Nop; + U032 reserved01[0x0BB]; + U032 reserved03[(0x040)-1]; + U032 Color1A; + struct + { + U032 TopLeft; + U032 WidthHeight; + } UnclippedRectangle[64]; + U032 reserved04[(0x080)-3]; + struct + { + U032 TopLeft; + U032 BottomRight; + } ClipB; + U032 Color1B; + struct + { + U032 TopLeft; + U032 BottomRight; + } ClippedRectangle[64]; + U032 reserved05[(0x080)-5]; + struct + { + U032 TopLeft; + U032 BottomRight; + } ClipC; + U032 Color1C; + U032 WidthHeightC; + U032 PointC; + U032 MonochromeData1C; + U032 reserved06[(0x080)+121]; + struct + { + U032 TopLeft; + U032 BottomRight; + } ClipD; + U032 Color1D; + U032 WidthHeightInD; + U032 WidthHeightOutD; + U032 PointD; + U032 MonochromeData1D; + U032 reserved07[(0x080)+120]; + struct + { + U032 TopLeft; + U032 BottomRight; + } ClipE; + U032 Color0E; + U032 Color1E; + U032 WidthHeightInE; + U032 WidthHeightOutE; + U032 PointE; + U032 MonochromeData01E; +} RivaBitmap; +/* + * 3D textured, Z buffered triangle. + */ +typedef volatile struct +{ + U032 reserved00[4]; + U016 FifoFree; + U016 Nop; + U032 reserved01[0x0BC]; + U032 TextureOffset; + U032 TextureFormat; + U032 TextureFilter; + U032 FogColor; +/* This is a problem on LynxOS */ +#ifdef Control +#undef Control +#endif + U032 Control; + U032 AlphaTest; + U032 reserved02[0x339]; + U032 FogAndIndex; + U032 Color; + float ScreenX; + float ScreenY; + float ScreenZ; + float EyeM; + float TextureS; + float TextureT; +} RivaTexturedTriangle03; +typedef volatile struct +{ + U032 reserved00[4]; + U016 FifoFree; + U016 Nop; + U032 reserved01[0x0BB]; + U032 ColorKey; + U032 TextureOffset; + U032 TextureFormat; + U032 TextureFilter; + U032 Blend; +/* This is a problem on LynxOS */ +#ifdef Control +#undef Control +#endif + U032 Control; + U032 FogColor; + U032 reserved02[0x39]; + struct + { + float ScreenX; + float ScreenY; + float ScreenZ; + float EyeM; + U032 Color; + U032 Specular; + float TextureS; + float TextureT; + } Vertex[16]; + U032 DrawTriangle3D; +} RivaTexturedTriangle05; +/* + * 2D line. + */ +typedef volatile struct +{ + U032 reserved00[4]; + U016 FifoFree; + U016 Nop[1]; + U032 reserved01[0x0BC]; + U032 Color; /* source color 0304-0307*/ + U032 Reserved02[0x03e]; + struct { /* start aliased methods in array 0400- */ + U032 point0; /* y_x S16_S16 in pixels 0- 3*/ + U032 point1; /* y_x S16_S16 in pixels 4- 7*/ + } Lin[16]; /* end of aliased methods in array -047f*/ + struct { /* start aliased methods in array 0480- */ + U032 point0X; /* in pixels, 0 at left 0- 3*/ + U032 point0Y; /* in pixels, 0 at top 4- 7*/ + U032 point1X; /* in pixels, 0 at left 8- b*/ + U032 point1Y; /* in pixels, 0 at top c- f*/ + } Lin32[8]; /* end of aliased methods in array -04ff*/ + U032 PolyLin[32]; /* y_x S16_S16 in pixels 0500-057f*/ + struct { /* start aliased methods in array 0580- */ + U032 x; /* in pixels, 0 at left 0- 3*/ + U032 y; /* in pixels, 0 at top 4- 7*/ + } PolyLin32[16]; /* end of aliased methods in array -05ff*/ + struct { /* start aliased methods in array 0600- */ + U032 color; /* source color 0- 3*/ + U032 point; /* y_x S16_S16 in pixels 4- 7*/ + } ColorPolyLin[16]; /* end of aliased methods in array -067f*/ +} RivaLine; +/* + * 2D/3D surfaces + */ +typedef volatile struct +{ + U032 reserved00[4]; + U016 FifoFree; + U016 Nop; + U032 reserved01[0x0BE]; + U032 Offset; +} RivaSurface; +typedef volatile struct +{ + U032 reserved00[4]; + U016 FifoFree; + U016 Nop; + U032 reserved01[0x0BD]; + U032 Pitch; + U032 RenderBufferOffset; + U032 ZBufferOffset; +} RivaSurface3D; + +/***************************************************************************\ +* * +* Virtualized RIVA H/W interface. * +* * +\***************************************************************************/ + +struct _riva_hw_inst; +struct _riva_hw_state; +/* + * Virtialized chip interface. Makes RIVA 128 and TNT look alike. + */ +typedef struct _riva_hw_inst +{ + /* + * Chip specific settings. + */ + U032 Architecture; + U032 Version; + U032 CrystalFreqKHz; + U032 RamAmountKBytes; + U032 MaxVClockFreqKHz; + U032 RamBandwidthKBytesPerSec; + U032 EnableIRQ; + U032 IO; + U032 VBlankBit; + U032 FifoFreeCount; + U032 FifoEmptyCount; + /* + * Non-FIFO registers. + */ + volatile U032 *PCRTC; + volatile U032 *PRAMDAC; + volatile U032 *PFB; + volatile U032 *PFIFO; + volatile U032 *PGRAPH; + volatile U032 *PEXTDEV; + volatile U032 *PTIMER; + volatile U032 *PMC; + volatile U032 *PRAMIN; + volatile U032 *FIFO; + volatile U032 *CURSOR; + volatile U032 *CURSORPOS; + volatile U032 *VBLANKENABLE; + volatile U032 *VBLANK; + volatile U008 *PCIO; + volatile U008 *PVIO; + volatile U008 *PDIO; + /* + * Common chip functions. + */ + int (*Busy)(struct _riva_hw_inst *); + void (*CalcStateExt)(struct _riva_hw_inst *,struct _riva_hw_state *,int,int,int,int,int,int,int,int,int,int,int,int,int); + void (*LoadStateExt)(struct _riva_hw_inst *,struct _riva_hw_state *); + void (*UnloadStateExt)(struct _riva_hw_inst *,struct _riva_hw_state *); + void (*SetStartAddress)(struct _riva_hw_inst *,U032); + void (*SetSurfaces2D)(struct _riva_hw_inst *,U032,U032); + void (*SetSurfaces3D)(struct _riva_hw_inst *,U032,U032); + int (*ShowHideCursor)(struct _riva_hw_inst *,int); + void (*LockUnlock)(struct _riva_hw_inst *, int); + /* + * Current extended mode settings. + */ + struct _riva_hw_state *CurrentState; + /* + * FIFO registers. + */ + RivaRop *Rop; + RivaPattern *Patt; + RivaClip *Clip; + RivaPixmap *Pixmap; + RivaScreenBlt *Blt; + RivaBitmap *Bitmap; + RivaLine *Line; + RivaTexturedTriangle03 *Tri03; + RivaTexturedTriangle05 *Tri05; +} RIVA_HW_INST; +/* + * Extended mode state information. + */ +typedef struct _riva_hw_state +{ + U032 bpp; + U032 width; + U032 height; + U032 repaint0; + U032 repaint1; + U032 screen; + U032 pixel; + U032 horiz; + U032 arbitration0; + U032 arbitration1; + U032 vpll; + U032 pllsel; + U032 general; + U032 config; + U032 cursor0; + U032 cursor1; + U032 cursor2; + U032 offset0; + U032 offset1; + U032 offset2; + U032 offset3; + U032 pitch0; + U032 pitch1; + U032 pitch2; + U032 pitch3; +} RIVA_HW_STATE; + +/* + * FIFO Free Count. Should attempt to yield processor if RIVA is busy. + */ + +#define RIVA_FIFO_FREE(hwptr,cnt) \ +{ \ + while (FifoFreeCount < (cnt)) \ + FifoFreeCount = hwptr->FifoFree >> 2; \ + FifoFreeCount -= (cnt); \ +} +#endif /* __RIVA_HW_H__ */ + diff --git a/3rdparty/SDL/src/video/fbcon/riva_regs.h b/3rdparty/SDL/src/video/fbcon/riva_regs.h new file mode 100644 index 0000000..5324562 --- /dev/null +++ b/3rdparty/SDL/src/video/fbcon/riva_regs.h @@ -0,0 +1,43 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#ifndef _RIVA_REGS_H +#define _RIVA_REGS_H + +/* This information comes from the XFree86 NVidia hardware driver */ + +/* mapped_io register offsets */ +#define PGRAPH_OFFSET 0x00400000 +#define FIFO_OFFSET 0x00800000 +#define ROP_OFFSET FIFO_OFFSET+0x00000000 +#define CLIP_OFFSET FIFO_OFFSET+0x00002000 +#define PATT_OFFSET FIFO_OFFSET+0x00004000 +#define PIXMAP_OFFSET FIFO_OFFSET+0x00006000 +#define BLT_OFFSET FIFO_OFFSET+0x00008000 +#define BITMAP_OFFSET FIFO_OFFSET+0x0000A000 +#define LINE_OFFSET FIFO_OFFSET+0x0000C000 +#define TRI03_OFFSET FIFO_OFFSET+0x0000E000 +#define PCIO_OFFSET 0x00601000 + +#endif /* _RIVA_REGS_H */ + diff --git a/3rdparty/SDL/src/video/gapi/SDL_gapivideo.c b/3rdparty/SDL/src/video/gapi/SDL_gapivideo.c new file mode 100644 index 0000000..86deadc --- /dev/null +++ b/3rdparty/SDL/src/video/gapi/SDL_gapivideo.c @@ -0,0 +1,1287 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* Pocket PC GAPI SDL video driver implementation; +Implemented by Dmitry Yakimov - support@activekitten.com +Inspired by http://arisme.free.fr/ports/SDL.php +*/ + +// TODO: copy surface on window when lost focus +// TODO: test buttons rotation +// TODO: test on be300 and HPC ( check WinDib fullscreen keys catching ) +// TODO: test on smartphones +// TODO: windib on SH3 PPC2000 landscape test +// TODO: optimize 8bpp landscape mode + +// there is some problems in runnings apps from a device landscape mode +// due to WinCE bugs. Some works and some - does not. +// TODO: finish Axim Dell X30 and user landscape mode, device landscape mode +// TODO: finish Axim Dell X30 user portrait, device landscape stylus conversion +// TODO: fix running GAPI apps from landscape mode - +// wince goes to portrait mode, but does not update video memory + + +#include "SDL.h" +#include "SDL_error.h" +#include "SDL_video.h" +#include "SDL_mouse.h" +#include "../SDL_sysvideo.h" +#include "../SDL_pixels_c.h" +#include "../../events/SDL_events_c.h" +#include "../wincommon/SDL_syswm_c.h" +#include "../wincommon/SDL_sysmouse_c.h" +#include "../windib/SDL_dibevents_c.h" + +#include "../windib/SDL_gapidibvideo.h" +#include "SDL_gapivideo.h" + +#define gapi this->hidden->gapiInfo + +#define GAPIVID_DRIVER_NAME "gapi" + +#if defined(DEBUG) || defined (_DEBUG) || defined(NDEBUG) +#define REPORT_VIDEO_INFO 1 +#else +#define REPORT_VIDEO_INFO 0 +#endif + +// for testing with GapiEmu +#define USE_GAPI_EMU 0 +#define EMULATE_AXIM_X30 0 +#define WITHOUT_GAPI 0 + +#if USE_GAPI_EMU && !REPORT_VIDEO_INFO +#pragma message("Warning: Using GapiEmu in release build. I assume you'd like to set USE_GAPI_EMU to zero.") +#endif + +#ifndef _T +#define _T(x) L##x +#endif + +#ifndef ASSERT +#define ASSERT(x) +#endif + +// defined and used in SDL_sysevents.c +extern HINSTANCE aygshell; +extern void SDL_UnregisterApp(); +extern int DIB_AddMode(_THIS, int bpp, int w, int h); + +/* Initialization/Query functions */ +static int GAPI_VideoInit(_THIS, SDL_PixelFormat *vformat); +static SDL_Rect **GAPI_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags); +static SDL_Surface *GAPI_SetVideoMode(_THIS, SDL_Surface *current, int width, int height, int bpp, Uint32 flags); +static int GAPI_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors); +static void GAPI_VideoQuit(_THIS); + +/* Hardware surface functions */ +static int GAPI_AllocHWSurface(_THIS, SDL_Surface *surface); +static int GAPI_LockHWSurface(_THIS, SDL_Surface *surface); +static void GAPI_UnlockHWSurface(_THIS, SDL_Surface *surface); +static void GAPI_FreeHWSurface(_THIS, SDL_Surface *surface); + +/* Windows message handling functions, will not be processed */ +static void GAPI_Activate(_THIS, BOOL active, BOOL minimized); +static void GAPI_RealizePalette(_THIS); +static void GAPI_PaletteChanged(_THIS, HWND window); +static void GAPI_WinPAINT(_THIS, HDC hdc); + +/* etc. */ +static void GAPI_UpdateRects(_THIS, int numrects, SDL_Rect *rects); + +static HMODULE g_hGapiLib = 0; +#define LINK(type,name,import) \ + if( g_hGapiLib ) \ + name = (PFN##type)GetProcAddress( g_hGapiLib, _T(import) ); + +static char g_bRawBufferAvailable = 0; + +/* GAPI driver bootstrap functions */ + +/* hi res definitions */ +typedef struct _RawFrameBufferInfo +{ + WORD wFormat; + WORD wBPP; + VOID *pFramePointer; + int cxStride; + int cyStride; + int cxPixels; + int cyPixels; +} RawFrameBufferInfo; + +static struct _RawFrameBufferInfo g_RawFrameBufferInfo = {0}; + +#define GETRAWFRAMEBUFFER 0x00020001 + +#define FORMAT_565 1 +#define FORMAT_555 2 +#define FORMAT_OTHER 3 + +/* Dell Axim x30 hangs when we use GAPI from landscape, + so lets avoid using GxOpenDisplay there via GETGXINFO trick + It seems that GAPI subsystem use the same ExtEscape code. +*/ +#define GETGXINFO 0x00020000 + +typedef struct GXDeviceInfo +{ +long Version; //00 (should filled with 100 before calling ExtEscape) +void * pvFrameBuffer; //04 +unsigned long cbStride; //08 +unsigned long cxWidth; //0c +unsigned long cyHeight; //10 +unsigned long cBPP; //14 +unsigned long ffFormat; //18 +char Unused[0x84-7*4]; +} GXDeviceInfo; + +static int GAPI_Available(void) +{ + // try to use VGA display, even on emulator + HDC hdc = GetDC(NULL); + int result = ExtEscape(hdc, GETRAWFRAMEBUFFER, 0, NULL, sizeof(RawFrameBufferInfo), (char *)&g_RawFrameBufferInfo); + ReleaseDC(NULL, hdc); + g_bRawBufferAvailable = result > 0; + + //My Asus MyPAL 696 reports the RAWFRAMEBUFFER as available, but with a size of 0 x 0 + if(g_RawFrameBufferInfo.cxPixels <= 0 || g_RawFrameBufferInfo.cyPixels <= 0){ + g_bRawBufferAvailable = 0; + } + +#if WITHOUT_GAPI + return g_bRawBufferAvailable; +#endif + +#if USE_GAPI_EMU + g_hGapiLib = LoadLibrary(_T("GAPI_Emu.dll")); + if( !g_hGapiLib ) + { + SDL_SetError("Gapi Emu not found!"); + } + return g_hGapiLib != 0; +#endif + + // try to find gx.dll + g_hGapiLib = LoadLibrary(_T("\\Windows\\gx.dll")); + if( !g_hGapiLib ) + { + g_hGapiLib = LoadLibrary(_T("gx.dll")); + if( !g_hGapiLib ) return g_bRawBufferAvailable; + } + + return(1); +} + +static int cmpmodes(const void *va, const void *vb) +{ + SDL_Rect *a = *(SDL_Rect **)va; + SDL_Rect *b = *(SDL_Rect **)vb; + if ( a->w == b->w ) + return b->h - a->h; + else + return b->w - a->w; +} + +static int GAPI_AddMode(_THIS, int bpp, int w, int h) +{ + SDL_Rect *mode; + int i, index; + int next_mode; + + /* Check to see if we already have this mode */ + if ( bpp < 8 ) { /* Not supported */ + return(0); + } + index = ((bpp+7)/8)-1; + for ( i=0; i<gapi->SDL_nummodes[index]; ++i ) { + mode = gapi->SDL_modelist[index][i]; + if ( (mode->w == w) && (mode->h == h) ) { + return(0); + } + } + + /* Set up the new video mode rectangle */ + mode = (SDL_Rect *)SDL_malloc(sizeof *mode); + if ( mode == NULL ) { + SDL_OutOfMemory(); + return(-1); + } + mode->x = 0; + mode->y = 0; + mode->w = w; + mode->h = h; + + /* Allocate the new list of modes, and fill in the new mode */ + next_mode = gapi->SDL_nummodes[index]; + gapi->SDL_modelist[index] = (SDL_Rect **) + SDL_realloc(gapi->SDL_modelist[index], (1+next_mode+1)*sizeof(SDL_Rect *)); + if ( gapi->SDL_modelist[index] == NULL ) { + SDL_OutOfMemory(); + gapi->SDL_nummodes[index] = 0; + SDL_free(mode); + return(-1); + } + gapi->SDL_modelist[index][next_mode] = mode; + gapi->SDL_modelist[index][next_mode+1] = NULL; + gapi->SDL_nummodes[index]++; + + return(0); +} + +static void GAPI_DeleteDevice(SDL_VideoDevice *device) +{ + if( g_hGapiLib ) + { + FreeLibrary(g_hGapiLib); + g_hGapiLib = 0; + } + SDL_free(device->hidden->gapiInfo); + SDL_free(device->hidden); + SDL_free(device); +} + +static SDL_VideoDevice *GAPI_CreateDevice(int devindex) +{ + SDL_VideoDevice *device; + + if( !g_hGapiLib && !g_bRawBufferAvailable) + { + if( !GAPI_Available() ) + { + SDL_SetError("GAPI dll is not found and VGA mode is not available!"); + return 0; + } + } + + /* Initialize all variables that we clean on shutdown */ + device = (SDL_VideoDevice *)SDL_malloc(sizeof(SDL_VideoDevice)); + if ( device ) { + SDL_memset(device, 0, (sizeof *device)); + device->hidden = (struct SDL_PrivateVideoData *) + SDL_malloc((sizeof *device->hidden)); + if(device->hidden){ + SDL_memset(device->hidden, 0, (sizeof *device->hidden)); + device->hidden->gapiInfo = (GapiInfo *)SDL_malloc((sizeof(GapiInfo))); + if(device->hidden->gapiInfo == NULL) + { + SDL_free(device->hidden); + device->hidden = NULL; + } + } + } + if ( (device == NULL) || (device->hidden == NULL) ) { + SDL_OutOfMemory(); + if ( device ) { + SDL_free(device); + } + return(0); + } + SDL_memset(device->hidden->gapiInfo, 0, (sizeof *device->hidden->gapiInfo)); + + /* Set the function pointers */ + device->VideoInit = GAPI_VideoInit; + device->ListModes = GAPI_ListModes; + device->SetVideoMode = GAPI_SetVideoMode; + device->UpdateMouse = WIN_UpdateMouse; + device->CreateYUVOverlay = NULL; + device->SetColors = GAPI_SetColors; + device->UpdateRects = GAPI_UpdateRects; + device->VideoQuit = GAPI_VideoQuit; + device->AllocHWSurface = GAPI_AllocHWSurface; + device->CheckHWBlit = NULL; + device->FillHWRect = NULL; + device->SetHWColorKey = NULL; + device->SetHWAlpha = NULL; + device->LockHWSurface = GAPI_LockHWSurface; + device->UnlockHWSurface = GAPI_UnlockHWSurface; + device->FlipHWSurface = NULL; + device->FreeHWSurface = GAPI_FreeHWSurface; + device->SetCaption = WIN_SetWMCaption; + device->SetIcon = WIN_SetWMIcon; + device->IconifyWindow = WIN_IconifyWindow; + device->GrabInput = WIN_GrabInput; + device->GetWMInfo = WIN_GetWMInfo; + device->FreeWMCursor = WIN_FreeWMCursor; + device->CreateWMCursor = WIN_CreateWMCursor; + device->ShowWMCursor = WIN_ShowWMCursor; + device->WarpWMCursor = WIN_WarpWMCursor; + device->CheckMouseMode = WIN_CheckMouseMode; + device->InitOSKeymap = DIB_InitOSKeymap; + device->PumpEvents = DIB_PumpEvents; + + /* Set up the windows message handling functions */ + WIN_Activate = GAPI_Activate; + WIN_RealizePalette = GAPI_RealizePalette; + WIN_PaletteChanged = GAPI_PaletteChanged; + WIN_WinPAINT = GAPI_WinPAINT; + HandleMessage = DIB_HandleMessage; + + device->free = GAPI_DeleteDevice; + + /* Load gapi library */ +#define gx device->hidden->gapiInfo->gxFunc + + LINK( GXOpenDisplay, gx.GXOpenDisplay, "?GXOpenDisplay@@YAHPAUHWND__@@K@Z" ) + LINK( GXCloseDisplay, gx.GXCloseDisplay, "?GXCloseDisplay@@YAHXZ" ) + LINK( GXBeginDraw, gx.GXBeginDraw, "?GXBeginDraw@@YAPAXXZ" ) + LINK( GXEndDraw, gx.GXEndDraw, "?GXEndDraw@@YAHXZ" ) + LINK( GXOpenInput, gx.GXOpenInput, "?GXOpenInput@@YAHXZ" ) + LINK( GXCloseInput, gx.GXCloseInput, "?GXCloseInput@@YAHXZ" ) + LINK( GXGetDisplayProperties, gx.GXGetDisplayProperties,"?GXGetDisplayProperties@@YA?AUGXDisplayProperties@@XZ" ) + LINK( GXGetDefaultKeys, gx.GXGetDefaultKeys, "?GXGetDefaultKeys@@YA?AUGXKeyList@@H@Z" ) + LINK( GXSuspend, gx.GXSuspend, "?GXSuspend@@YAHXZ" ) + LINK( GXResume, gx.GXResume, "?GXResume@@YAHXZ" ) + LINK( GXSetViewport, gx.GXSetViewport, "?GXSetViewport@@YAHKKKK@Z" ) + LINK( GXIsDisplayDRAMBuffer, gx.GXIsDisplayDRAMBuffer, "?GXIsDisplayDRAMBuffer@@YAHXZ" ) + + /* wrong gapi.dll */ + if( !gx.GXOpenDisplay ) + { + if( g_hGapiLib ) + { + FreeLibrary(g_hGapiLib); + g_hGapiLib = 0; + } + } + + if( !gx.GXOpenDisplay && !g_bRawBufferAvailable) + { + SDL_SetError("Error: damaged or unknown gapi.dll!\n"); + GAPI_DeleteDevice(device); + return 0; + } + + return device; +} + +VideoBootStrap GAPI_bootstrap = { + GAPIVID_DRIVER_NAME, "WinCE GAPI video driver", + GAPI_Available, GAPI_CreateDevice +}; + +static void FillStructs(_THIS, BOOL useVga) +{ +#ifdef _ARM_ + WCHAR oemstr[100]; +#endif + /* fill a device properties */ + + if( !useVga ) + { + gapi->gxProperties = gapi->gxFunc.GXGetDisplayProperties(); + gapi->needUpdate = 1; + gapi->hiresFix = 0; + gapi->useVga = 0; + gapi->useGXOpenDisplay = 1; + +#ifdef _ARM_ + /* check some devices and extract addition info */ + SystemParametersInfo( SPI_GETOEMINFO, sizeof( oemstr ), oemstr, 0 ); + + // buggy iPaq38xx + if ((oemstr[12] == 'H') && (oemstr[13] == '3') && (oemstr[14] == '8') && (gapi->gxProperties.cbxPitch > 0)) + { + gapi->videoMem = (PIXEL*)0xac0755a0; + gapi->gxProperties.cbxPitch = -640; + gapi->gxProperties.cbyPitch = 2; + gapi->needUpdate = 0; + } +#if (EMULATE_AXIM_X30 == 0) + // buggy Dell Axim X30 + if( _tcsncmp(oemstr, L"Dell Axim X30", 13) == 0 ) +#endif + { + GXDeviceInfo gxInfo = {0}; + HDC hdc = GetDC(NULL); + int result; + + gxInfo.Version = 100; + result = ExtEscape(hdc, GETGXINFO, 0, NULL, sizeof(gxInfo), (char *)&gxInfo); + if( result > 0 ) + { + gapi->useGXOpenDisplay = 0; + gapi->videoMem = gxInfo.pvFrameBuffer; + gapi->needUpdate = 0; + gapi->gxProperties.cbxPitch = 2; + gapi->gxProperties.cbyPitch = 480; + gapi->gxProperties.cxWidth = gxInfo.cxWidth; + gapi->gxProperties.cyHeight = gxInfo.cyHeight; + gapi->gxProperties.ffFormat = gxInfo.ffFormat; + } + } +#endif + } else + { + gapi->needUpdate = 0; + gapi->hiresFix = 0; + gapi->gxProperties.cBPP = g_RawFrameBufferInfo.wBPP; + gapi->gxProperties.cbxPitch = g_RawFrameBufferInfo.cxStride; + gapi->gxProperties.cbyPitch = g_RawFrameBufferInfo.cyStride; + gapi->gxProperties.cxWidth = g_RawFrameBufferInfo.cxPixels; + gapi->gxProperties.cyHeight = g_RawFrameBufferInfo.cyPixels; + gapi->videoMem = g_RawFrameBufferInfo.pFramePointer; + gapi->useVga = 1; + + switch( g_RawFrameBufferInfo.wFormat ) + { + case FORMAT_565: + gapi->gxProperties.ffFormat = kfDirect565; + break; + case FORMAT_555: + gapi->gxProperties.ffFormat = kfDirect555; + break; + default: + /* unknown pixel format, try define by BPP! */ + switch( g_RawFrameBufferInfo.wBPP ) + { + case 4: + case 8: + gapi->gxProperties.ffFormat = kfDirect; + case 16: + gapi->gxProperties.ffFormat = kfDirect565; + default: + gapi->gxProperties.ffFormat = kfDirect; + break; + } + } + } + + if( gapi->gxProperties.cBPP != 16 ) + { + gapi->gapiOrientation = SDL_ORIENTATION_UP; + } else + if( (gapi->gxProperties.cbxPitch > 0) && (gapi->gxProperties.cbyPitch > 0 )) + { + gapi->gapiOrientation = SDL_ORIENTATION_UP; + } else + if( (gapi->gxProperties.cbxPitch > 0) && (gapi->gxProperties.cbyPitch < 0 )) + { + gapi->gapiOrientation = SDL_ORIENTATION_RIGHT; // ipaq 3660 + } else + if( (gapi->gxProperties.cbxPitch < 0) && (gapi->gxProperties.cbyPitch > 0 )) + { + gapi->gapiOrientation = SDL_ORIENTATION_LEFT; // ipaq 3800 + } +} + +static void GAPI_CreatePalette(int ncolors, SDL_Color *colors) +{ + // Setup a custom color palette + BYTE buffer[ sizeof(LOGPALETTE) + 255 * sizeof(PALETTEENTRY) ]; + int i; + LOGPALETTE* pLogical = (LOGPALETTE*)buffer; + PALETTEENTRY* entries = pLogical->palPalEntry; + HPALETTE hPalette; + HDC hdc; + + for (i = 0; i < ncolors; ++i) + { + // Find intensity by replicating the bit patterns over a byte + entries[i].peRed = colors[i].r; + entries[i].peGreen = colors[i].g; + entries[i].peBlue = colors[i].b; + entries[i].peFlags = 0; + } + + // Create the GDI palette object + pLogical->palVersion = 0x0300; + pLogical->palNumEntries = ncolors; + + hPalette = CreatePalette( pLogical ); + ASSERT(hPalette); + + + // Realize the palette + hdc = GetDC(0); + + SelectPalette( hdc, hPalette, FALSE ); + RealizePalette( hdc ); + + ReleaseDC( 0, hdc ); + DeleteObject( hPalette ); +} + +int GAPI_VideoInit(_THIS, SDL_PixelFormat *vformat) +{ + int i,bpp; + + /* Create the window */ + if ( DIB_CreateWindow(this) < 0 ) { + return(-1); + } + + if( g_hGapiLib ) + { + FillStructs(this, 0); + + // SDL does not supports 2/4bpp mode, so use 16 bpp + bpp = gapi->gxProperties.cBPP < 8 ? 16 : gapi->gxProperties.cBPP; + + /* set up normal and landscape mode */ + GAPI_AddMode(this, bpp, gapi->gxProperties.cyHeight, gapi->gxProperties.cxWidth); + GAPI_AddMode(this, bpp, gapi->gxProperties.cxWidth, gapi->gxProperties.cyHeight); + } + + /* add hi-res mode */ + if( g_bRawBufferAvailable && + !((gapi->gxProperties.cxWidth == (unsigned)g_RawFrameBufferInfo.cxPixels) && (gapi->gxProperties.cyHeight == (unsigned)g_RawFrameBufferInfo.cyPixels))) + { + FillStructs(this, 1); + + // SDL does not supports 2/4bpp mode, so use 16 bpp + bpp = gapi->gxProperties.cBPP < 8 ? 16 : gapi->gxProperties.cBPP; + + /* set up normal and landscape mode */ + GAPI_AddMode(this, bpp, gapi->gxProperties.cyHeight, gapi->gxProperties.cxWidth); + GAPI_AddMode(this, bpp, gapi->gxProperties.cxWidth, gapi->gxProperties.cyHeight); + } + + /* Determine the current screen size. + * This is NOT necessarily the size of the Framebuffer or GAPI, as they return + * the displaysize in ORIENTATION_UP */ + this->info.current_w = GetSystemMetrics(SM_CXSCREEN); + this->info.current_h = GetSystemMetrics(SM_CYSCREEN); + + /* Sort the mode lists */ + for ( i=0; i<NUM_MODELISTS; ++i ) { + if ( gapi->SDL_nummodes[i] > 0 ) { + SDL_qsort(gapi->SDL_modelist[i], gapi->SDL_nummodes[i], sizeof *gapi->SDL_modelist[i], cmpmodes); + } + } + + vformat->BitsPerPixel = gapi->gxProperties.cBPP < 8 ? 16 : (unsigned char)gapi->gxProperties.cBPP; + + // Get color mask + if (gapi->gxProperties.ffFormat & kfDirect565) { + vformat->BitsPerPixel = 16; + vformat->Rmask = 0x0000f800; + vformat->Gmask = 0x000007e0; + vformat->Bmask = 0x0000001f; + gapi->videoMode = GAPI_DIRECT_565; + } + else + if (gapi->gxProperties.ffFormat & kfDirect555) { + vformat->BitsPerPixel = 16; + vformat->Rmask = 0x00007c00; + vformat->Gmask = 0x000003e0; + vformat->Bmask = 0x0000001f; + gapi->videoMode = GAPI_DIRECT_555; + } + else + if ((gapi->gxProperties.ffFormat & kfDirect) && (gapi->gxProperties.cBPP < 8)) { + // We'll perform the conversion + vformat->BitsPerPixel = 16; + vformat->Rmask = 0x0000f800; // 16 bit 565 + vformat->Gmask = 0x000007e0; + vformat->Bmask = 0x0000001f; + if (gapi->gxProperties.ffFormat & kfDirectInverted) + gapi->invert = (1 << gapi->gxProperties.cBPP) - 1; + gapi->colorscale = gapi->gxProperties.cBPP < 8 ? 8 - gapi->gxProperties.cBPP : 0; + gapi->videoMode = GAPI_MONO; + } + else + if (gapi->gxProperties.ffFormat & kfPalette) { + gapi->videoMode = GAPI_PALETTE; + } + + /* We're done! */ + return(0); +} + +SDL_Rect **GAPI_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags) +{ + return(gapi->SDL_modelist[((format->BitsPerPixel+7)/8)-1]); +// return (SDL_Rect **) -1; +} + +SDL_Surface *GAPI_SetVideoMode(_THIS, SDL_Surface *current, + int width, int height, int bpp, Uint32 flags) +{ + SDL_Surface *video; + Uint32 Rmask, Gmask, Bmask; + DWORD style; + SDL_Rect allScreen; + + if( bpp < 4 ) + { + SDL_SetError("1 bpp and 2 bpp modes is not implemented yet!"); + return 0; + } + + /* Recalculate bitmasks if necessary */ + if (bpp == current->format->BitsPerPixel) { + video = current; + } + else { + switch(bpp) { + case 8: + Rmask = 0; + Gmask = 0; + Bmask = 0; + break; + case 15: + case 16: + /* Default is 565 unless the display is specifically 555 */ + if (gapi->gxProperties.ffFormat & kfDirect555) { + Rmask = 0x00007c00; + Gmask = 0x000003e0; + Bmask = 0x0000001f; + } + else { + Rmask = 0x0000f800; + Gmask = 0x000007e0; + Bmask = 0x0000001f; + } + break; + case 24: + case 32: + Rmask = 0x00ff0000; + Gmask = 0x0000ff00; + Bmask = 0x000000ff; + break; + default: + SDL_SetError("Unsupported Bits Per Pixel format requested"); + return NULL; + } + video = SDL_CreateRGBSurface(SDL_SWSURFACE, + 0, 0, bpp, Rmask, Gmask, Bmask, 0); + if ( video == NULL ) { + SDL_OutOfMemory(); + return(NULL); + } + } + + gapi->userOrientation = SDL_ORIENTATION_UP; + gapi->systemOrientation = SDL_ORIENTATION_UP; + video->flags = SDL_FULLSCREEN; /* Clear flags, GAPI supports fullscreen only */ + + /* GAPI or VGA? */ + if( g_hGapiLib ) + { + FillStructs(this, 0); + if( (((unsigned)width != gapi->gxProperties.cxWidth) || ((unsigned)height != gapi->gxProperties.cyHeight)) + && (((unsigned)width != gapi->gxProperties.cyHeight) || ((unsigned)height != gapi->gxProperties.cxWidth))) + FillStructs(this, 1); // gapi is found but we use VGA resolution + } else + FillStructs(this, 1); + + if ( !gapi->needUpdate && !gapi->videoMem) { + SDL_SetError("Couldn't get address of video memory, may be unsupported device or bug"); + return(NULL); + } + + /* detect user landscape mode */ + if( (width > height) && (gapi->gxProperties.cxWidth < gapi->gxProperties.cyHeight)) + gapi->userOrientation = SDL_ORIENTATION_RIGHT; + + if(GetSystemMetrics(SM_CYSCREEN) < GetSystemMetrics(SM_CXSCREEN)) + gapi->systemOrientation = SDL_ORIENTATION_RIGHT; + + gapi->hiresFix = 0; + + /* check hires */ + if(GetSystemMetrics(SM_CXSCREEN) < width && GetSystemMetrics(SM_CYSCREEN) < height) + { + gapi->hiresFix = 1; + } + + switch( gapi->userOrientation ) + { + case SDL_ORIENTATION_UP: + gapi->startOffset = 0; + gapi->dstLineStep = gapi->gxProperties.cbyPitch; + gapi->dstPixelStep = gapi->gxProperties.cbxPitch; + break; + case SDL_ORIENTATION_RIGHT: + switch( gapi->gapiOrientation ) + { + case SDL_ORIENTATION_UP: + case SDL_ORIENTATION_RIGHT: + case SDL_ORIENTATION_LEFT: + if( (gapi->videoMode == GAPI_MONO) ) + gapi->startOffset = -gapi->gxProperties.cbxPitch + 1; // monochrome mode + else + gapi->startOffset = gapi->gxProperties.cbyPitch * (gapi->gxProperties.cyHeight - 1); + + gapi->dstLineStep = gapi->gxProperties.cbxPitch; + gapi->dstPixelStep = -gapi->gxProperties.cbyPitch; + break; + } + } + + video->w = gapi->w = width; + video->h = gapi->h = height; + video->pitch = SDL_CalculatePitch(video); + + /* Small fix for WinCE/Win32 - when activating window + SDL_VideoSurface is equal to zero, so activating code + is not called properly for fullscreen windows because + macros WINDIB_FULLSCREEN uses SDL_VideoSurface + */ + SDL_VideoSurface = video; + + /* GAPI is always fullscreen, title bar is useless */ + style = 0; + + if (!SDL_windowid) + SetWindowLong(SDL_Window, GWL_STYLE, style); + + /* Allocate bitmap */ + if( gapi->buffer ) + { + SDL_free( gapi->buffer ); + gapi->buffer = NULL; + } + gapi->buffer = SDL_malloc(video->h * video->pitch); + video->pixels = gapi->buffer; + + if ( ! gapi->buffer ) { + SDL_SetError("Couldn't allocate buffer for requested mode"); + return(NULL); + } + + SDL_memset(gapi->buffer, 255, video->h * video->pitch); + MoveWindow(SDL_Window, 0, 0, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN), FALSE); + ShowWindow(SDL_Window, SW_SHOW); + SetForegroundWindow(SDL_Window); + + /* JC 14 Mar 2006 + Flush the message loop or this can cause big problems later + Especially if the user decides to use dialog boxes or assert()! + */ + WIN_FlushMessageQueue(); + + /* Open GAPI display */ + if( !gapi->useVga && gapi->useGXOpenDisplay && !gapi->alreadyGXOpened ) + { +#if REPORT_VIDEO_INFO + printf("system display width (orig): %d\n", GetSystemMetrics(SM_CXSCREEN)); + printf("system display height (orig): %d\n", GetSystemMetrics(SM_CYSCREEN)); +#endif + gapi->alreadyGXOpened = 1; + if( !gapi->gxFunc.GXOpenDisplay(SDL_Window, GX_FULLSCREEN) ) + { + SDL_SetError("Couldn't initialize GAPI"); + return(NULL); + } + } + + if(gapi->useVga) + gapi->coordinateTransform = (4 - gapi->systemOrientation + gapi->userOrientation) % 4; + else + gapi->coordinateTransform = gapi->userOrientation; + +#if REPORT_VIDEO_INFO + printf("Video properties:\n"); + printf("display bpp: %d\n", gapi->gxProperties.cBPP); + printf("display width: %d\n", gapi->gxProperties.cxWidth); + printf("display height: %d\n", gapi->gxProperties.cyHeight); + printf("system display width: %d\n", GetSystemMetrics(SM_CXSCREEN)); + printf("system display height: %d\n", GetSystemMetrics(SM_CYSCREEN)); + printf("x pitch: %d\n", gapi->gxProperties.cbxPitch); + printf("y pitch: %d\n", gapi->gxProperties.cbyPitch); + printf("gapi flags: 0x%x\n", gapi->gxProperties.ffFormat); + printf("user orientation: %d\n", gapi->userOrientation); + printf("system orientation: %d\n", gapi->systemOrientation); + printf("gapi orientation: %d\n", gapi->gapiOrientation); + + + if( !gapi->useVga && gapi->useGXOpenDisplay && gapi->needUpdate) + { + gapi->videoMem = gapi->gxFunc.GXBeginDraw(); + gapi->gxFunc.GXEndDraw(); + } + + printf("video memory: 0x%x\n", gapi->videoMem); + printf("need update: %d\n", gapi->needUpdate); + printf("hi-res fix: %d\n", gapi->hiresFix); + printf("VGA is available on the device: %d\n", g_bRawBufferAvailable); + printf("use raw framebuffer: %d\n", gapi->useVga); + printf("video surface bpp: %d\n", video->format->BitsPerPixel); + printf("video surface width: %d\n", video->w); + printf("video surface height: %d\n", video->h); + printf("mouse/arrows transformation angle: %d\n", gapi->coordinateTransform); +#endif + + + /* Blank screen */ + allScreen.x = allScreen.y = 0; + allScreen.w = video->w - 1; + allScreen.h = video->h - 1; + GAPI_UpdateRects(this, 1, &allScreen); + + /* We're done */ + return(video); +} + +/* We don't actually allow hardware surfaces other than the main one */ +static int GAPI_AllocHWSurface(_THIS, SDL_Surface *surface) +{ + return(-1); +} +static void GAPI_FreeHWSurface(_THIS, SDL_Surface *surface) +{ + return; +} + +/* We need to wait for vertical retrace on page flipped displays */ +static int GAPI_LockHWSurface(_THIS, SDL_Surface *surface) +{ + return(0); +} + +static void GAPI_UnlockHWSurface(_THIS, SDL_Surface *surface) +{ + return; +} + +static int updateLine8to8(_THIS, unsigned char *srcPointer, unsigned char *destPointer, int width, int height, int lines) +{ + if( gapi->dstPixelStep == 1) /* optimized blitting on most devices */ + { + SDL_memcpy(destPointer, srcPointer, width); + return 1; + } else + { + // TODO: read 4 pixels, write DWORD + int step = gapi->dstPixelStep; + while(width--) + { + *destPointer = *srcPointer++; + destPointer += step; + } + } + return 1; +} + +/* Video memory is very slow so lets optimize as much as possible */ +static int updateLine16to16(_THIS, PIXEL *srcPointer, PIXEL *destPointer, int width, int height, int lines) +{ + PIXEL *line1, *line2; + int step = gapi->dstPixelStep / 2; + + if( step == 1 ) /* optimized blitting on most devices */ + { + SDL_memcpy(destPointer, srcPointer, width * sizeof(PIXEL)); + return 1; + } + else + { + if( (gapi->gapiOrientation != SDL_ORIENTATION_UP) && + (gapi->userOrientation == SDL_ORIENTATION_UP )) // iPaq 3660/3800 and user orientation up + { + // to prevent data misalignment copy only one line + if( ((((unsigned)destPointer & 3) != 0) && (gapi->gapiOrientation == SDL_ORIENTATION_LEFT)) + || ((((unsigned)destPointer & 3) == 0) && (gapi->gapiOrientation != SDL_ORIENTATION_LEFT)) + || (lines == 1) ) + { + while(width--) + { + *destPointer = *srcPointer++; + destPointer += step; + } + return 1; + } + + /* read two lines at the same time, write DWORD */ + line1 = srcPointer; + line2 = srcPointer + SDL_VideoSurface->pitch / 2; + + if( gapi->gapiOrientation == SDL_ORIENTATION_LEFT ) + while(width--) // iPaq 3800 + { + *(DWORD*)destPointer =(*line2++ << 16) | *line1++; + destPointer += step; + } + else + { + destPointer += gapi->gxProperties.cbyPitch / 2; + + while(width--) // iPaq 3660 + { + *(DWORD*)destPointer =(*line1++ << 16) | *line2++; + destPointer += step; + } + } + return 2; + } else + { + // iPaq 3800 and user orientation landscape + if( gapi->gapiOrientation == SDL_ORIENTATION_LEFT ) + { + int w1; + + // to prevent data misalignment copy only one pixel + if( (((unsigned)destPointer & 3) == 0) && (width > 0)) + { + *destPointer-- = *srcPointer++; + width--; + } + + destPointer--; + + w1 = width / 2; + + while(w1--) + { + DWORD p = *(DWORD*)srcPointer; + *((DWORD*)destPointer) = (p << 16) | (p >> 16); + destPointer -= 2; + srcPointer += 2; + } + + if( width & 1 ) // copy the last pixel + { + destPointer++; + *destPointer = *srcPointer; + } + + return 1; + } + + // modern iPaqs and user orientation landscape + // read two pixels, write DWORD + + line1 = srcPointer; + line2 = srcPointer + SDL_VideoSurface->pitch / 2; + + if( (((unsigned)destPointer & 3) != 0) || (lines == 1) ) + { + while(width--) + { + *destPointer = *srcPointer++; + destPointer += step; + } + return 1; + } + + while(width--) + { + *(DWORD*)destPointer =(*line2++ << 16) | *line1++; + destPointer -= gapi->gxProperties.cbyPitch / 2; + } + return 2; + } + } +} + +// Color component masks for 565 +#define REDMASK (31<<11) +#define GREENMASK (63<<5) +#define BLUEMASK (31) + + +static int updateLine16to4(_THIS, PIXEL *srcPointer, unsigned char *destPointer, int width, int height, int lines, int yNibble, int xNibble) +{ + PIXEL *line1, *line2; + int step = gapi->dstPixelStep; + + if( gapi->userOrientation == SDL_ORIENTATION_UP ) + { + if( yNibble ) // copy bottom half of a line + { + while(width--) + { + PIXEL c1 = *srcPointer++; + c1 = ((c1 & REDMASK) >> 11) + ((c1 & GREENMASK) >> 5) + (c1 & BLUEMASK); + *destPointer = (*destPointer & 0x0F) | ((~(c1 >> 3) << 4)); + destPointer += step; + } + return 1; + } + + // either 1 pixel picture or tail, anyway this is the last line + if( lines == 1 ) + { + while(width--) + { + PIXEL c1 = *srcPointer++; + c1 = ((c1 & REDMASK) >> 11) + ((c1 & GREENMASK) >> 5) + (c1 & BLUEMASK); + *destPointer = (*destPointer & 0xF0) | ((~(c1 >> 3) & 0xF)); + destPointer += step; + } + return 1; + } + + line1 = srcPointer; + line2 = srcPointer + SDL_VideoSurface->pitch / 2; + + while(width--) + { + PIXEL c1 = *line1++; + PIXEL c2 = *line2++; + c1 = ((c1 & REDMASK) >> 11) + ((c1 & GREENMASK) >> 5) + (c1 & BLUEMASK); + c2 = ((c2 & REDMASK) >> 11) + ((c2 & GREENMASK) >> 5) + (c2 & BLUEMASK); + *destPointer = ~((c1 >> 3) + ((c2 >> 3) << 4)); + destPointer += step; + } + return 2; + } else + { + int w1; + w1 = width / 2; + + if( xNibble ) + { + // copy one pixel + PIXEL c1 = *srcPointer++; + c1 = ((c1 & REDMASK) >> 11) + ((c1 & GREENMASK) >> 5) + (c1 & BLUEMASK); + *destPointer = (*destPointer & 0xF0) | ((~(c1 >> 3) & 0xF)); + destPointer++; + } + + while(w1--) + { + PIXEL c1 = *srcPointer; + PIXEL c2 = *(srcPointer + 1); + c1 = ((c1 & REDMASK) >> 11) + ((c1 & GREENMASK) >> 5) + (c1 & BLUEMASK); + c2 = ((c2 & REDMASK) >> 11) + ((c2 & GREENMASK) >> 5) + (c2 & BLUEMASK); + *destPointer++ = ~((c2 >> 3) + ((c1 >> 3) << 4)); + srcPointer += 2; + } + + // copy tail + if( (width & 1) && !xNibble ) + { + PIXEL c1 = *srcPointer; + c1 = ((c1 & REDMASK) >> 11) + ((c1 & GREENMASK) >> 5) + (c1 & BLUEMASK); + *destPointer = (*destPointer & 0x0F) | ((~(c1 >> 3) << 4)); + } + + return 1; + } +} + +static void GAPI_UpdateRectsMono(_THIS, int numrects, SDL_Rect *rects) +{ + int i, height; + int linesProcessed; + int xNibble, yNibble; + + for (i=0; i<numrects; i++) + { + unsigned char *destPointer; + unsigned char *srcPointer; + + if( gapi->userOrientation == SDL_ORIENTATION_UP ) + destPointer = (unsigned char*) gapi->videoMem + gapi->startOffset - rects[i].y * gapi->gxProperties.cBPP / 8 + rects[i].x * gapi->dstPixelStep; + else + destPointer = (unsigned char*) gapi->videoMem + gapi->startOffset + rects[i].x * gapi->gxProperties.cBPP / 8 + rects[i].y * gapi->dstLineStep; + + srcPointer = ((unsigned char*) SDL_VideoSurface->pixels) + rects[i].y * SDL_VideoSurface->pitch + rects[i].x * 2; + yNibble = rects[i].y & 1; // TODO: only for 4 bpp + xNibble = rects[i].x & 1; + height = rects[i].h; + while (height > 0) + { + switch(gapi->gxProperties.cBPP) + { + case 2: // TODO + case 4: + linesProcessed = updateLine16to4(this, (PIXEL*) srcPointer, destPointer, rects[i].w, rects[i].h, height, yNibble, xNibble); + yNibble = 0; + } + height -= linesProcessed; + if( gapi->userOrientation == SDL_ORIENTATION_UP ) + destPointer--; // always fill 1 byte + else destPointer += gapi->dstLineStep; + srcPointer += SDL_VideoSurface->pitch * linesProcessed; // pitch in bytes + } + } +} + +static void GAPI_UpdateRectsColor(_THIS, int numrects, SDL_Rect *rects) +{ + int i, height; + int bytesPerPixel = (gapi->gxProperties.cBPP + 1) / 8; + int linesProcessed; + for (i=0; i<numrects; i++) { + unsigned char *destPointer = (unsigned char*) gapi->videoMem + gapi->startOffset + rects[i].y * gapi->dstLineStep + rects[i].x * gapi->dstPixelStep; + unsigned char *srcPointer = ((unsigned char*) SDL_VideoSurface->pixels) + rects[i].y * SDL_VideoSurface->pitch + rects[i].x * bytesPerPixel; + height = rects[i].h; + +// fprintf(stderr, "Starting rect %dx%d, dst=0x%x, w = %d, h = %d\n", rects[i].w, rects[i].h,destPointer,rects[i].w,rects[i].h); +// fflush(stderr); + linesProcessed = height; + + while (height > 0) { + switch(bytesPerPixel) + { + case 1: + linesProcessed = updateLine8to8(this, srcPointer, (unsigned char *) destPointer, rects[i].w, rects[i].h, height); + break; + case 2: +#pragma warning(disable: 4133) + linesProcessed = updateLine16to16(this, (PIXEL*) srcPointer, destPointer, rects[i].w, rects[i].h, height); + break; + } + height -= linesProcessed; + destPointer += gapi->dstLineStep * linesProcessed; + srcPointer += SDL_VideoSurface->pitch * linesProcessed; // pitch in bytes + } +// fprintf(stderr, "End of rect\n"); +// fflush(stderr); + } +} + + +static void GAPI_UpdateRects(_THIS, int numrects, SDL_Rect *rects) +{ + // we do not want to corrupt video memory + if( gapi->suspended ) return; + + if( gapi->needUpdate ) + gapi->videoMem = gapi->gxFunc.GXBeginDraw(); + + if( gapi->gxProperties.cBPP < 8 ) + GAPI_UpdateRectsMono(this, numrects, rects); + else + GAPI_UpdateRectsColor(this, numrects, rects); + + if( gapi->needUpdate ) + gapi->gxFunc.GXEndDraw(); +} + +/* Note: If we are terminated, this could be called in the middle of + another SDL video routine -- notably UpdateRects. +*/ +void GAPI_VideoQuit(_THIS) +{ + int i, j; + /* Destroy the window and everything associated with it */ + if ( SDL_Window ) + { + if ((g_hGapiLib != 0) && this && gapi && gapi->gxFunc.GXCloseDisplay && !gapi->useVga) + gapi->gxFunc.GXCloseDisplay(); + + if (this->screen->pixels != NULL) + { + SDL_free(this->screen->pixels); + this->screen->pixels = NULL; + } + if ( screen_icn ) { + DestroyIcon(screen_icn); + screen_icn = NULL; + } + + DIB_DestroyWindow(this); + SDL_UnregisterApp(); + + SDL_Window = NULL; +#if defined(_WIN32_WCE) + +// Unload wince aygshell library to prevent leak + if( aygshell ) + { + FreeLibrary(aygshell); + aygshell = NULL; + } +#endif + + /* Free video mode lists */ + for ( i=0; i<NUM_MODELISTS; ++i ) { + if ( gapi->SDL_modelist[i] != NULL ) { + for ( j=0; gapi->SDL_modelist[i][j]; ++j ) + SDL_free(gapi->SDL_modelist[i][j]); + SDL_free(gapi->SDL_modelist[i]); + gapi->SDL_modelist[i] = NULL; + } + } + + } + +} + +static void GAPI_Activate(_THIS, BOOL active, BOOL minimized) +{ + //Nothing to do here (as far as I know) +} + +static void GAPI_RealizePalette(_THIS) +{ + OutputDebugString(TEXT("GAPI_RealizePalette NOT IMPLEMENTED !\r\n")); +} + +static void GAPI_PaletteChanged(_THIS, HWND window) +{ + OutputDebugString(TEXT("GAPI_PaletteChanged NOT IMPLEMENTED !\r\n")); +} + +static void GAPI_WinPAINT(_THIS, HDC hdc) +{ + // draw current offscreen buffer on hdc + + int bpp = 16; // we always use either 8 or 16 bpp internally + HGDIOBJ prevObject; + unsigned short *bitmapData; + HBITMAP hb; + HDC srcDC; + + // Create a DIB + BYTE buffer[sizeof(BITMAPINFOHEADER) + 3 * sizeof(RGBQUAD)] = {0}; + BITMAPINFO* pBMI = (BITMAPINFO*)buffer; + BITMAPINFOHEADER* pHeader = &pBMI->bmiHeader; + DWORD* pColors = (DWORD*)&pBMI->bmiColors; + + // CreateDIBSection does not support 332 pixel format on wce + if( gapi->gxProperties.cBPP == 8 ) return; + + // DIB Header + pHeader->biSize = sizeof(BITMAPINFOHEADER); + pHeader->biWidth = gapi->w; + pHeader->biHeight = -gapi->h; + pHeader->biPlanes = 1; + pHeader->biBitCount = bpp; + pHeader->biCompression = BI_RGB; + pHeader->biSizeImage = (gapi->w * gapi->h * bpp) / 8; + + // Color masks + if( bpp == 16 ) + { + pColors[0] = REDMASK; + pColors[1] = GREENMASK; + pColors[2] = BLUEMASK; + pHeader->biCompression = BI_BITFIELDS; + } + // Create the DIB + hb = CreateDIBSection( 0, pBMI, DIB_RGB_COLORS, (void**)&bitmapData, 0, 0 ); + + // copy data + // FIXME: prevent misalignment, but I've never seen non aligned width of screen + memcpy(bitmapData, gapi->buffer, pHeader->biSizeImage); + srcDC = CreateCompatibleDC(hdc); + prevObject = SelectObject(srcDC, hb); + + BitBlt(hdc, 0, 0, gapi->w, gapi->h, srcDC, 0, 0, SRCCOPY); + + SelectObject(srcDC, prevObject); + DeleteObject(hb); + DeleteDC(srcDC); +} + +int GAPI_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors) +{ + GAPI_CreatePalette(ncolors, colors); + return 1; +} diff --git a/3rdparty/SDL/src/video/gapi/SDL_gapivideo.h b/3rdparty/SDL/src/video/gapi/SDL_gapivideo.h new file mode 100644 index 0000000..842d098 --- /dev/null +++ b/3rdparty/SDL/src/video/gapi/SDL_gapivideo.h @@ -0,0 +1,160 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#ifndef _SDL_gapivideo_h +#define _SDL_gapivideo_h + +#include "SDL_mouse.h" +#include "SDL_mutex.h" +#include "../SDL_sysvideo.h" +#include "../windib/SDL_gapidibvideo.h" + +/* From gx.h, since it's not really C compliant */ + +struct GXDisplayProperties { + DWORD cxWidth; + DWORD cyHeight; // notice lack of 'th' in the word height. + long cbxPitch; // number of bytes to move right one x pixel - can be negative. + long cbyPitch; // number of bytes to move down one y pixel - can be negative. + long cBPP; // # of bits in each pixel + DWORD ffFormat; // format flags. +}; + +struct GXKeyList { + short vkUp; // key for up + POINT ptUp; // x,y position of key/button. Not on screen but in screen coordinates. + short vkDown; + POINT ptDown; + short vkLeft; + POINT ptLeft; + short vkRight; + POINT ptRight; + short vkA; + POINT ptA; + short vkB; + POINT ptB; + short vkC; + POINT ptC; + short vkStart; + POINT ptStart; +}; + +typedef int (*PFNGXOpenDisplay)(HWND hWnd, DWORD dwFlags); +typedef int (*PFNGXCloseDisplay)(); +typedef void* (*PFNGXBeginDraw)(); +typedef int (*PFNGXEndDraw)(); +typedef int (*PFNGXOpenInput)(); +typedef int (*PFNGXCloseInput)(); +typedef struct GXDisplayProperties (*PFNGXGetDisplayProperties)(); +typedef struct GXKeyList (*PFNGXGetDefaultKeys)(int iOptions); +typedef int (*PFNGXSuspend)(); +typedef int (*PFNGXResume)(); +typedef int (*PFNGXSetViewport)( DWORD dwTop, DWORD dwHeight, DWORD dwReserved1, DWORD dwReserved2 ); +typedef BOOL (*PFNGXIsDisplayDRAMBuffer)(); + +struct GapiFunc +{ + PFNGXOpenDisplay GXOpenDisplay; + PFNGXCloseDisplay GXCloseDisplay; + PFNGXBeginDraw GXBeginDraw; + PFNGXEndDraw GXEndDraw; + PFNGXOpenInput GXOpenInput; + PFNGXCloseInput GXCloseInput; + PFNGXGetDisplayProperties GXGetDisplayProperties; + PFNGXGetDefaultKeys GXGetDefaultKeys; + PFNGXSuspend GXSuspend; + PFNGXResume GXResume; + PFNGXSetViewport GXSetViewport; + PFNGXIsDisplayDRAMBuffer GXIsDisplayDRAMBuffer; +}; + +#define kfLandscape 0x8 // Screen is rotated 270 degrees +#define kfPalette 0x10 // Pixel values are indexes into a palette +#define kfDirect 0x20 // Pixel values contain actual level information +#define kfDirect555 0x40 // 5 bits each for red, green and blue values in a pixel. +#define kfDirect565 0x80 // 5 red bits, 6 green bits and 5 blue bits per pixel +#define kfDirect888 0x100 // 8 bits each for red, green and blue values in a pixel. +#define kfDirect444 0x200 // 4 red, 4 green, 4 blue +#define kfDirectInverted 0x400 + +#define GX_FULLSCREEN 0x01 // for OpenDisplay() +#define GX_NORMALKEYS 0x02 +#define GX_LANDSCAPEKEYS 0x03 + + +/* GAPI video mode */ +typedef enum { + GAPI_NONE = 0, + GAPI_DIRECT_565, + GAPI_DIRECT_555, + GAPI_MONO, + GAPI_PALETTE +} GAPIVideoMode; + +typedef unsigned short PIXEL; + +/* Private display data + begin with DIB private structure to allow DIB events code sharing +*/ +struct GapiInfo { + /* Rotation which has to be applied to the key (arrow keys) and mouse events measured in quarters of a circle + * counter clockwise */ + int coordinateTransform; + char hiresFix; /* using hires mode without defining hires resource */ + int invert; //TODO this is only written but never read, so it should be removed + +#define NUM_MODELISTS 4 /* 8, 16, 24, and 32 bits-per-pixel */ + int SDL_nummodes[NUM_MODELISTS]; + SDL_Rect **SDL_modelist[NUM_MODELISTS]; + + + // The orientation of the video mode user wants to get + // Probably restricted to UP and RIGHT + SDL_ScreenOrientation userOrientation; + SDL_ScreenOrientation systemOrientation; +// -------------- + int useGXOpenDisplay; /* use GXOpenDispplay */ + int alreadyGXOpened; + int w, h; + // The orientation of GAPI framebuffer. + // Never changes on the same device. + SDL_ScreenOrientation gapiOrientation; + + void *buffer; // may be 8, 16, 24, 32 bpp + PIXEL *videoMem; + BOOL needUpdate; + struct GXKeyList keyList; + struct GapiFunc gxFunc; + struct GXDisplayProperties gxProperties; + GAPIVideoMode videoMode; + int colorscale; + int dstLineStep; // in bytes + int dstPixelStep; // in bytes + int startOffset; // in bytes + int useVga; + int suspended; // do not pu anything into video memory +}; + + + +#endif /* _SDL_gapivideo_h */ diff --git a/3rdparty/SDL/src/video/gem/SDL_gemevents.c b/3rdparty/SDL/src/video/gem/SDL_gemevents.c new file mode 100644 index 0000000..c5a505d --- /dev/null +++ b/3rdparty/SDL/src/video/gem/SDL_gemevents.c @@ -0,0 +1,375 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* + * GEM SDL video driver implementation + * inspired from the Dummy SDL driver + * + * Patrice Mandin + * and work from + * Olivier Landemarre, Johan Klockars, Xavier Joubert, Claude Attard + */ + +#include <gem.h> + +#include "../../events/SDL_sysevents.h" +#include "../../events/SDL_events_c.h" +#include "SDL_gemvideo.h" +#include "SDL_gemevents_c.h" +#include "SDL_gemmouse_c.h" +#include "../ataricommon/SDL_atarikeys.h" /* for keyboard scancodes */ +#include "../ataricommon/SDL_atarievents_c.h" +#include "../ataricommon/SDL_xbiosevents_c.h" +#include "../ataricommon/SDL_ataridevmouse_c.h" + +/* Variables */ + +static unsigned char gem_currentkeyboard[ATARIBIOS_MAXKEYS]; +static unsigned char gem_previouskeyboard[ATARIBIOS_MAXKEYS]; + +/* Functions prototypes */ + +static int do_messages(_THIS, short *message); +static void do_keyboard(short kc, short ks); +static void do_mouse(_THIS, short mx, short my, short mb, short ks); + +/* Functions */ + +void GEM_InitOSKeymap(_THIS) +{ + SDL_memset(gem_currentkeyboard, 0, sizeof(gem_currentkeyboard)); + SDL_memset(gem_previouskeyboard, 0, sizeof(gem_previouskeyboard)); + + /* Mouse init */ + GEM_mouse_relative = SDL_FALSE; + + SDL_Atari_InitInternalKeymap(this); +} + +void GEM_PumpEvents(_THIS) +{ + short prevkc, prevks; + static short maskmouseb=0; + int i; + SDL_keysym keysym; + + SDL_memset(gem_currentkeyboard,0,sizeof(gem_currentkeyboard)); + prevkc = prevks = 0; + + for (;;) + { + int quit, resultat, event_mask, mouse_event; + short buffer[8], kc; + short x2,y2,w2,h2; + short mousex, mousey, mouseb, dummy; + short kstate; + + quit = + mouse_event = + x2=y2=w2=h2 = 0; + + event_mask = MU_MESAG|MU_TIMER|MU_KEYBD|MU_BUTTON; + if (!GEM_fullscreen && (GEM_handle>=0)) { + wind_get (GEM_handle, WF_WORKXYWH, &x2, &y2, &w2, &h2); + event_mask |= MU_M1; + mouse_event = ( (SDL_GetAppState() & SDL_APPMOUSEFOCUS) + == SDL_APPMOUSEFOCUS) ? MO_LEAVE : MO_ENTER; + } + + resultat = evnt_multi( + event_mask, + 0x101,7,maskmouseb, + mouse_event,x2,y2,w2,h2, + 0,0,0,0,0, + buffer, + 10, + &mousex,&mousey,&mouseb,&kstate,&kc,&dummy + ); + + /* Message event ? */ + if (resultat & MU_MESAG) + quit = do_messages(this, buffer); + + /* Keyboard event ? */ + if (resultat & MU_KEYBD) { + if ((prevkc != kc) || (prevks != kstate)) { + do_keyboard(kc,kstate); + } else { + /* Avoid looping, if repeating same key */ + break; + } + } + + /* Mouse entering/leaving window */ + if (resultat & MU_M1) { + if (this->input_grab == SDL_GRAB_OFF) { + /* Switch mouse focus state */ + SDL_PrivateAppActive((mouse_event == MO_ENTER), + SDL_APPMOUSEFOCUS); + } + GEM_CheckMouseMode(this); + } + + /* Mouse button event ? */ + if (resultat & MU_BUTTON) { + do_mouse(this, mousex, mousey, mouseb, kstate); + maskmouseb = mouseb & 7; + } + + /* Timer event ? */ + if ((resultat & MU_TIMER) || quit) + break; + } + + /* Now generate keyboard events */ + for (i=0; i<ATARIBIOS_MAXKEYS; i++) { + /* Key pressed ? */ + if (gem_currentkeyboard[i] && !gem_previouskeyboard[i]) + SDL_PrivateKeyboard(SDL_PRESSED, + SDL_Atari_TranslateKey(i, &keysym, SDL_TRUE)); + + /* Key unpressed ? */ + if (gem_previouskeyboard[i] && !gem_currentkeyboard[i]) + SDL_PrivateKeyboard(SDL_RELEASED, + SDL_Atari_TranslateKey(i, &keysym, SDL_FALSE)); + } + + SDL_memcpy(gem_previouskeyboard,gem_currentkeyboard,sizeof(gem_previouskeyboard)); + + /* Refresh window name ? */ + if (GEM_refresh_name) { + const char *window_name = + (SDL_GetAppState() & SDL_APPACTIVE) + ? GEM_title_name : GEM_icon_name; + if (window_name) { + wind_set(GEM_handle,WF_NAME, + (short)(((unsigned long)window_name)>>16), + (short)(((unsigned long)window_name) & 0xffff), + 0,0); + } + GEM_refresh_name = SDL_FALSE; + } +} + +static int do_messages(_THIS, short *message) +{ + int quit, check_mouse_mode; + short x2,y2,w2,h2; + + quit = check_mouse_mode = 0; + switch (message[0]) { + case WM_CLOSED: + case AP_TERM: + SDL_PrivateQuit(); + quit=1; + break; + case WM_MOVED: + wind_set(message[3],WF_CURRXYWH,message[4],message[5],message[6],message[7]); + break; + case WM_TOPPED: + wind_set(message[3],WF_TOP,message[4],0,0,0); + /* Continue with TOP event processing */ + case WM_ONTOP: + SDL_PrivateAppActive(1, SDL_APPINPUTFOCUS); + if (VDI_setpalette) { + VDI_setpalette(this, VDI_curpalette); + } + check_mouse_mode = 1; + break; + case WM_REDRAW: + if (!GEM_lock_redraw) { + GEM_wind_redraw(this, message[3],&message[4]); + } + break; + case WM_ICONIFY: + case WM_ALLICONIFY: + wind_set(message[3],WF_ICONIFY,message[4],message[5],message[6],message[7]); + /* If we're active, make ourselves inactive */ + if ( SDL_GetAppState() & SDL_APPACTIVE ) { + /* Send an internal deactivate event */ + SDL_PrivateAppActive(0, SDL_APPACTIVE); + } + /* Update window title */ + if (GEM_refresh_name && GEM_icon_name) { + wind_set(GEM_handle,WF_NAME,(short)(((unsigned long)GEM_icon_name)>>16),(short)(((unsigned long)GEM_icon_name) & 0xffff),0,0); + GEM_refresh_name = SDL_FALSE; + } + check_mouse_mode = 1; + break; + case WM_UNICONIFY: + wind_set(message[3],WF_UNICONIFY,message[4],message[5],message[6],message[7]); + /* If we're not active, make ourselves active */ + if ( !(SDL_GetAppState() & SDL_APPACTIVE) ) { + /* Send an internal activate event */ + SDL_PrivateAppActive(1, SDL_APPACTIVE); + } + if (GEM_refresh_name && GEM_title_name) { + wind_set(GEM_handle,WF_NAME,(short)(((unsigned long)GEM_title_name)>>16),(short)(((unsigned long)GEM_title_name) & 0xffff),0,0); + GEM_refresh_name = SDL_FALSE; + } + check_mouse_mode = 1; + break; + case WM_SIZED: + wind_set (message[3], WF_CURRXYWH, message[4], message[5], message[6], message[7]); + wind_get (message[3], WF_WORKXYWH, &x2, &y2, &w2, &h2); + GEM_win_fulled = SDL_FALSE; /* Cancel maximized flag */ + GEM_lock_redraw = SDL_TRUE; /* Prevent redraw till buffers resized */ + SDL_PrivateResize(w2, h2); + break; + case WM_FULLED: + { + short x,y,w,h; + + if (GEM_win_fulled) { + wind_get (message[3], WF_PREVXYWH, &x, &y, &w, &h); + GEM_win_fulled = SDL_FALSE; + } else { + x = GEM_desk_x; + y = GEM_desk_y; + w = GEM_desk_w; + h = GEM_desk_h; + GEM_win_fulled = SDL_TRUE; + } + wind_set (message[3], WF_CURRXYWH, x, y, w, h); + wind_get (message[3], WF_WORKXYWH, &x2, &y2, &w2, &h2); + GEM_lock_redraw = SDL_TRUE; /* Prevent redraw till buffers resized */ + SDL_PrivateResize(w2, h2); + } + break; + case WM_BOTTOMED: + wind_set(message[3],WF_BOTTOM,0,0,0,0); + /* Continue with BOTTOM event processing */ + case WM_UNTOPPED: + SDL_PrivateAppActive(0, SDL_APPINPUTFOCUS); + if (VDI_setpalette) { + VDI_setpalette(this, VDI_oldpalette); + } + check_mouse_mode = 1; + break; + } + + if (check_mouse_mode) { + GEM_CheckMouseMode(this); + } + + return quit; +} + +static void do_keyboard(short kc, short ks) +{ + int scancode; + + if (kc) { + scancode=(kc>>8) & (ATARIBIOS_MAXKEYS-1); + gem_currentkeyboard[scancode]=0xFF; + } + + /* Read special keys */ + if (ks & K_RSHIFT) + gem_currentkeyboard[SCANCODE_RIGHTSHIFT]=0xFF; + if (ks & K_LSHIFT) + gem_currentkeyboard[SCANCODE_LEFTSHIFT]=0xFF; + if (ks & K_CTRL) + gem_currentkeyboard[SCANCODE_LEFTCONTROL]=0xFF; + if (ks & K_ALT) + gem_currentkeyboard[SCANCODE_LEFTALT]=0xFF; +} + +static void do_mouse(_THIS, short mx, short my, short mb, short ks) +{ + static short prevmousex=0, prevmousey=0, prevmouseb=0; + short x2, y2, w2, h2; + + /* Don't return mouse events if out of window */ + if ((SDL_GetAppState() & SDL_APPMOUSEFOCUS)==0) { + return; + } + + /* Retrieve window coords, and generate mouse events accordingly */ + x2 = y2 = 0; + w2 = VDI_w; + h2 = VDI_h; + if ((!GEM_fullscreen) && (GEM_handle>=0)) { + wind_get (GEM_handle, WF_WORKXYWH, &x2, &y2, &w2, &h2); + + /* Do not generate mouse button event if out of window working area */ + if ((mx<x2) || (mx>=x2+w2) || (my<y2) || (my>=y2+h2)) { + mb=prevmouseb; + } + } + + /* Mouse motion ? */ + if (GEM_mouse_relative) { + if (GEM_usedevmouse) { + SDL_AtariDevMouse_PostMouseEvents(this, SDL_FALSE); + } else { + SDL_AtariXbios_PostMouseEvents(this, SDL_FALSE); + } + } else { + if ((prevmousex!=mx) || (prevmousey!=my)) { + int posx, posy; + + /* Give mouse position relative to window position */ + posx = mx - x2; + if (posx<0) posx = 0; + if (posx>w2) posx = w2-1; + posy = my - y2; + if (posy<0) posy = 0; + if (posy>h2) posy = h2-1; + + SDL_PrivateMouseMotion(0, 0, posx, posy); + } + prevmousex = mx; + prevmousey = my; + } + + /* Mouse button ? */ + if (prevmouseb!=mb) { + int i; + + for (i=0;i<3;i++) { + int curbutton, prevbutton; + + curbutton = mb & (1<<i); + prevbutton = prevmouseb & (1<<i); + + if (curbutton && !prevbutton) { + SDL_PrivateMouseButton(SDL_PRESSED, i+1, 0, 0); + } + if (!curbutton && prevbutton) { + SDL_PrivateMouseButton(SDL_RELEASED, i+1, 0, 0); + } + } + prevmouseb = mb; + } + + /* Read special keys */ + if (ks & K_RSHIFT) + gem_currentkeyboard[SCANCODE_RIGHTSHIFT]=0xFF; + if (ks & K_LSHIFT) + gem_currentkeyboard[SCANCODE_LEFTSHIFT]=0xFF; + if (ks & K_CTRL) + gem_currentkeyboard[SCANCODE_LEFTCONTROL]=0xFF; + if (ks & K_ALT) + gem_currentkeyboard[SCANCODE_LEFTALT]=0xFF; +} diff --git a/3rdparty/SDL/src/video/gem/SDL_gemevents_c.h b/3rdparty/SDL/src/video/gem/SDL_gemevents_c.h new file mode 100644 index 0000000..7d5d9b3 --- /dev/null +++ b/3rdparty/SDL/src/video/gem/SDL_gemevents_c.h @@ -0,0 +1,33 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#include "SDL_gemvideo.h" + +/* Variables and functions exported by SDL_sysevents.c to other parts + of the native video subsystem (SDL_sysvideo.c) */ + +extern void GEM_InitOSKeymap(_THIS); +extern void GEM_PumpEvents(_THIS); + +/* end of SDL_gemevents_c.h */ + diff --git a/3rdparty/SDL/src/video/gem/SDL_gemmouse.c b/3rdparty/SDL/src/video/gem/SDL_gemmouse.c new file mode 100644 index 0000000..c876cff --- /dev/null +++ b/3rdparty/SDL/src/video/gem/SDL_gemmouse.c @@ -0,0 +1,205 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* + * GEM Mouse manager + * + * Patrice Mandin + */ + +#include <gem.h> + +#include "SDL_mouse.h" +#include "../../events/SDL_events_c.h" +#include "../SDL_cursor_c.h" +#include "SDL_gemmouse_c.h" +#include "SDL_gemvideo.h" +#include "../ataricommon/SDL_xbiosevents_c.h" + +/* Defines */ + +/*#define DEBUG_VIDEO_GEM 1*/ + +#define MAXCURWIDTH 16 +#define MAXCURHEIGHT 16 + +void GEM_FreeWMCursor(_THIS, WMcursor *cursor) +{ +#ifdef DEBUG_VIDEO_GEM + printf("sdl:video:gem: free cursor\n"); +#endif + + if (cursor == NULL) + return; + + graf_mouse(ARROW, NULL); + + if (cursor->mform_p != NULL) + SDL_free(cursor->mform_p); + + SDL_free(cursor); +} + +WMcursor *GEM_CreateWMCursor(_THIS, + Uint8 *data, Uint8 *mask, int w, int h, int hot_x, int hot_y) +{ + WMcursor *cursor; + MFORM *new_mform; + int i; + +#ifdef DEBUG_VIDEO_GEM + Uint16 *data1, *mask1; + + printf("sdl:video:gem: create cursor\n"); +#endif + + /* Check the size */ + if ( (w > MAXCURWIDTH) || (h > MAXCURHEIGHT) ) { + SDL_SetError("Only cursors of dimension (%dx%d) are allowed", + MAXCURWIDTH, MAXCURHEIGHT); + return(NULL); + } + + /* Allocate the cursor memory */ + cursor = (WMcursor *)SDL_malloc(sizeof(WMcursor)); + if ( cursor == NULL ) { + SDL_OutOfMemory(); + return(NULL); + } + + /* Allocate mform */ + new_mform = (MFORM *)SDL_malloc(sizeof(MFORM)); + if (new_mform == NULL) { + SDL_free(cursor); + SDL_OutOfMemory(); + return(NULL); + } + + cursor->mform_p = new_mform; + + new_mform->mf_xhot = hot_x; + new_mform->mf_yhot = hot_y; + new_mform->mf_nplanes = 1; + new_mform->mf_fg = 0; + new_mform->mf_bg = 1; + + for (i=0;i<MAXCURHEIGHT;i++) { + new_mform->mf_mask[i]=0; + new_mform->mf_data[i]=0; +#ifdef DEBUG_VIDEO_GEM + data1 = (Uint16 *) &data[i<<1]; + mask1 = (Uint16 *) &mask[i<<1]; + printf("sdl:video:gem: source: line %d: data=0x%04x, mask=0x%04x\n", + i, data1[i], mask1[i]); +#endif + } + + if (w<=8) { + for (i=0;i<h;i++) { + new_mform->mf_mask[i]= mask[i]<<8; + new_mform->mf_data[i]= data[i]<<8; + } + } else { + for (i=0;i<h;i++) { + new_mform->mf_mask[i]= (mask[i<<1]<<8) | mask[(i<<1)+1]; + new_mform->mf_data[i]= (data[i<<1]<<8) | data[(i<<1)+1]; + } + } + +#ifdef DEBUG_VIDEO_GEM + for (i=0; i<h ;i++) { + printf("sdl:video:gem: cursor: line %d: data=0x%04x, mask=0x%04x\n", + i, new_mform->mf_data[i], new_mform->mf_mask[i]); + } + + printf("sdl:video:gem: CreateWMCursor(): done\n"); +#endif + + return cursor; +} + +int GEM_ShowWMCursor(_THIS, WMcursor *cursor) +{ + GEM_cursor = cursor; + + GEM_CheckMouseMode(this); + +#ifdef DEBUG_VIDEO_GEM + printf("sdl:video:gem: ShowWMCursor(0x%08x)\n", (long) cursor); +#endif + + return 1; +} + +#if 0 +void GEM_WarpWMCursor(_THIS, Uint16 x, Uint16 y) +{ + /* This seems to work only on AES 3.4 (Falcon) */ + + EVNTREC warpevent; + + warpevent.ap_event = APPEVNT_MOUSE; + warpevent.ap_value = (x << 16) | y; + + appl_tplay(&warpevent, 1, 1000); +} +#endif + +void GEM_CheckMouseMode(_THIS) +{ + const Uint8 full_focus = (SDL_APPACTIVE|SDL_APPINPUTFOCUS|SDL_APPMOUSEFOCUS); + int set_system_cursor = 1, show_system_cursor = 1; + +#ifdef DEBUG_VIDEO_GEM + printf("sdl:video:gem: check mouse mode\n"); +#endif + + /* If the mouse is hidden and input is grabbed, we use relative mode */ + GEM_mouse_relative = (!(SDL_cursorstate & CURSOR_VISIBLE)) + && (this->input_grab != SDL_GRAB_OFF) + && (SDL_GetAppState() & SDL_APPACTIVE); + SDL_AtariXbios_LockMousePosition(GEM_mouse_relative); + + if (SDL_cursorstate & CURSOR_VISIBLE) { + /* Application defined cursor only over the application window */ + if ((SDL_GetAppState() & full_focus) == full_focus) { + if (GEM_cursor) { + graf_mouse(USER_DEF, GEM_cursor->mform_p); + set_system_cursor = 0; + } else { + show_system_cursor = 0; + } + } + } else { + /* Mouse cursor hidden only over the application window */ + if ((SDL_GetAppState() & full_focus) == full_focus) { + set_system_cursor = 0; + show_system_cursor = 0; + } + } + + graf_mouse(show_system_cursor ? M_ON : M_OFF, NULL); + if (set_system_cursor) { + graf_mouse(ARROW, NULL); + } +} diff --git a/3rdparty/SDL/src/video/gem/SDL_gemmouse_c.h b/3rdparty/SDL/src/video/gem/SDL_gemmouse_c.h new file mode 100644 index 0000000..06f90ba --- /dev/null +++ b/3rdparty/SDL/src/video/gem/SDL_gemmouse_c.h @@ -0,0 +1,34 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#include "SDL_gemvideo.h" + +/* Functions to be exported */ +extern void GEM_FreeWMCursor(_THIS, WMcursor *cursor); +extern WMcursor *GEM_CreateWMCursor(_THIS, + Uint8 *data, Uint8 *mask, int w, int h, int hot_x, int hot_y); +extern int GEM_ShowWMCursor(_THIS, WMcursor *cursor); +#if 0 +extern void GEM_WarpWMCursor(_THIS, Uint16 x, Uint16 y); +#endif +extern void GEM_CheckMouseMode(_THIS); diff --git a/3rdparty/SDL/src/video/gem/SDL_gemvideo.c b/3rdparty/SDL/src/video/gem/SDL_gemvideo.c new file mode 100644 index 0000000..2ce9151 --- /dev/null +++ b/3rdparty/SDL/src/video/gem/SDL_gemvideo.c @@ -0,0 +1,1337 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* + GEM video driver + + Patrice Mandin + and work from + Olivier Landemarre, Johan Klockars, Xavier Joubert, Claude Attard +*/ + +/* Mint includes */ +#include <gem.h> +#include <gemx.h> +#include <mint/osbind.h> +#include <mint/cookie.h> + +#include "SDL_endian.h" +#include "SDL_video.h" +#include "SDL_mouse.h" +#include "../SDL_sysvideo.h" +#include "../SDL_pixels_c.h" +#include "../../events/SDL_events_c.h" +#include "../SDL_cursor_c.h" + +#include "../ataricommon/SDL_ataric2p_s.h" +#include "../ataricommon/SDL_atarieddi_s.h" +#include "../ataricommon/SDL_atarimxalloc_c.h" +#include "../ataricommon/SDL_atarigl_c.h" + +#include "SDL_gemvideo.h" +#include "SDL_gemevents_c.h" +#include "SDL_gemmouse_c.h" +#include "SDL_gemwm_c.h" +#include "../ataricommon/SDL_xbiosevents_c.h" +#include "../ataricommon/SDL_ataridevmouse_c.h" + +/* Defines */ + +/*#define DEBUG_VIDEO_GEM 1*/ + +#define GEM_VID_DRIVER_NAME "gem" + +#undef MIN +#define MIN(a,b) (((a)<(b)) ? (a) : (b)) +#undef MAX +#define MAX(a,b) (((a)>(b)) ? (a) : (b)) + +/* Variables */ + +static unsigned char vdi_index[256] = { + 0, 2, 3, 6, 4, 7, 5, 8, + 9, 10, 11, 14, 12, 15, 13, 255 +}; + +static const char empty_name[]=""; + +/* Initialization/Query functions */ +static int GEM_VideoInit(_THIS, SDL_PixelFormat *vformat); +static SDL_Rect **GEM_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags); +static SDL_Surface *GEM_SetVideoMode(_THIS, SDL_Surface *current, int width, int height, int bpp, Uint32 flags); +static int GEM_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors); +static void GEM_VideoQuit(_THIS); + +/* Hardware surface functions */ +static int GEM_AllocHWSurface(_THIS, SDL_Surface *surface); +static int GEM_LockHWSurface(_THIS, SDL_Surface *surface); +static int GEM_FlipHWSurface(_THIS, SDL_Surface *surface); +static void GEM_UnlockHWSurface(_THIS, SDL_Surface *surface); +static void GEM_FreeHWSurface(_THIS, SDL_Surface *surface); +static void GEM_UpdateRects(_THIS, int numrects, SDL_Rect *rects); +#if 0 +static int GEM_ToggleFullScreen(_THIS, int on); +#endif + +/* Internal functions */ +static void GEM_FreeBuffers(_THIS); +static void GEM_ClearScreen(_THIS); +static void GEM_ClearRect(_THIS, short *rect); +static void GEM_SetNewPalette(_THIS, Uint16 newpal[256][3]); +static void GEM_LockScreen(_THIS); +static void GEM_UnlockScreen(_THIS); +static void refresh_window(_THIS, int winhandle, short *rect); + +#if SDL_VIDEO_OPENGL +/* OpenGL functions */ +static void GEM_GL_SwapBuffers(_THIS); +#endif + +/* GEM driver bootstrap functions */ + +static int GEM_Available(void) +{ + /* Test if AES available */ + if (appl_init() == -1) + return 0; + + appl_exit(); + return 1; +} + +static void GEM_DeleteDevice(SDL_VideoDevice *device) +{ + SDL_free(device->hidden); + SDL_free(device); +} + +static SDL_VideoDevice *GEM_CreateDevice(int devindex) +{ + SDL_VideoDevice *device; + int vectors_mask; +/* unsigned long dummy;*/ + + /* Initialize all variables that we clean on shutdown */ + device = (SDL_VideoDevice *)SDL_malloc(sizeof(SDL_VideoDevice)); + if ( device ) { + SDL_memset(device, 0, (sizeof *device)); + device->hidden = (struct SDL_PrivateVideoData *) + SDL_malloc((sizeof *device->hidden)); + device->gl_data = (struct SDL_PrivateGLData *) + SDL_malloc((sizeof *device->gl_data)); + } + if ( (device == NULL) || (device->hidden == NULL) ) { + SDL_OutOfMemory(); + if ( device ) { + SDL_free(device); + } + return(0); + } + SDL_memset(device->hidden, 0, (sizeof *device->hidden)); + SDL_memset(device->gl_data, 0, sizeof(*device->gl_data)); + + /* Set the function pointers */ + device->VideoInit = GEM_VideoInit; + device->ListModes = GEM_ListModes; + device->SetVideoMode = GEM_SetVideoMode; + device->SetColors = GEM_SetColors; + device->UpdateRects = NULL /*GEM_UpdateRects*/; + device->VideoQuit = GEM_VideoQuit; + device->AllocHWSurface = GEM_AllocHWSurface; + device->LockHWSurface = GEM_LockHWSurface; + device->UnlockHWSurface = GEM_UnlockHWSurface; + device->FlipHWSurface = GEM_FlipHWSurface; + device->FreeHWSurface = GEM_FreeHWSurface; + device->ToggleFullScreen = NULL /*GEM_ToggleFullScreen*/; + + /* Window manager */ + device->SetCaption = GEM_SetCaption; + device->SetIcon = GEM_SetIcon; + device->IconifyWindow = GEM_IconifyWindow; + device->GrabInput = GEM_GrabInput; + + /* Events */ + device->InitOSKeymap = GEM_InitOSKeymap; + device->PumpEvents = GEM_PumpEvents; + + /* Mouse */ + device->FreeWMCursor = GEM_FreeWMCursor; + device->CreateWMCursor = GEM_CreateWMCursor; + device->ShowWMCursor = GEM_ShowWMCursor; + device->WarpWMCursor = NULL /*GEM_WarpWMCursor*/; + device->CheckMouseMode = GEM_CheckMouseMode; + +#if SDL_VIDEO_OPENGL + /* OpenGL functions */ + device->GL_LoadLibrary = SDL_AtariGL_LoadLibrary; + device->GL_GetProcAddress = SDL_AtariGL_GetProcAddress; + device->GL_GetAttribute = SDL_AtariGL_GetAttribute; + device->GL_MakeCurrent = SDL_AtariGL_MakeCurrent; + device->GL_SwapBuffers = GEM_GL_SwapBuffers; +#endif + + device->hidden->use_dev_mouse = + (SDL_AtariDevMouse_Open()!=0) ? SDL_TRUE : SDL_FALSE; + + vectors_mask = ATARI_XBIOS_JOYSTICKEVENTS; /* XBIOS joystick events */ + if (!(device->hidden->use_dev_mouse)) { + vectors_mask |= ATARI_XBIOS_MOUSEEVENTS; /* XBIOS mouse events */ + } +/* if (Getcookie(C_MiNT, &dummy)==C_FOUND) { + vectors_mask = 0; + }*/ + + SDL_AtariXbios_InstallVectors(vectors_mask); + + device->free = GEM_DeleteDevice; + + return device; +} + +VideoBootStrap GEM_bootstrap = { + GEM_VID_DRIVER_NAME, "Atari GEM video driver", + GEM_Available, GEM_CreateDevice +}; + +static void VDI_ReadExtInfo(_THIS, short *work_out) +{ + unsigned long EdDI_version; + long cookie_EdDI; + Uint16 clut_type; + + /* Read EdDI informations */ + if (Getcookie(C_EdDI, &cookie_EdDI) == C_NOTFOUND) { + return; + } + + EdDI_version = Atari_get_EdDI_version( (void *)cookie_EdDI); + + vq_scrninfo(VDI_handle, work_out); + + VDI_format = work_out[0]; + clut_type = work_out[1]; + + /* With EdDI>=1.1, we can have screen pitch, address and format + * so we can directly write to screen without using vro_cpyfm + */ + if (EdDI_version >= EDDI_11) { + VDI_pitch = work_out[5]; + VDI_screen = (void *) *((unsigned long *) &work_out[6]); + } + + switch(clut_type) { + case VDI_CLUT_HARDWARE: + { + int i; + Uint16 *tmp_p; + + tmp_p = (Uint16 *)&work_out[16]; + + for (i=0;i<256;i++) { + vdi_index[*tmp_p++] = i; + } + } + break; + case VDI_CLUT_SOFTWARE: + { + int component; /* red, green, blue, alpha, overlay */ + int num_bit; + unsigned short *tmp_p; + + /* We can build masks with info here */ + tmp_p = (unsigned short *) &work_out[16]; + for (component=0;component<5;component++) { + for (num_bit=0;num_bit<16;num_bit++) { + unsigned short valeur; + + valeur = *tmp_p++; + + if (valeur == 0xffff) { + continue; + } + + switch(component) { + case 0: + VDI_redmask |= 1<< valeur; + break; + case 1: + VDI_greenmask |= 1<< valeur; + break; + case 2: + VDI_bluemask |= 1<< valeur; + break; + case 3: + VDI_alphamask |= 1<< valeur; + break; + } + } + } + } + + /* Remove lower green bits for Intel endian screen */ + if ((VDI_greenmask == ((7<<13)|3)) || (VDI_greenmask == ((7<<13)|7))) { + VDI_greenmask &= ~(7<<13); + } + break; + case VDI_CLUT_NONE: + break; + } +} + +int GEM_VideoInit(_THIS, SDL_PixelFormat *vformat) +{ + int i, menubar_size; + short work_in[12], work_out[272], dummy; + + /* Open AES (Application Environment Services) */ + if (appl_init() == -1) { + fprintf(stderr,"Can not open AES\n"); + return 1; + } + + /* Read version and features */ + GEM_version = aes_global[0]; + if (GEM_version >= 0x0410) { + short ap_gout[4], errorcode; + + GEM_wfeatures=0; + errorcode=appl_getinfo(AES_WINDOW, &ap_gout[0], &ap_gout[1], &ap_gout[2], &ap_gout[3]); + + if (errorcode==0) { + GEM_wfeatures=ap_gout[0]; + } + } + + /* Ask VDI physical workstation handle opened by AES */ + VDI_handle = graf_handle(&dummy, &dummy, &dummy, &dummy); + if (VDI_handle<1) { + fprintf(stderr,"Wrong VDI handle %d returned by AES\n",VDI_handle); + return 1; + } + + /* Open virtual VDI workstation */ + work_in[0]=Getrez()+2; + for(i = 1; i < 10; i++) + work_in[i] = 1; + work_in[10] = 2; + + v_opnvwk(work_in, &VDI_handle, work_out); + if (VDI_handle == 0) { + fprintf(stderr,"Can not open VDI virtual workstation\n"); + return 1; + } + + /* Read fullscreen size */ + VDI_w = work_out[0] + 1; + VDI_h = work_out[1] + 1; + + /* Read desktop size and position */ + if (!wind_get(DESKTOP_HANDLE, WF_WORKXYWH, &GEM_desk_x, &GEM_desk_y, &GEM_desk_w, &GEM_desk_h)) { + fprintf(stderr,"Can not read desktop properties\n"); + return 1; + } + + /* Read bit depth */ + vq_extnd(VDI_handle, 1, work_out); + VDI_bpp = work_out[4]; + VDI_oldnumcolors=0; + + switch(VDI_bpp) { + case 8: + VDI_pixelsize=1; + break; + case 15: + case 16: + VDI_pixelsize=2; + break; + case 24: + VDI_pixelsize=3; + break; + case 32: + VDI_pixelsize=4; + break; + default: + fprintf(stderr,"%d bits colour depth not supported\n",VDI_bpp); + return 1; + } + + /* Setup hardware -> VDI palette mapping */ + for(i = 16; i < 255; i++) { + vdi_index[i] = i; + } + vdi_index[255] = 1; + + /* Save current palette */ + if (VDI_bpp>8) { + VDI_oldnumcolors=1<<8; + } else { + VDI_oldnumcolors=1<<VDI_bpp; + } + + for(i = 0; i < VDI_oldnumcolors; i++) { + short rgb[3]; + + vq_color(VDI_handle, i, 0, rgb); + + VDI_oldpalette[i][0] = rgb[0]; + VDI_oldpalette[i][1] = rgb[1]; + VDI_oldpalette[i][2] = rgb[2]; + } + VDI_setpalette = GEM_SetNewPalette; + SDL_memcpy(VDI_curpalette,VDI_oldpalette,sizeof(VDI_curpalette)); + + /* Setup screen info */ + GEM_title_name = empty_name; + GEM_icon_name = empty_name; + + GEM_handle = -1; + GEM_locked = SDL_FALSE; + GEM_win_fulled = SDL_FALSE; + GEM_fullscreen = SDL_FALSE; + GEM_lock_redraw = SDL_TRUE; /* Prevent redraw till buffers are setup */ + + VDI_screen = NULL; + VDI_pitch = VDI_w * VDI_pixelsize; + VDI_format = ( (VDI_bpp <= 8) ? VDI_FORMAT_INTER : VDI_FORMAT_PACK); + VDI_redmask = VDI_greenmask = VDI_bluemask = VDI_alphamask = 0; + VDI_ReadExtInfo(this, work_out); + +#ifdef DEBUG_VIDEO_GEM + printf("sdl:video:gem: screen: address=0x%08x, pitch=%d\n", VDI_screen, VDI_pitch); + printf("sdl:video:gem: format=%d\n", VDI_format); + printf("sdl:video:gem: masks: 0x%08x, 0x%08x, 0x%08x, 0x%08x\n", + VDI_alphamask, VDI_redmask, VDI_greenmask, VDI_bluemask + ); +#endif + + /* Setup destination mfdb */ + VDI_dst_mfdb.fd_addr = NULL; + + /* Determine the current screen size */ + this->info.current_w = VDI_w; + this->info.current_h = VDI_h; + + /* Determine the screen depth */ + /* we change this during the SDL_SetVideoMode implementation... */ + vformat->BitsPerPixel = VDI_bpp; + + /* Set mouse cursor to arrow */ + graf_mouse(ARROW, NULL); + GEM_cursor = NULL; + + /* Init chunky to planar routine */ + SDL_Atari_C2pConvert = SDL_Atari_C2pConvert8; + + /* Setup VDI fill functions */ + vsf_color(VDI_handle,0); + vsf_interior(VDI_handle,1); + vsf_perimeter(VDI_handle,0); + + /* Menu bar save buffer */ + menubar_size = GEM_desk_w * GEM_desk_y * VDI_pixelsize; + GEM_menubar=Atari_SysMalloc(menubar_size,MX_PREFTTRAM); + + /* Fill video modes list */ + SDL_modelist[0] = SDL_malloc(sizeof(SDL_Rect)); + SDL_modelist[0]->x = 0; + SDL_modelist[0]->y = 0; + SDL_modelist[0]->w = VDI_w; + SDL_modelist[0]->h = VDI_h; + + SDL_modelist[1] = NULL; + +#if SDL_VIDEO_OPENGL + SDL_AtariGL_InitPointers(this); +#endif + + this->info.wm_available = 1; + + /* We're done! */ + return(0); +} + +SDL_Rect **GEM_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags) +{ + if (format->BitsPerPixel != VDI_bpp) { + return ((SDL_Rect **)NULL); + } + + if (flags & SDL_FULLSCREEN) { + return (SDL_modelist); + } + + return((SDL_Rect **)-1); +} + +static void GEM_FreeBuffers(_THIS) +{ + /* Release buffer */ + if ( GEM_buffer2 ) { + Mfree( GEM_buffer2 ); + GEM_buffer2=NULL; + } + + if ( GEM_buffer1 ) { + Mfree( GEM_buffer1 ); + GEM_buffer1=NULL; + } +} + +static void GEM_ClearRect(_THIS, short *rect) +{ + short oldrgb[3], rgb[3]={0,0,0}; + + vq_color(VDI_handle, vdi_index[0], 0, oldrgb); + vs_color(VDI_handle, vdi_index[0], rgb); + + vsf_color(VDI_handle,0); + vsf_interior(VDI_handle,1); + vsf_perimeter(VDI_handle,0); + v_bar(VDI_handle, rect); + + vs_color(VDI_handle, vdi_index[0], oldrgb); +} + +static void GEM_ClearScreen(_THIS) +{ + short pxy[4]; + + v_hide_c(VDI_handle); + + pxy[0] = pxy[1] = 0; + pxy[2] = VDI_w - 1; + pxy[3] = VDI_h - 1; + GEM_ClearRect(this, pxy); + + v_show_c(VDI_handle, 1); +} + +static void GEM_SetNewPalette(_THIS, Uint16 newpal[256][3]) +{ + int i; + short rgb[3]; + + if (VDI_oldnumcolors==0) + return; + + for(i = 0; i < VDI_oldnumcolors; i++) { + rgb[0] = newpal[i][0]; + rgb[1] = newpal[i][1]; + rgb[2] = newpal[i][2]; + + vs_color(VDI_handle, i, rgb); + } +} + +static void GEM_LockScreen(_THIS) +{ + if (!GEM_locked) { + /* Lock AES */ + wind_update(BEG_UPDATE); + wind_update(BEG_MCTRL); + /* Reserve memory space, used to be sure of compatibility */ + form_dial( FMD_START, 0,0,0,0, 0,0,VDI_w,VDI_h); + + /* Save menu bar */ + if (GEM_menubar) { + MFDB mfdb_src; + short blitcoords[8]; + + mfdb_src.fd_addr=GEM_menubar; + mfdb_src.fd_w=GEM_desk_w; + mfdb_src.fd_h=GEM_desk_y; + mfdb_src.fd_wdwidth=GEM_desk_w>>4; + mfdb_src.fd_nplanes=VDI_bpp; + mfdb_src.fd_stand= + mfdb_src.fd_r1= + mfdb_src.fd_r2= + mfdb_src.fd_r3= 0; + + blitcoords[0] = blitcoords[4] = 0; + blitcoords[1] = blitcoords[5] = 0; + blitcoords[2] = blitcoords[6] = GEM_desk_w-1; + blitcoords[3] = blitcoords[7] = GEM_desk_y-1; + + vro_cpyfm(VDI_handle, S_ONLY, blitcoords, &VDI_dst_mfdb, &mfdb_src); + } + + GEM_locked=SDL_TRUE; + } +} + +static void GEM_UnlockScreen(_THIS) +{ + if (GEM_locked) { + /* Restore menu bar */ + if (GEM_menubar) { + MFDB mfdb_src; + short blitcoords[8]; + + mfdb_src.fd_addr=GEM_menubar; + mfdb_src.fd_w=GEM_desk_w; + mfdb_src.fd_h=GEM_desk_y; + mfdb_src.fd_wdwidth=GEM_desk_w>>4; + mfdb_src.fd_nplanes=VDI_bpp; + mfdb_src.fd_stand= + mfdb_src.fd_r1= + mfdb_src.fd_r2= + mfdb_src.fd_r3= 0; + + blitcoords[0] = blitcoords[4] = 0; + blitcoords[1] = blitcoords[5] = 0; + blitcoords[2] = blitcoords[6] = GEM_desk_w-1; + blitcoords[3] = blitcoords[7] = GEM_desk_y-1; + + vro_cpyfm(VDI_handle, S_ONLY, blitcoords, &mfdb_src, &VDI_dst_mfdb); + } + + /* Restore screen memory, and send REDRAW to all apps */ + form_dial( FMD_FINISH, 0,0,0,0, 0,0,VDI_w,VDI_h); + /* Unlock AES */ + wind_update(END_MCTRL); + wind_update(END_UPDATE); + + GEM_locked=SDL_FALSE; + } +} + +SDL_Surface *GEM_SetVideoMode(_THIS, SDL_Surface *current, + int width, int height, int bpp, Uint32 flags) +{ + Uint32 modeflags, screensize; + SDL_bool use_shadow1, use_shadow2; + + /* width must be multiple of 16, for vro_cpyfm() and c2p_convert() */ + if ((width & 15) != 0) { + width = (width | 15) +1; + } + + /*--- Verify if asked mode can be used ---*/ + if (VDI_bpp != bpp) { + SDL_SetError("%d bpp mode not supported", bpp); + return(NULL); + } + + if (flags & SDL_FULLSCREEN) { + if ((VDI_w < width) || (VDI_h < height)) { + SDL_SetError("%dx%d mode is too large", width, height); + return(NULL); + } + } + + /*--- Allocate the new pixel format for the screen ---*/ + if ( ! SDL_ReallocFormat(current, VDI_bpp, VDI_redmask, VDI_greenmask, VDI_bluemask, VDI_alphamask) ) { + SDL_SetError("Couldn't allocate new pixel format for requested mode"); + return(NULL); + } + + screensize = width * height * VDI_pixelsize; + +#ifdef DEBUG_VIDEO_GEM + printf("sdl:video:gem: setvideomode(): %dx%dx%d = %d\n", width, height, bpp, screensize); +#endif + + /*--- Allocate shadow buffers if needed, and conversion operations ---*/ + GEM_FreeBuffers(this); + + GEM_bufops=0; + use_shadow1=use_shadow2=SDL_FALSE; + if (VDI_screen && (flags & SDL_FULLSCREEN)) { + if (VDI_format==VDI_FORMAT_INTER) { + use_shadow1=SDL_TRUE; + GEM_bufops = B2S_C2P_1TOS; + } + } else { + use_shadow1=SDL_TRUE; + if (VDI_format==VDI_FORMAT_PACK) { + GEM_bufops = B2S_VROCPYFM_1TOS; + } else { + use_shadow2=SDL_TRUE; + GEM_bufops = B2S_C2P_1TO2|B2S_VROCPYFM_2TOS; + } + } + + if (use_shadow1) { + GEM_buffer1 = Atari_SysMalloc(screensize, MX_PREFTTRAM); + if (GEM_buffer1==NULL) { + SDL_SetError("Can not allocate %d KB for frame buffer", screensize>>10); + return NULL; + } + SDL_memset(GEM_buffer1, 0, screensize); +#ifdef DEBUG_VIDEO_GEM + printf("sdl:video:gem: setvideomode(): allocated buffer 1\n"); +#endif + } + + if (use_shadow2) { + GEM_buffer2 = Atari_SysMalloc(screensize, MX_PREFTTRAM); + if (GEM_buffer2==NULL) { + SDL_SetError("Can not allocate %d KB for shadow buffer", screensize>>10); + return NULL; + } + SDL_memset(GEM_buffer2, 0, screensize); +#ifdef DEBUG_VIDEO_GEM + printf("sdl:video:gem: setvideomode(): allocated buffer 2\n"); +#endif + } + + /*--- Initialize screen ---*/ + modeflags = SDL_PREALLOC; + if (VDI_bpp == 8) { + modeflags |= SDL_HWPALETTE; + } + + if (flags & SDL_FULLSCREEN) { + GEM_LockScreen(this); + + GEM_ClearScreen(this); + + modeflags |= SDL_FULLSCREEN; + if (VDI_screen && (VDI_format==VDI_FORMAT_PACK) && !use_shadow1) { + modeflags |= SDL_HWSURFACE; + } else { + modeflags |= SDL_SWSURFACE; + } + + GEM_fullscreen = SDL_TRUE; + } else { + int old_win_type; + short x2,y2,w2,h2; + + GEM_UnlockScreen(this); + + /* Set window gadgets */ + old_win_type = GEM_win_type; + if (!(flags & SDL_NOFRAME)) { + GEM_win_type=NAME|MOVER|CLOSER|SMALLER; + if (flags & SDL_RESIZABLE) { + GEM_win_type |= FULLER|SIZER; + modeflags |= SDL_RESIZABLE; + } + } else { + GEM_win_type=0; + modeflags |= SDL_NOFRAME; + } + modeflags |= SDL_SWSURFACE; + + /* Recreate window ? only for different widget or non-created window */ + if ((old_win_type != GEM_win_type) || (GEM_handle < 0)) { + /* Calculate window size */ + if (!wind_calc(WC_BORDER, GEM_win_type, 0,0,width,height, &x2,&y2,&w2,&h2)) { + GEM_FreeBuffers(this); + SDL_SetError("Can not calculate window attributes"); + return NULL; + } + + /* Center window */ + x2 = (GEM_desk_w-w2)>>1; + y2 = (GEM_desk_h-h2)>>1; + if (x2<0) { + x2 = 0; + } + if (y2<0) { + y2 = 0; + } + x2 += GEM_desk_x; + y2 += GEM_desk_y; + + /* Destroy existing window */ + if (GEM_handle >= 0) { + wind_close(GEM_handle); + wind_delete(GEM_handle); + } + + /* Create window */ + GEM_handle=wind_create(GEM_win_type, x2,y2,w2,h2); + if (GEM_handle<0) { + GEM_FreeBuffers(this); + SDL_SetError("Can not create window"); + return NULL; + } + +#ifdef DEBUG_VIDEO_GEM + printf("sdl:video:gem: handle=%d\n", GEM_handle); +#endif + + /* Setup window name */ + wind_set(GEM_handle,WF_NAME,(short)(((unsigned long)GEM_title_name)>>16),(short)(((unsigned long)GEM_title_name) & 0xffff),0,0); + GEM_refresh_name = SDL_FALSE; + + /* Open the window */ + wind_open(GEM_handle,x2,y2,w2,h2); + } else { + /* Resize window to fit asked video mode */ + wind_get (GEM_handle, WF_WORKXYWH, &x2,&y2,&w2,&h2); + if (wind_calc(WC_BORDER, GEM_win_type, x2,y2,width,height, &x2,&y2,&w2,&h2)) { + wind_set (GEM_handle, WF_CURRXYWH, x2,y2,w2,h2); + } + } + + GEM_fullscreen = SDL_FALSE; + } + + /* Set up the new mode framebuffer */ + current->w = width; + current->h = height; + if (use_shadow1) { + current->pixels = GEM_buffer1; + current->pitch = width * VDI_pixelsize; + } else { + current->pixels = VDI_screen; + current->pitch = VDI_pitch; + } + +#if SDL_VIDEO_OPENGL + if (flags & SDL_OPENGL) { + if (!SDL_AtariGL_Init(this, current)) { + GEM_FreeBuffers(this); + SDL_SetError("Can not create OpenGL context"); + return NULL; + } + + modeflags |= SDL_OPENGL; + } +#endif + + current->flags = modeflags; + +#ifdef DEBUG_VIDEO_GEM + printf("sdl:video:gem: surface: %dx%d\n", current->w, current->h); +#endif + + this->UpdateRects = GEM_UpdateRects; + GEM_lock_redraw = SDL_FALSE; /* Enable redraw */ + + /* We're done */ + return(current); +} + +static int GEM_AllocHWSurface(_THIS, SDL_Surface *surface) +{ + return -1; +} + +static void GEM_FreeHWSurface(_THIS, SDL_Surface *surface) +{ + return; +} + +static int GEM_LockHWSurface(_THIS, SDL_Surface *surface) +{ + return(0); +} + +static void GEM_UnlockHWSurface(_THIS, SDL_Surface *surface) +{ + return; +} + +static void GEM_UpdateRectsFullscreen(_THIS, int numrects, SDL_Rect *rects) +{ + SDL_Surface *surface; + int i, surf_width; + + surface = this->screen; + /* Need to be a multiple of 16 pixels */ + surf_width=surface->w; + if ((surf_width & 15) != 0) { + surf_width = (surf_width | 15) + 1; + } + + if (GEM_bufops & (B2S_C2P_1TO2|B2S_C2P_1TOS)) { + void *destscr; + int destpitch; + + if (GEM_bufops & B2S_C2P_1TOS) { + destscr = VDI_screen; + destpitch = VDI_pitch; + } else { + destscr = GEM_buffer2; + destpitch = surface->pitch; + } + + for (i=0;i<numrects;i++) { + void *source,*destination; + int x1,x2; + + x1 = rects[i].x & ~15; + x2 = rects[i].x+rects[i].w; + if (x2 & 15) { + x2 = (x2 | 15) +1; + } + + source = surface->pixels; + source += surface->pitch * rects[i].y; + source += x1; + + destination = destscr; + destination += destpitch * rects[i].y; + destination += x1; + + SDL_Atari_C2pConvert( + source, destination, + x2-x1, rects[i].h, + SDL_FALSE, + surface->pitch, destpitch + ); + } + } + + if (GEM_bufops & (B2S_VROCPYFM_1TOS|B2S_VROCPYFM_2TOS)) { + MFDB mfdb_src; + short blitcoords[8]; + + mfdb_src.fd_addr=surface->pixels; + mfdb_src.fd_w=surf_width; + mfdb_src.fd_h=surface->h; + mfdb_src.fd_wdwidth= (surface->pitch/VDI_pixelsize) >> 4; + mfdb_src.fd_nplanes=surface->format->BitsPerPixel; + mfdb_src.fd_stand= + mfdb_src.fd_r1= + mfdb_src.fd_r2= + mfdb_src.fd_r3= 0; + if (GEM_bufops & B2S_VROCPYFM_2TOS) { + mfdb_src.fd_addr=GEM_buffer2; + } + + for ( i=0; i<numrects; ++i ) { + blitcoords[0] = blitcoords[4] = rects[i].x; + blitcoords[1] = blitcoords[5] = rects[i].y; + blitcoords[2] = blitcoords[6] = rects[i].x + rects[i].w - 1; + blitcoords[3] = blitcoords[7] = rects[i].y + rects[i].h - 1; + + vro_cpyfm(VDI_handle, S_ONLY, blitcoords, &mfdb_src, &VDI_dst_mfdb); + } + } +} + +static void GEM_UpdateRectsWindowed(_THIS, int numrects, SDL_Rect *rects) +{ + short pxy[4], wind_pxy[4]; + int i; + + if (wind_get(GEM_handle, WF_WORKXYWH, &wind_pxy[0], &wind_pxy[1], &wind_pxy[2], &wind_pxy[3])==0) { + return; + } + + for ( i=0; i<numrects; ++i ) { + pxy[0] = wind_pxy[0] + rects[i].x; + pxy[1] = wind_pxy[1] + rects[i].y; + pxy[2] = rects[i].w; + pxy[3] = rects[i].h; + + GEM_wind_redraw(this, GEM_handle, pxy); + } +} + +static void GEM_UpdateRects(_THIS, int numrects, SDL_Rect *rects) +{ + SDL_Surface *surface; + + if (GEM_lock_redraw) { + return; + } + + surface = this->screen; + + if (surface->flags & SDL_FULLSCREEN) { + GEM_UpdateRectsFullscreen(this, numrects, rects); + } else { + GEM_UpdateRectsWindowed(this, numrects, rects); + } +} + +static int GEM_FlipHWSurfaceFullscreen(_THIS, SDL_Surface *surface) +{ + int surf_width; + + /* Need to be a multiple of 16 pixels */ + surf_width=surface->w; + if ((surf_width & 15) != 0) { + surf_width = (surf_width | 15) + 1; + } + + if (GEM_bufops & (B2S_C2P_1TO2|B2S_C2P_1TOS)) { + void *destscr; + int destpitch; + + if (GEM_bufops & B2S_C2P_1TOS) { + destscr = VDI_screen; + destpitch = VDI_pitch; + } else { + destscr = GEM_buffer2; + destpitch = surface->pitch; + } + + SDL_Atari_C2pConvert( + surface->pixels, destscr, + surf_width, surface->h, + SDL_FALSE, + surface->pitch, destpitch + ); + } + + if (GEM_bufops & (B2S_VROCPYFM_1TOS|B2S_VROCPYFM_2TOS)) { + MFDB mfdb_src; + short blitcoords[8]; + + mfdb_src.fd_w=surf_width; + mfdb_src.fd_h=surface->h; + mfdb_src.fd_wdwidth=mfdb_src.fd_w >> 4; + mfdb_src.fd_nplanes=surface->format->BitsPerPixel; + mfdb_src.fd_stand= + mfdb_src.fd_r1= + mfdb_src.fd_r2= + mfdb_src.fd_r3= 0; + if (GEM_bufops & B2S_VROCPYFM_1TOS) { + mfdb_src.fd_addr=surface->pixels; + } else { + mfdb_src.fd_addr=GEM_buffer2; + } + + blitcoords[0] = blitcoords[4] = 0; + blitcoords[1] = blitcoords[5] = 0; + blitcoords[2] = blitcoords[6] = surface->w - 1; + blitcoords[3] = blitcoords[7] = surface->h - 1; + + vro_cpyfm(VDI_handle, S_ONLY, blitcoords, &mfdb_src, &VDI_dst_mfdb); + } + + return(0); +} + +static int GEM_FlipHWSurfaceWindowed(_THIS, SDL_Surface *surface) +{ + short pxy[8]; + + /* Update the whole window */ + wind_get(GEM_handle, WF_WORKXYWH, &pxy[0], &pxy[1], &pxy[2], &pxy[3]); + + GEM_wind_redraw(this, GEM_handle, pxy); + + return(0); +} + +static int GEM_FlipHWSurface(_THIS, SDL_Surface *surface) +{ + if (GEM_lock_redraw) { + return(0); + } + + if (surface->flags & SDL_FULLSCREEN) { + return GEM_FlipHWSurfaceFullscreen(this, surface); + } else { + return GEM_FlipHWSurfaceWindowed(this, surface); + } +} + +static int GEM_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors) +{ + int i; + SDL_Surface *surface; + +#ifdef DEBUG_VIDEO_GEM + printf("sdl:video:gem: setcolors()\n"); +#endif + + /* Do not change palette in True Colour */ + surface = this->screen; + if (surface->format->BitsPerPixel > 8) { + return 1; + } + + for(i = 0; i < ncolors; i++) + { + int r, g, b; + short rgb[3]; + + r = colors[i].r; + g = colors[i].g; + b = colors[i].b; + + rgb[0] = VDI_curpalette[i][0] = (1000 * r) / 255; + rgb[1] = VDI_curpalette[i][1] =(1000 * g) / 255; + rgb[2] = VDI_curpalette[i][2] =(1000 * b) / 255; + + vs_color(VDI_handle, vdi_index[firstcolor+i], rgb); + } + + return(1); +} + +#if 0 +static int GEM_ToggleFullScreen(_THIS, int on) +{ + if (on) { + GEM_LockScreen(this); + } else { + GEM_UnlockScreen(this); + } + + return(1); +} +#endif + +/* Note: If we are terminated, this could be called in the middle of + another SDL video routine -- notably UpdateRects. +*/ +void GEM_VideoQuit(_THIS) +{ + SDL_AtariXbios_RestoreVectors(); + if (GEM_usedevmouse) { + SDL_AtariDevMouse_Close(); + } + + GEM_FreeBuffers(this); + +#if SDL_VIDEO_OPENGL + if (gl_active) { + SDL_AtariGL_Quit(this, SDL_TRUE); + } +#endif + + /* Destroy window */ + if (GEM_handle>=0) { + wind_close(GEM_handle); + wind_delete(GEM_handle); + GEM_handle=-1; + } + + GEM_UnlockScreen(this); + if (GEM_menubar) { + Mfree(GEM_menubar); + GEM_menubar=NULL; + } + + appl_exit(); + + GEM_SetNewPalette(this, VDI_oldpalette); + + /* Close VDI workstation */ + if (VDI_handle) { + v_clsvwk(VDI_handle); + } + + /* Free mode list */ + if (SDL_modelist[0]) { + SDL_free(SDL_modelist[0]); + SDL_modelist[0]=NULL; + } + + this->screen->pixels = NULL; +} + +void GEM_wind_redraw(_THIS, int winhandle, short *inside) +{ + short todo[4]; + + /* Tell AES we are going to update */ + wind_update(BEG_UPDATE); + + v_hide_c(VDI_handle); + + /* Browse the rectangle list to redraw */ + if (wind_get(winhandle, WF_FIRSTXYWH, &todo[0], &todo[1], &todo[2], &todo[3])!=0) { + + while (todo[2] && todo[3]) { + + if (rc_intersect((GRECT *)inside,(GRECT *)todo)) { + todo[2] += todo[0]-1; + todo[3] += todo[1]-1; + refresh_window(this, winhandle, todo); + } + + if (wind_get(winhandle, WF_NEXTXYWH, &todo[0], &todo[1], &todo[2], &todo[3])==0) { + break; + } + } + + } + + /* Update finished */ + wind_update(END_UPDATE); + + v_show_c(VDI_handle,1); +} + +static void refresh_window(_THIS, int winhandle, short *rect) +{ + MFDB mfdb_src; + short pxy[8],wind_pxy[8]; + SDL_Surface *surface; + int iconified; + + /* Is window iconified ? */ + iconified = 0; +/* if (GEM_wfeatures & (1<<WF_ICONIFY))*/ { + if (wind_get(winhandle, WF_ICONIFY, &wind_pxy[0], &wind_pxy[1], &wind_pxy[2], &wind_pxy[3])!=0) { + iconified = wind_pxy[0]; + } + } + + if (wind_get(winhandle, WF_WORKXYWH, &wind_pxy[0], &wind_pxy[1], &wind_pxy[2], &wind_pxy[3])==0) { + return; + } + + if (iconified && GEM_icon) { + short icon_rect[4], dst_rect[4]; + short iconx,icony; + + surface = GEM_icon; + + GEM_ClearRect(this, rect); + + /* Calculate centered icon(x,y,w,h) relative to window */ + iconx = (wind_pxy[2]-surface->w)>>1; + icony = (wind_pxy[3]-surface->h)>>1; + + icon_rect[0] = iconx; + icon_rect[1] = icony; + icon_rect[2] = surface->w; + icon_rect[3] = surface->h; + + /* Calculate redraw rectangle(x,y,w,h) relative to window */ + dst_rect[0] = rect[0]-wind_pxy[0]; + dst_rect[1] = rect[1]-wind_pxy[1]; + dst_rect[2] = rect[2]-rect[0]+1; + dst_rect[3] = rect[3]-rect[1]+1; + + /* Does the icon rectangle must be redrawn ? */ + if (!rc_intersect((GRECT *)icon_rect, (GRECT *)dst_rect)) { + return; + } + +#if DEBUG_VIDEO_GEM + printf("sdl:video:gem: clip(0,0,%d,%d) to (%d,%d,%d,%d)\n", + surface->w-1,surface->h-1, dst_rect[0],dst_rect[1],dst_rect[2],dst_rect[3]); + printf("sdl:video:gem: icon(%d,%d,%d,%d)\n", + icon_rect[0], icon_rect[1], icon_rect[2], icon_rect[3]); + printf("sdl:video:gem: refresh_window(): draw icon\n"); +#endif + + /* Calculate icon(x1,y1,x2,y2) relative to screen */ + icon_rect[0] += wind_pxy[0]; + icon_rect[1] += wind_pxy[1]; + icon_rect[2] += icon_rect[0]-1; + icon_rect[3] += icon_rect[1]-1; + + /* Calculate intersection rectangle to redraw */ + pxy[4]=pxy[0]=MAX(icon_rect[0],rect[0]); + pxy[5]=pxy[1]=MAX(icon_rect[1],rect[1]); + pxy[6]=pxy[2]=MIN(icon_rect[2],rect[2]); + pxy[7]=pxy[3]=MIN(icon_rect[3],rect[3]); + + /* Calculate icon source image pos relative to window */ + pxy[0] -= wind_pxy[0]+iconx; + pxy[1] -= wind_pxy[1]+icony; + pxy[2] -= wind_pxy[0]+iconx; + pxy[3] -= wind_pxy[1]+icony; + + } else { + surface = this->screen; + +#if DEBUG_VIDEO_GEM + printf("sdl:video:gem: refresh_window(): draw frame buffer\n"); +#endif + + /* Redraw all window content */ + pxy[0] = rect[0]-wind_pxy[0]; + pxy[1] = rect[1]-wind_pxy[1]; + pxy[2] = rect[2]-wind_pxy[0]; + pxy[3] = rect[3]-wind_pxy[1]; + + pxy[4] = rect[0]; + pxy[5] = rect[1]; + pxy[6] = rect[2]; + pxy[7] = rect[3]; + } + + if (GEM_bufops & B2S_C2P_1TO2) { + void *src, *dest; + int x1,x2; + + x1 = (rect[0]-wind_pxy[0]) & ~15; + x2 = rect[2]-wind_pxy[0]; + if (x2 & 15) { + x2 = (x2 | 15) +1; + } + + src = surface->pixels; + src += surface->pitch * (rect[1]-wind_pxy[1]); + src += x1; + + dest = GEM_buffer2; + dest += surface->pitch * (rect[1]-wind_pxy[1]); + dest += x1; + + SDL_Atari_C2pConvert( + src, dest, + x2-x1, rect[3]-rect[1]+1, + SDL_FALSE, + surface->pitch, surface->pitch + ); + } + + mfdb_src.fd_addr=surface->pixels; + { + int width; + + /* Need to be a multiple of 16 pixels */ + width=surface->w; + if ((width & 15) != 0) { + width = (width | 15) + 1; + } + mfdb_src.fd_w=width; + } + mfdb_src.fd_h=surface->h; + mfdb_src.fd_nplanes=surface->format->BitsPerPixel; + mfdb_src.fd_wdwidth=mfdb_src.fd_w>>4; + mfdb_src.fd_stand= + mfdb_src.fd_r1= + mfdb_src.fd_r2= + mfdb_src.fd_r3= 0; + + if (GEM_bufops & B2S_VROCPYFM_2TOS) { + mfdb_src.fd_addr=GEM_buffer2; + } + +#if DEBUG_VIDEO_GEM + printf("sdl:video:gem: redraw %dx%d: (%d,%d,%d,%d) to (%d,%d,%d,%d)\n", + surface->w, surface->h, + pxy[0],pxy[1],pxy[2],pxy[3], + pxy[4],pxy[5],pxy[6],pxy[7] + ); +#endif + + vro_cpyfm( VDI_handle, S_ONLY, pxy, &mfdb_src, &VDI_dst_mfdb); +} + +#if SDL_VIDEO_OPENGL + +static void GEM_GL_SwapBuffers(_THIS) +{ + SDL_AtariGL_SwapBuffers(this); + GEM_FlipHWSurface(this, this->screen); +} + +#endif diff --git a/3rdparty/SDL/src/video/gem/SDL_gemvideo.h b/3rdparty/SDL/src/video/gem/SDL_gemvideo.h new file mode 100644 index 0000000..f3a1954 --- /dev/null +++ b/3rdparty/SDL/src/video/gem/SDL_gemvideo.h @@ -0,0 +1,191 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#ifndef _SDL_gemvideo_h +#define _SDL_gemvideo_h + +#include "SDL_mutex.h" +#include "../SDL_sysvideo.h" + +/* The implementation dependent data for the window manager cursor */ +struct WMcursor { + MFORM *mform_p; +}; + +/* Hidden "this" pointer for the video functions */ +#define _THIS SDL_VideoDevice *this + +/* Functions prototypes */ +void GEM_wind_redraw(_THIS, int winhandle, short *inside); + +/* Private display data */ + +#define B2S_C2P_1TO2 (1<<0) /* C2P convert buffer 1 to buffer 2 */ +#define B2S_C2P_1TOS (1<<1) /* C2P convert buffer 1 to screen */ +#define B2S_VROCPYFM_1TOS (1<<2) /* vro_cpyfm() buffer 1 to screen */ +#define B2S_VROCPYFM_2TOS (1<<3) /* vro_cpyfm() buffer 2 to screen */ + +#define SDL_NUMMODES 1 /* Fullscreen */ + +struct SDL_PrivateVideoData { + Uint16 buf2scr_ops; /* Operations to get buffer to screen */ + void *buffer1; /* Our shadow buffers */ + void *buffer2; + + /* VDI infos */ + short vdi_handle; /* VDI handle */ + short full_w, full_h; /* Fullscreen size */ + short bpp; /* Colour depth */ + short pixelsize; /* Bytes per pixel */ + short old_numcolors; /* Number of colors in saved palette */ + Uint16 pitch; /* Line length */ + Uint16 format; /* Screen format */ + void *screen; /* Screen address */ + Uint32 red, green, blue, alpha; /* Screen components */ + Uint32 screensize; + short blit_coords[8]; /* Coordinates for bitblt */ + MFDB src_mfdb, dst_mfdb; /* VDI MFDB for bitblt */ + Uint16 old_palette[256][3]; /* Saved current palette */ + Uint16 cur_palette[256][3]; /* SDL application palette */ + /* Function to set/restore palette */ + void (*setpalette)(_THIS, Uint16 newpal[256][3]); + + /* GEM infos */ + short desk_x, desk_y; /* Desktop properties */ + short desk_w, desk_h; + short win_handle; /* Our window handle */ + int window_type; /* Window type */ + const char *title_name; /* Window title */ + const char *icon_name; /* Icon title */ + short version; /* AES version */ + short wfeatures; /* AES window features */ + SDL_bool refresh_name; /* Change window title ? */ + SDL_bool window_fulled; /* Window maximized ? */ + SDL_bool mouse_relative; /* Report relative mouse movement */ + SDL_bool locked; /* AES locked for fullscreen ? */ + SDL_bool lock_redraw; /* Prevent redraw till buffers are setup */ + short message[8]; /* To self-send an AES message */ + void *menubar; /* Menu bar save buffer when going fullscreen */ + SDL_bool use_dev_mouse; /* Use /dev/mouse ? */ + WMcursor *cursor; /* To restore cursor when leaving/entering window */ + + SDL_bool fullscreen; /* Fullscreen or windowed mode ? */ + SDL_Rect *SDL_modelist[SDL_NUMMODES+1]; /* Mode list */ + SDL_Surface *icon; /* The icon */ +}; + +/* Hidden structure -> variables names */ +#define VDI_handle (this->hidden->vdi_handle) +#define VDI_w (this->hidden->full_w) +#define VDI_h (this->hidden->full_h) +#define VDI_bpp (this->hidden->bpp) +#define VDI_pixelsize (this->hidden->pixelsize) +#define VDI_oldnumcolors (this->hidden->old_numcolors) +#define VDI_oldpalette (this->hidden->old_palette) +#define VDI_curpalette (this->hidden->cur_palette) +#define VDI_setpalette (this->hidden->setpalette) +#define VDI_pitch (this->hidden->pitch) +#define VDI_format (this->hidden->format) +#define VDI_screen (this->hidden->screen) +#define VDI_redmask (this->hidden->red) +#define VDI_greenmask (this->hidden->green) +#define VDI_bluemask (this->hidden->blue) +#define VDI_alphamask (this->hidden->alpha) +#define VDI_screensize (this->hidden->screensize) +#define VDI_src_mfdb (this->hidden->src_mfdb) +#define VDI_dst_mfdb (this->hidden->dst_mfdb) +#define VDI_blit_coords (this->hidden->blit_coords) + +#define GEM_desk_x (this->hidden->desk_x) +#define GEM_desk_y (this->hidden->desk_y) +#define GEM_desk_w (this->hidden->desk_w) +#define GEM_desk_h (this->hidden->desk_h) +#define GEM_handle (this->hidden->win_handle) +#define GEM_win_type (this->hidden->window_type) +#define GEM_title_name (this->hidden->title_name) +#define GEM_icon_name (this->hidden->icon_name) +#define GEM_refresh_name (this->hidden->refresh_name) +#define GEM_version (this->hidden->version) +#define GEM_wfeatures (this->hidden->wfeatures) +#define GEM_win_fulled (this->hidden->window_fulled) +#define GEM_mouse_relative (this->hidden->mouse_relative) +#define GEM_locked (this->hidden->locked) +#define GEM_lock_redraw (this->hidden->lock_redraw) +#define GEM_message (this->hidden->message) +#define SDL_modelist (this->hidden->SDL_modelist) +#define GEM_icon (this->hidden->icon) +#define GEM_fullscreen (this->hidden->fullscreen) +#define GEM_menubar (this->hidden->menubar) +#define GEM_usedevmouse (this->hidden->use_dev_mouse) +#define GEM_cursor (this->hidden->cursor) + +#define GEM_buffer1 (this->hidden->buffer1) +#define GEM_buffer2 (this->hidden->buffer2) +#define GEM_bufops (this->hidden->buf2scr_ops) + +#define VDI_FBMASK(amask, rmask, gmask, bmask) \ + VDI_alphamask = (amask); \ + VDI_redmask = (rmask); \ + VDI_greenmask = (gmask); \ + VDI_bluemask = (bmask); + +/* + Possible buffer to screen operations: + + TC: 8 (chunky),15,16,24,32 bpp + 8I: 8 bpp planes + FB: screen framebuffer address available + FS: fullscreen + + TC, FB, FS: + - draw to screen + 8I, FB, FS: + - draw to buffer 1 + - C2P from buffer 1 to screen + + TC, !FB, FS: + - draw to buffer 1 + - vro_cpyfm() from buffer 1 to screen + 8I, !FB, FS: + - draw to buffer 1 + - C2P from buffer 1 to buffer 2 + - vro_cpyfm() from buffer 2 to screen + + TC, FB, !FS: + - draw to buffer 1 + - vro_cpyfm() from buffer 1 to screen + 8I, FB, !FS: + - draw to buffer 1 + - C2P from buffer 1 to buffer 2 + - vro_cpyfm() from buffer 2 to screen + + TC, !FB, !FS: + - draw to buffer 1 + - vro_cpyfm() from buffer 1 to screen + 8I, !FB, !FS: + - draw to buffer 1 + - C2P from buffer 1 to buffer 2 + - vro_cpyfm() from buffer 2 to screen +*/ + +#endif /* _SDL_gemvideo_h */ diff --git a/3rdparty/SDL/src/video/gem/SDL_gemwm.c b/3rdparty/SDL/src/video/gem/SDL_gemwm.c new file mode 100644 index 0000000..10776fd --- /dev/null +++ b/3rdparty/SDL/src/video/gem/SDL_gemwm.c @@ -0,0 +1,116 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* + GEM SDL video driver + Window manager functions + + Patrice Mandin +*/ + +/* Mint includes */ +#include <gem.h> + +#include "SDL_gemwm_c.h" + +/* Defines */ + +#define ICONWIDTH 64 +#define ICONHEIGHT 64 + +/* Functions */ + +void GEM_SetCaption(_THIS, const char *title, const char *icon) +{ + if (title) { + GEM_title_name = title; + GEM_refresh_name = SDL_TRUE; + } + + if (icon) { + GEM_icon_name = icon; + GEM_refresh_name = SDL_TRUE; + } +} + +void GEM_SetIcon(_THIS, SDL_Surface *icon, Uint8 *mask) +{ + SDL_Surface *sicon; + SDL_Rect bounds; + +#if 0 + if ((GEM_wfeatures & (1<<WF_ICONIFY))==0) { + return; + } +#endif + + if (icon == NULL) { + return; + } + + /* Convert icon to the screen format */ + sicon = SDL_CreateRGBSurface(SDL_SWSURFACE, icon->w, icon->h, + VDI_bpp, VDI_redmask, VDI_greenmask, VDI_bluemask, 0); + if ( sicon == NULL ) { + return; + } + + bounds.x = 0; + bounds.y = 0; + bounds.w = icon->w; + bounds.h = icon->h; + if ( SDL_LowerBlit(icon, &bounds, sicon, &bounds) < 0 ) { + SDL_FreeSurface(sicon); + return; + } + + GEM_icon = sicon; +} + +int GEM_IconifyWindow(_THIS) +{ + if ((GEM_wfeatures & (1<<WF_ICONIFY))==0) + return 0; + + GEM_message[0] = WM_ICONIFY; + GEM_message[1] = gl_apid; + GEM_message[2] = 0; + GEM_message[3] = GEM_handle; + GEM_message[4] = 0; + GEM_message[5] = GEM_desk_h-ICONHEIGHT; + GEM_message[6] = ICONWIDTH; + GEM_message[7] = ICONHEIGHT; + + appl_write(gl_apid, sizeof(GEM_message), GEM_message); + + return 1; +} + +SDL_GrabMode GEM_GrabInput(_THIS, SDL_GrabMode mode) +{ + if (this->screen == NULL) { + return SDL_GRAB_OFF; + } + + return mode; +} diff --git a/3rdparty/SDL/src/video/gem/SDL_gemwm_c.h b/3rdparty/SDL/src/video/gem/SDL_gemwm_c.h new file mode 100644 index 0000000..59828b7 --- /dev/null +++ b/3rdparty/SDL/src/video/gem/SDL_gemwm_c.h @@ -0,0 +1,37 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* + * GEM SDL video driver implementation + * Window manager functions + * + * Patrice Mandin + */ + +#include "SDL_gemvideo.h" + +/* Functions prototypes */ +extern void GEM_SetCaption(_THIS, const char *title, const char *icon); +extern void GEM_SetIcon(_THIS, SDL_Surface *icon, Uint8 *mask); +extern int GEM_IconifyWindow(_THIS); +extern SDL_GrabMode GEM_GrabInput(_THIS, SDL_GrabMode mode); diff --git a/3rdparty/SDL/src/video/ggi/SDL_ggievents.c b/3rdparty/SDL/src/video/ggi/SDL_ggievents.c new file mode 100644 index 0000000..d963fe1 --- /dev/null +++ b/3rdparty/SDL/src/video/ggi/SDL_ggievents.c @@ -0,0 +1,264 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* Handle the event stream, converting GGI events into SDL events */ + +#include <sys/types.h> +#include <sys/time.h> +#include <unistd.h> +#include <fcntl.h> +#include <termios.h> + +#include <ggi/keyboard.h> + +#include "SDL_ggikeys.h" + +#include "SDL.h" +#include "../SDL_sysvideo.h" +#include "../../events/SDL_sysevents.h" +#include "../../events/SDL_events_c.h" +#include "SDL_ggivideo.h" +#include "SDL_ggievents_c.h" + +/* The translation tables from a GGI keycode to a SDL keysym */ +static SDLKey keymap[128]; +static SDL_keysym *GGI_TranslateKey(ggi_event *ev, SDL_keysym *keysym); + +static int posted = 0; + +void GGI_PumpEvents(_THIS) +{ + struct timeval *tvp, tv = { 0, 0 }; + ggi_event ev; + + tvp = &tv; + +/* ggiFlush(VIS); */ + + while (ggiEventPoll(VIS, emAll, tvp)) +/* while (ggiEventPoll(VIS, (emKeyboard | emPointer | emCommand), tvp)) */ + { + int queueevent_mouse = 0, queueevent_kbd = 0; + static int buttons = 0; + static int mouse_x = 0, mouse_y = 0, mouse_z = 0; + int x = 0, y = 0, z = 0, rx = 0, ry = 0, rz = 0; + int pressed_mouse, pressed_kbd; + SDL_keysym keysym; + + posted = 0; + + /* FIXME: We do not actually want all events, only + * mouse and keyboard events. Having to handle all + * events will slow things down. */ + + ggiEventRead(VIS, &ev, emAll); +/* ggiEventRead(VIS, &ev, (emKeyboard | emPointer | emCommand)); */ + + switch (ev.any.type) + { + case evPtrRelative: + x = ev.pmove.x; + y = ev.pmove.y; + z = ev.pmove.wheel; + posted += SDL_PrivateMouseMotion(0, 1, x, y); + break; + case evPtrAbsolute: + if (mouse_x != ev.pmove.x || mouse_y != ev.pmove.y || mouse_z != ev.pmove.wheel) + { + x = ev.pmove.x - mouse_x; + y = ev.pmove.y - mouse_y; + z = ev.pmove.wheel - mouse_z; + mouse_x = ev.pmove.x; + mouse_y = ev.pmove.y; + mouse_z = ev.pmove.wheel; + posted += SDL_PrivateMouseMotion(0, 1, x, y); + } + break; + case evPtrButtonPress: + posted += SDL_PrivateMouseButton(SDL_PRESSED, ev.pbutton.button, 0, 0); + break; + case evPtrButtonRelease: + posted += SDL_PrivateMouseButton(SDL_RELEASED, ev.pbutton.button, 0, 0); + break; + case evKeyPress: + case evKeyRepeat: + posted += SDL_PrivateKeyboard(SDL_PRESSED, GGI_TranslateKey(&ev, &keysym)); + break; + case evKeyRelease: + posted += SDL_PrivateKeyboard(SDL_RELEASED, GGI_TranslateKey(&ev, &keysym)); + break; + case evCommand: + fprintf(stderr, "Command event %x recieved\n", ev.cmd.code); + break; + default: + fprintf(stderr, "Unhandled event type %d\n", ev.any.type); + break; + } + } + +} + +void GGI_InitOSKeymap(_THIS) +{ + int i; + + /* Initialize the GGI key translation table */ + for ( i=0; i<SDL_arraysize(keymap); ++i ) + keymap[i] = SDLK_UNKNOWN; + + keymap[SCANCODE_ESCAPE] = SDLK_ESCAPE; + keymap[SCANCODE_1] = SDLK_1; + keymap[SCANCODE_2] = SDLK_2; + keymap[SCANCODE_3] = SDLK_3; + keymap[SCANCODE_4] = SDLK_4; + keymap[SCANCODE_5] = SDLK_5; + keymap[SCANCODE_6] = SDLK_6; + keymap[SCANCODE_7] = SDLK_7; + keymap[SCANCODE_8] = SDLK_8; + keymap[SCANCODE_9] = SDLK_9; + keymap[SCANCODE_0] = SDLK_0; + keymap[SCANCODE_MINUS] = SDLK_MINUS; + keymap[SCANCODE_EQUAL] = SDLK_EQUALS; + keymap[SCANCODE_BACKSPACE] = SDLK_BACKSPACE; + keymap[SCANCODE_TAB] = SDLK_TAB; + keymap[SCANCODE_Q] = SDLK_q; + keymap[SCANCODE_W] = SDLK_w; + keymap[SCANCODE_E] = SDLK_e; + keymap[SCANCODE_R] = SDLK_r; + keymap[SCANCODE_T] = SDLK_t; + keymap[SCANCODE_Y] = SDLK_y; + keymap[SCANCODE_U] = SDLK_u; + keymap[SCANCODE_I] = SDLK_i; + keymap[SCANCODE_O] = SDLK_o; + keymap[SCANCODE_P] = SDLK_p; + keymap[SCANCODE_BRACKET_LEFT] = SDLK_LEFTBRACKET; + keymap[SCANCODE_BRACKET_RIGHT] = SDLK_RIGHTBRACKET; + keymap[SCANCODE_ENTER] = SDLK_RETURN; + keymap[SCANCODE_LEFTCONTROL] = SDLK_LCTRL; + keymap[SCANCODE_A] = SDLK_a; + keymap[SCANCODE_S] = SDLK_s; + keymap[SCANCODE_D] = SDLK_d; + keymap[SCANCODE_F] = SDLK_f; + keymap[SCANCODE_G] = SDLK_g; + keymap[SCANCODE_H] = SDLK_h; + keymap[SCANCODE_J] = SDLK_j; + keymap[SCANCODE_K] = SDLK_k; + keymap[SCANCODE_L] = SDLK_l; + keymap[SCANCODE_SEMICOLON] = SDLK_SEMICOLON; + keymap[SCANCODE_APOSTROPHE] = SDLK_QUOTE; + keymap[SCANCODE_GRAVE] = SDLK_BACKQUOTE; + keymap[SCANCODE_LEFTSHIFT] = SDLK_LSHIFT; + keymap[SCANCODE_BACKSLASH] = SDLK_BACKSLASH; + keymap[SCANCODE_Z] = SDLK_z; + keymap[SCANCODE_X] = SDLK_x; + keymap[SCANCODE_C] = SDLK_c; + keymap[SCANCODE_V] = SDLK_v; + keymap[SCANCODE_B] = SDLK_b; + keymap[SCANCODE_N] = SDLK_n; + keymap[SCANCODE_M] = SDLK_m; + keymap[SCANCODE_COMMA] = SDLK_COMMA; + keymap[SCANCODE_PERIOD] = SDLK_PERIOD; + keymap[SCANCODE_SLASH] = SDLK_SLASH; + keymap[SCANCODE_RIGHTSHIFT] = SDLK_RSHIFT; + keymap[SCANCODE_KEYPADMULTIPLY] = SDLK_KP_MULTIPLY; + keymap[SCANCODE_LEFTALT] = SDLK_LALT; + keymap[SCANCODE_SPACE] = SDLK_SPACE; + keymap[SCANCODE_CAPSLOCK] = SDLK_CAPSLOCK; + keymap[SCANCODE_F1] = SDLK_F1; + keymap[SCANCODE_F2] = SDLK_F2; + keymap[SCANCODE_F3] = SDLK_F3; + keymap[SCANCODE_F4] = SDLK_F4; + keymap[SCANCODE_F5] = SDLK_F5; + keymap[SCANCODE_F6] = SDLK_F6; + keymap[SCANCODE_F7] = SDLK_F7; + keymap[SCANCODE_F8] = SDLK_F8; + keymap[SCANCODE_F9] = SDLK_F9; + keymap[SCANCODE_F10] = SDLK_F10; + keymap[SCANCODE_NUMLOCK] = SDLK_NUMLOCK; + keymap[SCANCODE_SCROLLLOCK] = SDLK_SCROLLOCK; + keymap[SCANCODE_KEYPAD7] = SDLK_KP7; + keymap[SCANCODE_CURSORUPLEFT] = SDLK_KP7; + keymap[SCANCODE_KEYPAD8] = SDLK_KP8; + keymap[SCANCODE_CURSORUP] = SDLK_KP8; + keymap[SCANCODE_KEYPAD9] = SDLK_KP9; + keymap[SCANCODE_CURSORUPRIGHT] = SDLK_KP9; + keymap[SCANCODE_KEYPADMINUS] = SDLK_KP_MINUS; + keymap[SCANCODE_KEYPAD4] = SDLK_KP4; + keymap[SCANCODE_CURSORLEFT] = SDLK_KP4; + keymap[SCANCODE_KEYPAD5] = SDLK_KP5; + keymap[SCANCODE_KEYPAD6] = SDLK_KP6; + keymap[SCANCODE_CURSORRIGHT] = SDLK_KP6; + keymap[SCANCODE_KEYPADPLUS] = SDLK_KP_PLUS; + keymap[SCANCODE_KEYPAD1] = SDLK_KP1; + keymap[SCANCODE_CURSORDOWNLEFT] = SDLK_KP1; + keymap[SCANCODE_KEYPAD2] = SDLK_KP2; + keymap[SCANCODE_CURSORDOWN] = SDLK_KP2; + keymap[SCANCODE_KEYPAD3] = SDLK_KP3; + keymap[SCANCODE_CURSORDOWNRIGHT] = SDLK_KP3; + keymap[SCANCODE_KEYPAD0] = SDLK_KP0; + keymap[SCANCODE_KEYPADPERIOD] = SDLK_KP_PERIOD; + keymap[SCANCODE_LESS] = SDLK_LESS; + keymap[SCANCODE_F11] = SDLK_F11; + keymap[SCANCODE_F12] = SDLK_F12; + keymap[SCANCODE_KEYPADENTER] = SDLK_KP_ENTER; + keymap[SCANCODE_RIGHTCONTROL] = SDLK_RCTRL; + keymap[SCANCODE_CONTROL] = SDLK_RCTRL; + keymap[SCANCODE_KEYPADDIVIDE] = SDLK_KP_DIVIDE; + keymap[SCANCODE_PRINTSCREEN] = SDLK_PRINT; + keymap[SCANCODE_RIGHTALT] = SDLK_RALT; + keymap[SCANCODE_BREAK] = SDLK_BREAK; + keymap[SCANCODE_BREAK_ALTERNATIVE] = SDLK_UNKNOWN; + keymap[SCANCODE_HOME] = SDLK_HOME; + keymap[SCANCODE_CURSORBLOCKUP] = SDLK_UP; + keymap[SCANCODE_PAGEUP] = SDLK_PAGEUP; + keymap[SCANCODE_CURSORBLOCKLEFT] = SDLK_LEFT; + keymap[SCANCODE_CURSORBLOCKRIGHT] = SDLK_RIGHT; + keymap[SCANCODE_END] = SDLK_END; + keymap[SCANCODE_CURSORBLOCKDOWN] = SDLK_DOWN; + keymap[SCANCODE_PAGEDOWN] = SDLK_PAGEDOWN; + keymap[SCANCODE_INSERT] = SDLK_INSERT; + keymap[SCANCODE_REMOVE] = SDLK_DELETE; + keymap[119] = SDLK_PAUSE; + keymap[SCANCODE_RIGHTWIN] = SDLK_RSUPER; + keymap[SCANCODE_LEFTWIN] = SDLK_LSUPER; + keymap[127] = SDLK_MENU; +} + + + +static SDL_keysym *GGI_TranslateKey(gii_event *ev, SDL_keysym *keysym) +{ + /* Set the keysym information */ + keysym->scancode = ev->key.button; + keysym->sym = keymap[ev->key.button]; + keysym->mod = KMOD_NONE; + + /* If UNICODE is on, get the UNICODE value for the key */ + keysym->unicode = 0; + if (SDL_TranslateUNICODE) + { + keysym->unicode = GII_UNICODE(ev->key.sym); + } + + return keysym; +} diff --git a/3rdparty/SDL/src/video/ggi/SDL_ggievents_c.h b/3rdparty/SDL/src/video/ggi/SDL_ggievents_c.h new file mode 100644 index 0000000..2c66106 --- /dev/null +++ b/3rdparty/SDL/src/video/ggi/SDL_ggievents_c.h @@ -0,0 +1,29 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#include "SDL_ggivideo.h" + +/* Functions to be exported */ +extern void GGI_InitOSKeymap(_THIS); +extern void GGI_PumpEvents(_THIS); + diff --git a/3rdparty/SDL/src/video/ggi/SDL_ggikeys.h b/3rdparty/SDL/src/video/ggi/SDL_ggikeys.h new file mode 100644 index 0000000..2868ee6 --- /dev/null +++ b/3rdparty/SDL/src/video/ggi/SDL_ggikeys.h @@ -0,0 +1,135 @@ + +#define SCANCODE_ESCAPE 1 + +#define SCANCODE_1 2 +#define SCANCODE_2 3 +#define SCANCODE_3 4 +#define SCANCODE_4 5 +#define SCANCODE_5 6 +#define SCANCODE_6 7 +#define SCANCODE_7 8 +#define SCANCODE_8 9 +#define SCANCODE_9 10 +#define SCANCODE_0 11 + +#define SCANCODE_MINUS 12 +#define SCANCODE_EQUAL 13 + +#define SCANCODE_BACKSPACE 14 +#define SCANCODE_TAB 15 + +#define SCANCODE_Q 16 +#define SCANCODE_W 17 +#define SCANCODE_E 18 +#define SCANCODE_R 19 +#define SCANCODE_T 20 +#define SCANCODE_Y 21 +#define SCANCODE_U 22 +#define SCANCODE_I 23 +#define SCANCODE_O 24 +#define SCANCODE_P 25 +#define SCANCODE_BRACKET_LEFT 26 +#define SCANCODE_BRACKET_RIGHT 27 + +#define SCANCODE_ENTER 28 + +#define SCANCODE_LEFTCONTROL 29 + +#define SCANCODE_A 30 +#define SCANCODE_S 31 +#define SCANCODE_D 32 +#define SCANCODE_F 33 +#define SCANCODE_G 34 +#define SCANCODE_H 35 +#define SCANCODE_J 36 +#define SCANCODE_K 37 +#define SCANCODE_L 38 +#define SCANCODE_SEMICOLON 39 +#define SCANCODE_APOSTROPHE 40 +#define SCANCODE_GRAVE 41 + +#define SCANCODE_LEFTSHIFT 42 +#define SCANCODE_BACKSLASH 43 + +#define SCANCODE_Z 44 +#define SCANCODE_X 45 +#define SCANCODE_C 46 +#define SCANCODE_V 47 +#define SCANCODE_B 48 +#define SCANCODE_N 49 +#define SCANCODE_M 50 +#define SCANCODE_COMMA 51 +#define SCANCODE_PERIOD 52 +#define SCANCODE_SLASH 53 + +#define SCANCODE_RIGHTSHIFT 54 +#define SCANCODE_KEYPADMULTIPLY 55 + +#define SCANCODE_LEFTALT 56 +#define SCANCODE_SPACE 57 +#define SCANCODE_CAPSLOCK 58 + +#define SCANCODE_F1 59 +#define SCANCODE_F2 60 +#define SCANCODE_F3 61 +#define SCANCODE_F4 62 +#define SCANCODE_F5 63 +#define SCANCODE_F6 64 +#define SCANCODE_F7 65 +#define SCANCODE_F8 66 +#define SCANCODE_F9 67 +#define SCANCODE_F10 68 + +#define SCANCODE_NUMLOCK 69 +#define SCANCODE_SCROLLLOCK 70 + +#define SCANCODE_KEYPAD7 71 +#define SCANCODE_CURSORUPLEFT 71 +#define SCANCODE_KEYPAD8 72 +#define SCANCODE_CURSORUP 72 +#define SCANCODE_KEYPAD9 73 +#define SCANCODE_CURSORUPRIGHT 73 +#define SCANCODE_KEYPADMINUS 74 +#define SCANCODE_KEYPAD4 75 +#define SCANCODE_CURSORLEFT 75 +#define SCANCODE_KEYPAD5 76 +#define SCANCODE_KEYPAD6 77 +#define SCANCODE_CURSORRIGHT 77 +#define SCANCODE_KEYPADPLUS 78 +#define SCANCODE_KEYPAD1 79 +#define SCANCODE_CURSORDOWNLEFT 79 +#define SCANCODE_KEYPAD2 80 +#define SCANCODE_CURSORDOWN 80 +#define SCANCODE_KEYPAD3 81 +#define SCANCODE_CURSORDOWNRIGHT 81 +#define SCANCODE_KEYPAD0 82 +#define SCANCODE_KEYPADPERIOD 83 + +#define SCANCODE_LESS 86 + +#define SCANCODE_F11 87 +#define SCANCODE_F12 88 + +#define SCANCODE_KEYPADENTER 96 +#define SCANCODE_RIGHTCONTROL 97 +#define SCANCODE_CONTROL 97 +#define SCANCODE_KEYPADDIVIDE 98 +#define SCANCODE_PRINTSCREEN 99 +#define SCANCODE_RIGHTALT 100 +#define SCANCODE_BREAK 101 /* Beware: is 119 */ +#define SCANCODE_BREAK_ALTERNATIVE 119 /* on some keyboards! */ + +#define SCANCODE_HOME 102 +#define SCANCODE_CURSORBLOCKUP 90 /* Cursor key block */ +#define SCANCODE_PAGEUP 104 +#define SCANCODE_CURSORBLOCKLEFT 92 /* Cursor key block */ +#define SCANCODE_CURSORBLOCKRIGHT 94 /* Cursor key block */ +#define SCANCODE_END 107 +#define SCANCODE_CURSORBLOCKDOWN 108 /* Cursor key block */ +#define SCANCODE_PAGEDOWN 109 +#define SCANCODE_INSERT 110 +#define SCANCODE_REMOVE 111 + +#define SCANCODE_RIGHTWIN 126 +#define SCANCODE_LEFTWIN 125 + diff --git a/3rdparty/SDL/src/video/ggi/SDL_ggimouse.c b/3rdparty/SDL/src/video/ggi/SDL_ggimouse.c new file mode 100644 index 0000000..52c5337 --- /dev/null +++ b/3rdparty/SDL/src/video/ggi/SDL_ggimouse.c @@ -0,0 +1,32 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#include "SDL_mouse.h" +#include "../../events/SDL_events_c.h" +#include "SDL_ggimouse_c.h" + + +/* The implementation dependent data for the window manager cursor */ +struct WMcursor { + int unused; +}; diff --git a/3rdparty/SDL/src/video/ggi/SDL_ggimouse_c.h b/3rdparty/SDL/src/video/ggi/SDL_ggimouse_c.h new file mode 100644 index 0000000..c0ce295 --- /dev/null +++ b/3rdparty/SDL/src/video/ggi/SDL_ggimouse_c.h @@ -0,0 +1,26 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#include "SDL_ggivideo.h" + +/* Functions to be exported */ diff --git a/3rdparty/SDL/src/video/ggi/SDL_ggivideo.c b/3rdparty/SDL/src/video/ggi/SDL_ggivideo.c new file mode 100644 index 0000000..face495 --- /dev/null +++ b/3rdparty/SDL/src/video/ggi/SDL_ggivideo.c @@ -0,0 +1,378 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* GGI-based SDL video driver implementation. +*/ + +#include <fcntl.h> +#include <unistd.h> +#include <sys/mman.h> + +#include <ggi/ggi.h> +#include <ggi/gii.h> + +#include "SDL_video.h" +#include "SDL_mouse.h" +#include "../SDL_sysvideo.h" +#include "../SDL_pixels_c.h" +#include "../../events/SDL_events_c.h" +#include "SDL_ggivideo.h" +#include "SDL_ggimouse_c.h" +#include "SDL_ggievents_c.h" + + +struct private_hwdata +{ + ggi_visual_t vis; +}; + +ggi_visual_t VIS; + +/* Initialization/Query functions */ +static int GGI_VideoInit(_THIS, SDL_PixelFormat *vformat); +static SDL_Rect **GGI_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags); +static SDL_Surface *GGI_SetVideoMode(_THIS, SDL_Surface *current, int width, int height, int bpp, Uint32 flags); +static int GGI_SetColors(_THIS, int firstcolor, int ncolors, + SDL_Color *colors); +static void GGI_VideoQuit(_THIS); + +/* Hardware surface functions */ +static int GGI_AllocHWSurface(_THIS, SDL_Surface *surface); +static int GGI_LockHWSurface(_THIS, SDL_Surface *surface); +static void GGI_UnlockHWSurface(_THIS, SDL_Surface *surface); +static void GGI_FreeHWSurface(_THIS, SDL_Surface *surface); + +/* GGI driver bootstrap functions */ + +static int GGI_Available(void) +{ + ggi_visual_t *vis; + + vis = NULL; + if (ggiInit() == 0) { + vis = ggiOpen(NULL); + if (vis != NULL) { + ggiClose(vis); + } + } + return (vis != NULL); +} + +static void GGI_DeleteDevice(SDL_VideoDevice *device) +{ + SDL_free(device->hidden); + SDL_free(device); +} + +static SDL_VideoDevice *GGI_CreateDevice(int devindex) +{ + SDL_VideoDevice *device; + + /* Initialize all variables that we clean on shutdown */ + device = (SDL_VideoDevice *)SDL_malloc(sizeof(SDL_VideoDevice)); + if ( device ) { + SDL_memset(device, 0, (sizeof *device)); + device->hidden = (struct SDL_PrivateVideoData *) + SDL_malloc((sizeof *device->hidden)); + } + if ( (device == NULL) || (device->hidden == NULL) ) { + SDL_OutOfMemory(); + if ( device ) { + SDL_free(device); + } + return(0); + } + SDL_memset(device->hidden, 0, (sizeof *device->hidden)); + + /* Set the function pointers */ + device->VideoInit = GGI_VideoInit; + device->ListModes = GGI_ListModes; + device->SetVideoMode = GGI_SetVideoMode; + device->SetColors = GGI_SetColors; + device->UpdateRects = NULL; + device->VideoQuit = GGI_VideoQuit; + device->AllocHWSurface = GGI_AllocHWSurface; + device->CheckHWBlit = NULL; + device->FillHWRect = NULL; + device->SetHWColorKey = NULL; + device->SetHWAlpha = NULL; + device->LockHWSurface = GGI_LockHWSurface; + device->UnlockHWSurface = GGI_UnlockHWSurface; + device->FlipHWSurface = NULL; + device->FreeHWSurface = GGI_FreeHWSurface; + device->SetCaption = NULL; + device->SetIcon = NULL; + device->IconifyWindow = NULL; + device->GrabInput = NULL; + device->GetWMInfo = NULL; + device->InitOSKeymap = GGI_InitOSKeymap; + device->PumpEvents = GGI_PumpEvents; + + device->free = GGI_DeleteDevice; + + return device; +} + +VideoBootStrap GGI_bootstrap = { + "ggi", "General Graphics Interface (GGI)", + GGI_Available, GGI_CreateDevice +}; + + +static SDL_Rect video_mode; +static SDL_Rect *SDL_modelist[4] = { NULL, NULL, NULL, NULL }; + +int GGI_VideoInit(_THIS, SDL_PixelFormat *vformat) +{ + ggi_mode mode = + { + 1, + { GGI_AUTO, GGI_AUTO }, + { GGI_AUTO, GGI_AUTO }, + { 0, 0 }, + GT_AUTO, + { GGI_AUTO, GGI_AUTO } + }; + struct private_hwdata *priv; + ggi_color pal[256], map[256]; + const ggi_directbuffer *db; + int err, num_bufs; + ggi_pixel white, black; + + priv = SDL_malloc(sizeof(struct private_hwdata)); + if (priv == NULL) + { + SDL_SetError("Unhandled GGI mode type!\n"); + GGI_VideoQuit(NULL); + } + + if (ggiInit() != 0) + { + SDL_SetError("Unable to initialize GGI!\n"); + GGI_VideoQuit(NULL); + } + + VIS = ggiOpen(NULL); + if (VIS == NULL) + { + SDL_SetError("Unable to open default GGI visual!\n"); + ggiExit(); + GGI_VideoQuit(NULL); + } + + ggiSetFlags(VIS, GGIFLAG_ASYNC); + + /* Validate mode, autodetecting any GGI_AUTO or GT_AUTO fields */ + ggiCheckMode(VIS, &mode); + + /* At this point we should have a valid mode - try to set it */ + err = ggiSetMode(VIS, &mode); + + /* If we couldn't set _any_ modes, something is very wrong */ + if (err) + { + SDL_SetError("Can't set a mode!\n"); + ggiClose(VIS); + ggiExit(); + GGI_VideoQuit(NULL); + } + + /* Determine the current screen size */ + this->info.current_w = mode.virt.x; + this->info.current_h = mode.virt.y; + + /* Set a palette for palletized modes */ + if (GT_SCHEME(mode.graphtype) == GT_PALETTE) + { + ggiSetColorfulPalette(VIS); + ggiGetPalette(VIS, 0, 1 << vformat->BitsPerPixel, pal); + } + + /* Now we try to get the DirectBuffer info, which determines whether + * SDL can access hardware surfaces directly. */ + + num_bufs = ggiDBGetNumBuffers(VIS); + + if (num_bufs > 0) + { + db = ggiDBGetBuffer(VIS, 0); /* Only handle one DB for now */ + + vformat->BitsPerPixel = db->buffer.plb.pixelformat->depth; + + vformat->Rmask = db->buffer.plb.pixelformat->red_mask; + vformat->Gmask = db->buffer.plb.pixelformat->green_mask; + vformat->Bmask = db->buffer.plb.pixelformat->blue_mask; + + /* Fill in our hardware acceleration capabilities */ + + this->info.wm_available = 0; + this->info.hw_available = 1; + this->info.video_mem = db->buffer.plb.stride * mode.virt.y; + } + + video_mode.x = 0; + video_mode.y = 0; + video_mode.w = mode.virt.x; + video_mode.h = mode.virt.y; + SDL_modelist[((vformat->BitsPerPixel + 7) / 8) - 1] = &video_mode; + + /* We're done! */ + return(0); +} + +static SDL_Rect **GGI_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags) +{ + return(&SDL_modelist[((format->BitsPerPixel + 7) / 8) - 1]); +} + +/* Various screen update functions available */ +static void GGI_DirectUpdate(_THIS, int numrects, SDL_Rect *rects); + +SDL_Surface *GGI_SetVideoMode(_THIS, SDL_Surface *current, int width, int height, int bpp, Uint32 flags) +{ + ggi_mode mode = + { + 1, + { GGI_AUTO, GGI_AUTO }, + { GGI_AUTO, GGI_AUTO }, + { 0, 0 }, + GT_AUTO, + { GGI_AUTO, GGI_AUTO } + }; + const ggi_directbuffer *db; + ggi_color pal[256]; + int err; + + fprintf(stderr, "GGI_SetVideoMode()\n"); + + mode.visible.x = mode.virt.x = width; + mode.visible.y = mode.virt.y = height; + + /* Translate requested SDL bit depth into a GGI mode */ + switch (bpp) + { + case 1: mode.graphtype = GT_1BIT; break; + case 2: mode.graphtype = GT_2BIT; break; + case 4: mode.graphtype = GT_4BIT; break; + case 8: mode.graphtype = GT_8BIT; break; + case 15: mode.graphtype = GT_15BIT; break; + case 16: mode.graphtype = GT_16BIT; break; + case 24: mode.graphtype = GT_24BIT; break; + case 32: mode.graphtype = GT_32BIT; break; + default: + SDL_SetError("Unknown SDL bit depth, using GT_AUTO....\n"); + mode.graphtype = GT_AUTO; + } + + /* Validate mode, autodetecting any GGI_AUTO or GT_AUTO fields */ + ggiCheckMode(VIS, &mode); + + /* At this point we should have a valid mode - try to set it */ + err = ggiSetMode(VIS, &mode); + + /* If we couldn't set _any_ modes, something is very wrong */ + if (err) + { + SDL_SetError("Can't set a mode!\n"); + ggiClose(VIS); + ggiExit(); + GGI_VideoQuit(NULL); + } + + /* Set a palette for palletized modes */ + if (GT_SCHEME(mode.graphtype) == GT_PALETTE) + { + ggiSetColorfulPalette(VIS); + ggiGetPalette(VIS, 0, 1 << bpp, pal); + } + + db = ggiDBGetBuffer(VIS, 0); + + /* Set up the new mode framebuffer */ + current->flags = (SDL_FULLSCREEN | SDL_HWSURFACE); + current->w = mode.virt.x; + current->h = mode.virt.y; + current->pitch = db->buffer.plb.stride; + current->pixels = db->read; + + /* Set the blit function */ + this->UpdateRects = GGI_DirectUpdate; + + /* We're done */ + return(current); +} + +static int GGI_AllocHWSurface(_THIS, SDL_Surface *surface) +{ + return(-1); +} +static void GGI_FreeHWSurface(_THIS, SDL_Surface *surface) +{ + return; +} +static int GGI_LockHWSurface(_THIS, SDL_Surface *surface) +{ + return(0); +} +static void GGI_UnlockHWSurface(_THIS, SDL_Surface *surface) +{ + return; +} + +static void GGI_DirectUpdate(_THIS, int numrects, SDL_Rect *rects) +{ + int i; + +/* ggiFlush(VIS); */ + + for (i = 0; i < numrects; i++) + { + ggiFlushRegion(VIS, rects[i].x, rects[i].y, rects[i].w, rects[i].h); + } + return; +} + +int GGI_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors) +{ + int i; + ggi_color pal[256]; + + /* Set up the colormap */ + for (i = 0; i < ncolors; i++) + { + pal[i].r = (colors[i].r << 8) | colors[i].r; + pal[i].g = (colors[i].g << 8) | colors[i].g; + pal[i].b = (colors[i].b << 8) | colors[i].b; + } + + ggiSetPalette(VIS, firstcolor, ncolors, pal); + + return 1; +} + +void GGI_VideoQuit(_THIS) +{ +} +void GGI_FinalQuit(void) +{ +} diff --git a/3rdparty/SDL/src/video/ggi/SDL_ggivideo.h b/3rdparty/SDL/src/video/ggi/SDL_ggivideo.h new file mode 100644 index 0000000..014dd09 --- /dev/null +++ b/3rdparty/SDL/src/video/ggi/SDL_ggivideo.h @@ -0,0 +1,48 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#ifndef _SDL_ggivideo_h +#define _SDL_ggivideo_h + +#include <ggi/ggi.h> + +#include "SDL_mouse.h" +#include "../SDL_sysvideo.h" + +#define _THIS SDL_VideoDevice *this + +/* Private display data */ + +struct SDL_PrivateVideoData +{ + ggi_visual_t *ggivis; +}; + +extern ggi_visual_t VIS; /* FIXME: use the private data struct */ + +extern int SDL_OpenKeyboard(void); +extern void SDL_CloseKeyboard(void); +extern int SDL_OpenMouse(void); +extern void SDL_CloseMouse(void); + +#endif /* _SDL_ggivideo_h */ diff --git a/3rdparty/SDL/src/video/ipod/SDL_ipodvideo.c b/3rdparty/SDL/src/video/ipod/SDL_ipodvideo.c new file mode 100644 index 0000000..a2f3db3 --- /dev/null +++ b/3rdparty/SDL/src/video/ipod/SDL_ipodvideo.c @@ -0,0 +1,733 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#include <sys/types.h> +#include <sys/ioctl.h> + +#include <unistd.h> +#include <fcntl.h> +#include <string.h> +#include <termios.h> +#include <ctype.h> + +#include <linux/vt.h> +#include <linux/kd.h> +#include <linux/keyboard.h> +#include <linux/fb.h> + +#include "SDL_video.h" +#include "SDL_mouse.h" +#include "../SDL_sysvideo.h" +#include "../SDL_pixels_c.h" +#include "../../events/SDL_events_c.h" +#include "SDL_sysevents.h" +#include "SDL_ipodvideo.h" + +#define _THIS SDL_VideoDevice *this + +static int iPod_VideoInit (_THIS, SDL_PixelFormat *vformat); +static SDL_Rect **iPod_ListModes (_THIS, SDL_PixelFormat *format, Uint32 flags); +static SDL_Surface *iPod_SetVideoMode (_THIS, SDL_Surface *current, int width, int height, int bpp, Uint32 flags); +static int iPod_SetColors (_THIS, int firstcolor, int ncolors, SDL_Color *colors); +static void iPod_UpdateRects (_THIS, int nrects, SDL_Rect *rects); +static void iPod_VideoQuit (_THIS); +static void iPod_PumpEvents (_THIS); + +static long iPod_GetGeneration(); + +static int initd = 0; +static int kbfd = -1; +static int fbfd = -1; +static int oldvt = -1; +static int curvt = -1; +static int old_kbmode = -1; +static long generation = 0; +static struct termios old_termios, cur_termios; + +FILE *dbgout; + +#define LCD_DATA 0x10 +#define LCD_CMD 0x08 +#define IPOD_OLD_LCD_BASE 0xc0001000 +#define IPOD_OLD_LCD_RTC 0xcf001110 +#define IPOD_NEW_LCD_BASE 0x70003000 +#define IPOD_NEW_LCD_RTC 0x60005010 + +static unsigned long lcd_base, lcd_rtc, lcd_width, lcd_height; + +static long iPod_GetGeneration() +{ + int i; + char cpuinfo[256]; + char *ptr; + FILE *file; + + if ((file = fopen("/proc/cpuinfo", "r")) != NULL) { + while (fgets(cpuinfo, sizeof(cpuinfo), file) != NULL) + if (SDL_strncmp(cpuinfo, "Revision", 8) == 0) + break; + fclose(file); + } + for (i = 0; !isspace(cpuinfo[i]); i++); + for (; isspace(cpuinfo[i]); i++); + ptr = cpuinfo + i + 2; + + return SDL_strtol(ptr, NULL, 10); +} + +static int iPod_Available() +{ + return 1; +} + +static void iPod_DeleteDevice (SDL_VideoDevice *device) +{ + free (device->hidden); + free (device); +} + +void iPod_InitOSKeymap (_THIS) {} + +static SDL_VideoDevice *iPod_CreateDevice (int devindex) +{ + SDL_VideoDevice *this; + + this = (SDL_VideoDevice *)SDL_malloc (sizeof(SDL_VideoDevice)); + if (this) { + memset (this, 0, sizeof *this); + this->hidden = (struct SDL_PrivateVideoData *) SDL_malloc (sizeof(struct SDL_PrivateVideoData)); + } + if (!this || !this->hidden) { + SDL_OutOfMemory(); + if (this) + SDL_free (this); + return 0; + } + memset (this->hidden, 0, sizeof(struct SDL_PrivateVideoData)); + + generation = iPod_GetGeneration(); + + this->VideoInit = iPod_VideoInit; + this->ListModes = iPod_ListModes; + this->SetVideoMode = iPod_SetVideoMode; + this->SetColors = iPod_SetColors; + this->UpdateRects = iPod_UpdateRects; + this->VideoQuit = iPod_VideoQuit; + this->AllocHWSurface = 0; + this->CheckHWBlit = 0; + this->FillHWRect = 0; + this->SetHWColorKey = 0; + this->SetHWAlpha = 0; + this->LockHWSurface = 0; + this->UnlockHWSurface = 0; + this->FlipHWSurface = 0; + this->FreeHWSurface = 0; + this->SetCaption = 0; + this->SetIcon = 0; + this->IconifyWindow = 0; + this->GrabInput = 0; + this->GetWMInfo = 0; + this->InitOSKeymap = iPod_InitOSKeymap; + this->PumpEvents = iPod_PumpEvents; + this->free = iPod_DeleteDevice; + + return this; +} + +VideoBootStrap iPod_bootstrap = { + "ipod", "iPod Framebuffer Driver", + iPod_Available, iPod_CreateDevice +}; + +//--// + +static int iPod_VideoInit (_THIS, SDL_PixelFormat *vformat) +{ + if (!initd) { + /*** Code adapted/copied from SDL fbcon driver. ***/ + + static const char * const tty0[] = { "/dev/tty0", "/dev/vc/0", 0 }; + static const char * const vcs[] = { "/dev/vc/%d", "/dev/tty%d", 0 }; + int i, tty0_fd; + + dbgout = fdopen (open ("/etc/sdlpod.log", O_WRONLY | O_SYNC | O_APPEND), "a"); + if (dbgout) { + setbuf (dbgout, 0); + fprintf (dbgout, "--> Started SDL <--\n"); + } + + // Try to query for a free VT + tty0_fd = -1; + for ( i=0; tty0[i] && (tty0_fd < 0); ++i ) { + tty0_fd = open(tty0[i], O_WRONLY, 0); + } + if ( tty0_fd < 0 ) { + tty0_fd = dup(0); /* Maybe stdin is a VT? */ + } + ioctl(tty0_fd, VT_OPENQRY, &curvt); + close(tty0_fd); + + tty0_fd = open("/dev/tty", O_RDWR, 0); + if ( tty0_fd >= 0 ) { + ioctl(tty0_fd, TIOCNOTTY, 0); + close(tty0_fd); + } + + if ( (geteuid() == 0) && (curvt > 0) ) { + for ( i=0; vcs[i] && (kbfd < 0); ++i ) { + char vtpath[12]; + + SDL_snprintf(vtpath, SDL_arraysize(vtpath), vcs[i], curvt); + kbfd = open(vtpath, O_RDWR); + } + } + if ( kbfd < 0 ) { + if (dbgout) fprintf (dbgout, "Couldn't open any VC\n"); + return -1; + } + if (dbgout) fprintf (stderr, "Current VT: %d\n", curvt); + + if (kbfd >= 0) { + /* Switch to the correct virtual terminal */ + if ( curvt > 0 ) { + struct vt_stat vtstate; + + if ( ioctl(kbfd, VT_GETSTATE, &vtstate) == 0 ) { + oldvt = vtstate.v_active; + } + if ( ioctl(kbfd, VT_ACTIVATE, curvt) == 0 ) { + if (dbgout) fprintf (dbgout, "Waiting for switch to this VT... "); + ioctl(kbfd, VT_WAITACTIVE, curvt); + if (dbgout) fprintf (dbgout, "done!\n"); + } + } + + // Set terminal input mode + if (tcgetattr (kbfd, &old_termios) < 0) { + if (dbgout) fprintf (dbgout, "Can't get termios\n"); + return -1; + } + cur_termios = old_termios; + // cur_termios.c_iflag &= ~(ICRNL | INPCK | ISTRIP | IXON); + // cur_termios.c_iflag |= (BRKINT); + // cur_termios.c_lflag &= ~(ICANON | ECHO | ISIG | IEXTEN); + // cur_termios.c_oflag &= ~(OPOST); + // cur_termios.c_oflag |= (ONOCR | ONLRET); + cur_termios.c_lflag &= ~(ICANON | ECHO | ISIG); + cur_termios.c_iflag &= ~(ISTRIP | IGNCR | ICRNL | INLCR | IXOFF | IXON); + cur_termios.c_cc[VMIN] = 0; + cur_termios.c_cc[VTIME] = 0; + + if (tcsetattr (kbfd, TCSAFLUSH, &cur_termios) < 0) { + if (dbgout) fprintf (dbgout, "Can't set termios\n"); + return -1; + } + if (ioctl (kbfd, KDSKBMODE, K_MEDIUMRAW) < 0) { + if (dbgout) fprintf (dbgout, "Can't set medium-raw mode\n"); + return -1; + } + if (ioctl (kbfd, KDSETMODE, KD_GRAPHICS) < 0) { + if (dbgout) fprintf (dbgout, "Can't set graphics\n"); + return -1; + } + } + + // Open the framebuffer + if ((fbfd = open ("/dev/fb0", O_RDWR)) < 0) { + if (dbgout) fprintf (dbgout, "Can't open framebuffer\n"); + return -1; + } else { + struct fb_var_screeninfo vinfo; + + if (dbgout) fprintf (dbgout, "Generation: %ld\n", generation); + + if (generation >= 40000) { + lcd_base = IPOD_NEW_LCD_BASE; + } else { + lcd_base = IPOD_OLD_LCD_BASE; + } + + ioctl (fbfd, FBIOGET_VSCREENINFO, &vinfo); + close (fbfd); + + if (lcd_base == IPOD_OLD_LCD_BASE) + lcd_rtc = IPOD_OLD_LCD_RTC; + else if (lcd_base == IPOD_NEW_LCD_BASE) + lcd_rtc = IPOD_NEW_LCD_RTC; + else { + SDL_SetError ("Unknown iPod version"); + return -1; + } + + lcd_width = vinfo.xres; + lcd_height = vinfo.yres; + + if (dbgout) fprintf (dbgout, "LCD is %dx%d\n", lcd_width, lcd_height); + } + + fcntl (kbfd, F_SETFL, O_RDWR | O_NONBLOCK); + + /* Determine the current screen size */ + this->info.current_w = lcd_width; + this->info.current_h = lcd_height; + + if ((generation >= 60000) && (generation < 70000)) { + vformat->BitsPerPixel = 16; + vformat->Rmask = 0xF800; + vformat->Gmask = 0x07E0; + vformat->Bmask = 0x001F; + } else { + vformat->BitsPerPixel = 8; + vformat->Rmask = vformat->Gmask = vformat->Bmask = 0; + } + + initd = 1; + if (dbgout) fprintf (dbgout, "Initialized.\n\n"); + } + return 0; +} + +static SDL_Rect **iPod_ListModes (_THIS, SDL_PixelFormat *format, Uint32 flags) +{ + int width, height, fd; + static SDL_Rect r; + static SDL_Rect *rs[2] = { &r, 0 }; + + if ((fd = open ("/dev/fb0", O_RDWR)) < 0) { + return 0; + } else { + struct fb_var_screeninfo vinfo; + + ioctl (fbfd, FBIOGET_VSCREENINFO, &vinfo); + close (fbfd); + + width = vinfo.xres; + height = vinfo.yres; + } + r.x = r.y = 0; + r.w = width; + r.h = height; + return rs; +} + + +static SDL_Surface *iPod_SetVideoMode (_THIS, SDL_Surface *current, int width, int height, int bpp, + Uint32 flags) +{ + Uint32 Rmask, Gmask, Bmask; + if (bpp > 8) { + Rmask = 0xF800; + Gmask = 0x07E0; + Bmask = 0x001F; + } else { + Rmask = Gmask = Bmask = 0; + } + + if (this->hidden->buffer) SDL_free (this->hidden->buffer); + this->hidden->buffer = SDL_malloc (width * height * (bpp / 8)); + if (!this->hidden->buffer) { + SDL_SetError ("Couldn't allocate buffer for requested mode"); + return 0; + } + + memset (this->hidden->buffer, 0, width * height * (bpp / 8)); + + if (!SDL_ReallocFormat (current, bpp, Rmask, Gmask, Bmask, 0)) { + SDL_SetError ("Couldn't allocate new pixel format"); + SDL_free (this->hidden->buffer); + this->hidden->buffer = 0; + return 0; + } + + if (bpp <= 8) { + int i, j; + for (i = 0; i < 256; i += 4) { + for (j = 0; j < 4; j++) { + current->format->palette->colors[i+j].r = 85 * j; + current->format->palette->colors[i+j].g = 85 * j; + current->format->palette->colors[i+j].b = 85 * j; + } + } + } + + current->flags = flags & SDL_FULLSCREEN; + this->hidden->w = current->w = width; + this->hidden->h = current->h = height; + current->pitch = current->w * (bpp / 8); + current->pixels = this->hidden->buffer; + + return current; +} + +static int iPod_SetColors (_THIS, int firstcolor, int ncolors, SDL_Color *colors) +{ + if (SDL_VideoSurface && SDL_VideoSurface->format && SDL_VideoSurface->format->palette) { + int i, j; + for (i = 0; i < 256; i += 4) { + for (j = 0; j < 4; j++) { + SDL_VideoSurface->format->palette->colors[i+j].r = 85 * j; + SDL_VideoSurface->format->palette->colors[i+j].g = 85 * j; + SDL_VideoSurface->format->palette->colors[i+j].b = 85 * j; + } + } + } + return 0; +} + +static void iPod_VideoQuit (_THIS) +{ + ioctl (kbfd, KDSETMODE, KD_TEXT); + tcsetattr (kbfd, TCSAFLUSH, &old_termios); + old_kbmode = -1; + + if (oldvt > 0) + ioctl (kbfd, VT_ACTIVATE, oldvt); + + if (kbfd > 0) + close (kbfd); + + if (dbgout) { + fprintf (dbgout, "<-- Ended SDL -->\n"); + fclose (dbgout); + } + + kbfd = -1; +} + +static char iPod_SC_keymap[] = { + 0, /* 0 - no key */ + '[' - 0x40, /* ESC (Ctrl+[) */ + '1', '2', '3', '4', '5', '6', '7', '8', '9', + '-', '=', + '\b', '\t', /* Backspace, Tab (Ctrl+H,Ctrl+I) */ + 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p', '[', ']', + '\n', 0, /* Enter, Left CTRL */ + 'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';', '\'', '`', + 0, '\\', /* left shift, backslash */ + 'z', 'x', 'c', 'v', 'b', 'n', 'm', ',', '.', '/', + 0, '*', 0, ' ', 0, /* right shift, KP mul, left alt, space, capslock */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* F1-10 */ + 0, 0, /* numlock, scrollock */ + '7', '8', '9', '-', '4', '5', '6', '+', '1', '2', '3', '0', '.', /* numeric keypad */ + 0, 0, /* padding */ + 0, 0, 0, /* "less" (?), F11, F12 */ + 0, 0, 0, 0, 0, 0, 0, /* padding */ + '\n', 0, '/', 0, 0, /* KP enter, Rctrl, Ctrl, KP div, PrtSc, RAlt */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, /* Break, Home, Up, PgUp, Left, Right, End, Down, PgDn */ + 0, 0, /* Ins, Del */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* padding */ + 0, 0, /* RWin, LWin */ + 0 /* no key */ +}; + + +static void iPod_keyboard() +{ + unsigned char keybuf[128]; + int i, nread; + SDL_keysym keysym; + SDL_Event ev; + + keysym.mod = 0; + keysym.scancode = 0xff; + memset (&ev, 0, sizeof(SDL_Event)); + + nread = read (kbfd, keybuf, 128); + for (i = 0; i < nread; i++) { + char ascii = iPod_SC_keymap[keybuf[i] & 0x7f]; + + if (dbgout) fprintf (dbgout, "Key! %02x is %c %s", keybuf[i], ascii, (keybuf[i] & 0x80)? "up" : "down"); + + keysym.sym = keysym.unicode = ascii; + ev.type = (keybuf[i] & 0x80)? SDL_KEYUP : SDL_KEYDOWN; + ev.key.state = 0; + ev.key.keysym = keysym; + SDL_PushEvent (&ev); + } +} + +static void iPod_PumpEvents (_THIS) +{ + fd_set fdset; + int max_fd = 0; + static struct timeval zero; + int posted; + + do { + posted = 0; + + FD_ZERO (&fdset); + if (kbfd >= 0) { + FD_SET (kbfd, &fdset); + max_fd = kbfd; + } + if (dbgout) fprintf (dbgout, "Selecting"); + if (select (max_fd + 1, &fdset, 0, 0, &zero) > 0) { + if (dbgout) fprintf (dbgout, " -> match!\n"); + iPod_keyboard(); + posted++; + } + if (dbgout) fprintf (dbgout, "\n"); + } while (posted); +} + +// enough space for 160x128x2 +static char ipod_scr[160 * (128/4)]; + +#define outl(datum,addr) (*(volatile unsigned long *)(addr) = (datum)) +#define inl(addr) (*(volatile unsigned long *)(addr)) + +/*** The following LCD code is taken from Linux kernel uclinux-2.4.24-uc0-ipod2, + file arch/armnommu/mach-ipod/fb.c. A few modifications have been made. ***/ + +/* get current usec counter */ +static int M_timer_get_current(void) +{ + return inl(lcd_rtc); +} + +/* check if number of useconds has past */ +static int M_timer_check(int clock_start, int usecs) +{ + unsigned long clock; + clock = inl(lcd_rtc); + + if ( (clock - clock_start) >= usecs ) { + return 1; + } else { + return 0; + } +} + +/* wait for LCD with timeout */ +static void M_lcd_wait_write(void) +{ + if ( (inl(lcd_base) & 0x8000) != 0 ) { + int start = M_timer_get_current(); + + do { + if ( (inl(lcd_base) & (unsigned int)0x8000) == 0 ) + break; + } while ( M_timer_check(start, 1000) == 0 ); + } +} + + +/* send LCD data */ +static void M_lcd_send_data(int data_lo, int data_hi) +{ + M_lcd_wait_write(); + + outl(data_lo, lcd_base + LCD_DATA); + + M_lcd_wait_write(); + + outl(data_hi, lcd_base + LCD_DATA); + +} + +/* send LCD command */ +static void +M_lcd_prepare_cmd(int cmd) +{ + M_lcd_wait_write(); + + outl(0x0, lcd_base + LCD_CMD); + + M_lcd_wait_write(); + + outl(cmd, lcd_base + LCD_CMD); + +} + +/* send LCD command and data */ +static void M_lcd_cmd_and_data(int cmd, int data_lo, int data_hi) +{ + M_lcd_prepare_cmd(cmd); + + M_lcd_send_data(data_lo, data_hi); +} + +// Copied from uW +static void M_update_display(int sx, int sy, int mx, int my) +{ + int y; + unsigned short cursor_pos; + + sx >>= 3; + mx >>= 3; + + cursor_pos = sx + (sy << 5); + + for ( y = sy; y <= my; y++ ) { + unsigned char *img_data; + int x; + + /* move the cursor */ + M_lcd_cmd_and_data(0x11, cursor_pos >> 8, cursor_pos & 0xff); + + /* setup for printing */ + M_lcd_prepare_cmd(0x12); + + img_data = ipod_scr + (sx << 1) + (y * (lcd_width/4)); + + /* loops up to 160 times */ + for ( x = sx; x <= mx; x++ ) { + /* display eight pixels */ + M_lcd_send_data(*(img_data + 1), *img_data); + + img_data += 2; + } + + /* update cursor pos counter */ + cursor_pos += 0x20; + } +} + +/* get current usec counter */ +static int C_timer_get_current(void) +{ + return inl(0x60005010); +} + +/* check if number of useconds has past */ +static int C_timer_check(int clock_start, int usecs) +{ + unsigned long clock; + clock = inl(0x60005010); + + if ( (clock - clock_start) >= usecs ) { + return 1; + } else { + return 0; + } +} + +/* wait for LCD with timeout */ +static void C_lcd_wait_write(void) +{ + if ((inl(0x70008A0C) & 0x80000000) != 0) { + int start = C_timer_get_current(); + + do { + if ((inl(0x70008A0C) & 0x80000000) == 0) + break; + } while (C_timer_check(start, 1000) == 0); + } +} +static void C_lcd_cmd_data(int cmd, int data) +{ + C_lcd_wait_write(); + outl(cmd | 0x80000000, 0x70008A0C); + + C_lcd_wait_write(); + outl(data | 0x80000000, 0x70008A0C); +} + +static void C_update_display(int sx, int sy, int mx, int my) +{ + int height = (my - sy) + 1; + int width = (mx - sx) + 1; + + char *addr = SDL_VideoSurface->pixels; + + if (width & 1) width++; + + /* start X and Y */ + C_lcd_cmd_data(0x12, (sy & 0xff)); + C_lcd_cmd_data(0x13, (((SDL_VideoSurface->w - 1) - sx) & 0xff)); + + /* max X and Y */ + C_lcd_cmd_data(0x15, (((sy + height) - 1) & 0xff)); + C_lcd_cmd_data(0x16, (((((SDL_VideoSurface->w - 1) - sx) - width) + 1) & 0xff)); + + addr += sx + sy * SDL_VideoSurface->pitch; + + while (height > 0) { + int h, x, y, pixels_to_write; + + pixels_to_write = (width * height) * 2; + + /* calculate how much we can do in one go */ + h = height; + if (pixels_to_write > 64000) { + h = (64000/2) / width; + pixels_to_write = (width * h) * 2; + } + + outl(0x10000080, 0x70008A20); + outl((pixels_to_write - 1) | 0xC0010000, 0x70008A24); + outl(0x34000000, 0x70008A20); + + /* for each row */ + for (x = 0; x < h; x++) + { + /* for each column */ + for (y = 0; y < width; y += 2) { + unsigned two_pixels; + + two_pixels = addr[0] | (addr[1] << 16); + addr += 2; + + while ((inl(0x70008A20) & 0x1000000) == 0); + + /* output 2 pixels */ + outl(two_pixels, 0x70008B00); + } + + addr += SDL_VideoSurface->w - width; + } + + while ((inl(0x70008A20) & 0x4000000) == 0); + + outl(0x0, 0x70008A24); + + height = height - h; + } +} + +// Should work with photo. However, I don't have one, so I'm not sure. +static void iPod_UpdateRects (_THIS, int nrects, SDL_Rect *rects) +{ + if (SDL_VideoSurface->format->BitsPerPixel == 16) { + C_update_display (0, 0, lcd_width, lcd_height); + } else { + int i, y, x; + for (i = 0; i < nrects; i++) { + SDL_Rect *r = rects + i; + if (!r) { + continue; + } + + for (y = r->y; (y < r->y + r->h) && y < lcd_height; y++) { + for (x = r->x; (x < r->x + r->w) && x < lcd_width; x++) { + ipod_scr[y*(lcd_width/4) + x/4] &= ~(3 << (2 * (x%4))); + ipod_scr[y*(lcd_width/4) + x/4] |= + (((Uint8*)(SDL_VideoSurface->pixels))[ y*SDL_VideoSurface->pitch + x ] & 3) << (2 * (x%4)); + } + } + } + + M_update_display (0, 0, lcd_width, lcd_height); + } +} diff --git a/3rdparty/SDL/src/video/ipod/SDL_ipodvideo.h b/3rdparty/SDL/src/video/ipod/SDL_ipodvideo.h new file mode 100644 index 0000000..921eee8 --- /dev/null +++ b/3rdparty/SDL/src/video/ipod/SDL_ipodvideo.h @@ -0,0 +1,38 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* iPod SDL framebuffer driver + * Joshua Oreman + * Main header file + */ + +#ifndef _SDL_ipodvideo_h +#define _SDL_ipodvideo_h + +struct SDL_PrivateVideoData { + char *buffer; + int w, h; +}; + + +#endif diff --git a/3rdparty/SDL/src/video/maccommon/SDL_lowvideo.h b/3rdparty/SDL/src/video/maccommon/SDL_lowvideo.h new file mode 100644 index 0000000..f3dac29 --- /dev/null +++ b/3rdparty/SDL/src/video/maccommon/SDL_lowvideo.h @@ -0,0 +1,102 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#ifndef _SDL_lowvideo_h +#define _SDL_lowvideo_h + +#if defined(__APPLE__) && defined(__MACH__) +#include <Carbon/Carbon.h> +#elif TARGET_API_MAC_CARBON && (UNIVERSAL_INTERFACES_VERSION > 0x0335) +#include <Carbon.h> +#else +#include <Quickdraw.h> +#include <Palettes.h> +#include <Menus.h> +#include <DrawSprocket.h> +#endif + +#if SDL_VIDEO_OPENGL +typedef struct __AGLContextRec *AGLContext; +#endif + +#include "SDL_video.h" +#include "../SDL_sysvideo.h" + +/* Hidden "this" pointer for the video functions */ +#define _THIS SDL_VideoDevice *this + +#if !TARGET_API_MAC_CARBON /* not available in OS X (or more accurately, Carbon) */ +/* Global QuickDraw data */ +extern QDGlobals *theQD; +#endif + +/* Private display data */ +struct SDL_PrivateVideoData { + GDevice **SDL_Display; + WindowRef SDL_Window; + SDL_Rect **SDL_modelist; + CTabHandle SDL_CTab; + PaletteHandle SDL_CPal; + +#if TARGET_API_MAC_CARBON + /* For entering and leaving fullscreen mode */ + Ptr fullscreen_ctx; +#endif + + /* The current window document style */ + int current_style; + + /* Information about the last cursor position */ + Point last_where; + + /* Information about the last keys down */ + EventModifiers last_mods; + KeyMap last_keys; + + /* A handle to the Apple Menu */ + MenuRef apple_menu; + + /* Information used by DrawSprocket driver */ + struct DSpInfo *dspinfo; + +#if SDL_VIDEO_OPENGL + AGLContext appleGLContext; + + void *libraryHandle; +#endif +}; +/* Old variable names */ +#define SDL_Display (this->hidden->SDL_Display) +#define SDL_Window (this->hidden->SDL_Window) +#define SDL_modelist (this->hidden->SDL_modelist) +#define SDL_CTab (this->hidden->SDL_CTab) +#define SDL_CPal (this->hidden->SDL_CPal) +#define fullscreen_ctx (this->hidden->fullscreen_ctx) +#define current_style (this->hidden->current_style) +#define last_where (this->hidden->last_where) +#define last_mods (this->hidden->last_mods) +#define last_keys (this->hidden->last_keys) +#define apple_menu (this->hidden->apple_menu) +#define glContext (this->hidden->appleGLContext) + +#endif /* _SDL_lowvideo_h */ diff --git a/3rdparty/SDL/src/video/maccommon/SDL_macevents.c b/3rdparty/SDL/src/video/maccommon/SDL_macevents.c new file mode 100644 index 0000000..6e3fef2 --- /dev/null +++ b/3rdparty/SDL/src/video/maccommon/SDL_macevents.c @@ -0,0 +1,746 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#include <stdio.h> + +#if defined(__APPLE__) && defined(__MACH__) +#include <Carbon/Carbon.h> +#elif TARGET_API_MAC_CARBON && (UNIVERSAL_INTERFACES_VERSION > 0x0335) +#include <Carbon.h> +#else +#include <Script.h> +#include <LowMem.h> +#include <Devices.h> +#include <DiskInit.h> +#include <ToolUtils.h> +#endif + +#include "SDL_events.h" +#include "SDL_video.h" +#include "SDL_syswm.h" +#include "../../events/SDL_events_c.h" +#include "../../events/SDL_sysevents.h" +#include "../SDL_cursor_c.h" +#include "SDL_macevents_c.h" +#include "SDL_mackeys.h" +#include "SDL_macmouse_c.h" + +/* Define this to be able to collapse SDL windows. +#define USE_APPEARANCE_MANAGER + */ + +/* Macintosh resource constants */ +#define mApple 128 /* Apple menu resource */ +#define iAbout 1 /* About menu item */ + +/* Functions to handle the About menu */ +static void Mac_DoAppleMenu(_THIS, long item); + +/* The translation table from a macintosh key scancode to a SDL keysym */ +static SDLKey MAC_keymap[256]; +static SDL_keysym *TranslateKey(int scancode, int modifiers, + SDL_keysym *keysym, int pressed); + +/* Handle activation and deactivation -- returns whether an event was posted */ +static int Mac_HandleActivate(int activate) +{ + if ( activate ) { + /* Show the current SDL application cursor */ + SDL_SetCursor(NULL); + + /* put our mask back case it changed during context switch */ + SetEventMask(everyEvent & ~autoKeyMask); + } else { +#if TARGET_API_MAC_CARBON + { Cursor cursor; + SetCursor(GetQDGlobalsArrow(&cursor)); + } +#else + SetCursor(&theQD->arrow); +#endif + if ( ! Mac_cursor_showing ) { + ShowCursor(); + Mac_cursor_showing = 1; + } + } + return(SDL_PrivateAppActive(activate, SDL_APPINPUTFOCUS)); +} + +static void myGlobalToLocal(_THIS, Point *pt) +{ + if ( SDL_VideoSurface && !(SDL_VideoSurface->flags&SDL_FULLSCREEN) ) { + GrafPtr saveport; + GetPort(&saveport); +#if TARGET_API_MAC_CARBON + SetPort(GetWindowPort(SDL_Window)); +#else + SetPort(SDL_Window); +#endif + GlobalToLocal(pt); + SetPort(saveport); + } +} + +/* The main MacOS event handler */ +static int Mac_HandleEvents(_THIS, int wait4it) +{ + static int mouse_button = 1; + int i; + EventRecord event; + +#if TARGET_API_MAC_CARBON + /* There's no GetOSEvent() in the Carbon API. *sigh* */ +#define cooperative_multitasking 1 +#else + int cooperative_multitasking; + /* If we're running fullscreen, we can hog the MacOS events, + otherwise we had better play nicely with the other apps. + */ + if ( this->screen && (this->screen->flags & SDL_FULLSCREEN) ) { + cooperative_multitasking = 0; + } else { + cooperative_multitasking = 1; + } +#endif + + /* If we call WaitNextEvent(), MacOS will check other processes + * and allow them to run, and perform other high-level processing. + */ + if ( cooperative_multitasking || wait4it ) { + UInt32 wait_time; + + /* Are we polling or not? */ + if ( wait4it ) { + wait_time = 2147483647; + } else { + wait_time = 0; + } + WaitNextEvent(everyEvent, &event, wait_time, nil); + } else { +#if ! TARGET_API_MAC_CARBON + GetOSEvent(everyEvent, &event); +#endif + } + +#if TARGET_API_MAC_CARBON + /* for some reason, event.where isn't set ? */ + GetGlobalMouse ( &event.where ); +#endif + + /* Check for mouse motion */ + if ( (event.where.h != last_where.h) || + (event.where.v != last_where.v) ) { + Point pt; + pt = last_where = event.where; + myGlobalToLocal(this, &pt); + SDL_PrivateMouseMotion(0, 0, pt.h, pt.v); + } + + /* Check the current state of the keyboard */ + if ( SDL_GetAppState() & SDL_APPINPUTFOCUS ) { + KeyMap keys; + const Uint32 *keysptr = (Uint32 *) &keys; + const Uint32 *last_keysptr = (Uint32 *) &last_keys; + + /* Check for special non-event keys */ + if ( event.modifiers != last_mods ) { + static struct { + EventModifiers mask; + SDLKey key; + } mods[] = { + { alphaLock, SDLK_CAPSLOCK }, +#if 0 /* These are handled below in the GetKeys() code */ + { cmdKey, SDLK_LMETA }, + { shiftKey, SDLK_LSHIFT }, + { rightShiftKey, SDLK_RSHIFT }, + { optionKey, SDLK_LALT }, + { rightOptionKey, SDLK_RALT }, + { controlKey, SDLK_LCTRL }, + { rightControlKey, SDLK_RCTRL }, +#endif /* 0 */ + { 0, 0 } + }; + SDL_keysym keysym; + Uint8 mode; + EventModifiers mod, mask; + + + /* Set up the keyboard event */ + keysym.scancode = 0; + keysym.sym = SDLK_UNKNOWN; + keysym.mod = KMOD_NONE; + keysym.unicode = 0; + + /* See what has changed, and generate events */ + mod = event.modifiers; + for ( i=0; mods[i].mask; ++i ) { + mask = mods[i].mask; + if ( (mod&mask) != (last_mods&mask) ) { + keysym.sym = mods[i].key; + if ( (mod&mask) || + (mods[i].key == SDLK_CAPSLOCK) ) { + mode = SDL_PRESSED; + } else { + mode = SDL_RELEASED; + } + SDL_PrivateKeyboard(mode, &keysym); + } + } + + /* Save state for next time */ + last_mods = mod; + } + + /* Check for normal event keys, but we have to scan the + actual keyboard state because on Mac OS X a keydown event + is immediately followed by a keyup event. + */ + GetKeys(keys); + if ( (keysptr[0] != last_keysptr[0]) || + (keysptr[1] != last_keysptr[1]) || + (keysptr[2] != last_keysptr[2]) || + (keysptr[3] != last_keysptr[3]) ) { + SDL_keysym keysym; + int old_bit, new_bit; + +#ifdef DEBUG_KEYBOARD + fprintf(sterr, "New keys: 0x%x 0x%x 0x%x 0x%x\n", + new_keys[0], new_keys[1], + new_keys[2], new_keys[3]); +#endif + for ( i=0; i<128; ++i ) { + old_bit = (((Uint8 *)last_keys)[i/8]>>(i%8)) & 0x01; + new_bit = (((Uint8 *)keys)[i/8]>>(i%8)) & 0x01; + if ( old_bit != new_bit ) { + /* Post the keyboard event */ +#ifdef DEBUG_KEYBOARD + fprintf(stderr,"Scancode: 0x%2.2X\n",i); +#endif + SDL_PrivateKeyboard(new_bit, + TranslateKey(i, event.modifiers, + &keysym, new_bit)); + } + } + + /* Save state for next time */ + last_keys[0] = keys[0]; + last_keys[1] = keys[1]; + last_keys[2] = keys[2]; + last_keys[3] = keys[3]; + } + } + + /* Handle normal events */ + switch (event.what) { + case mouseDown: { + WindowRef win; + short area; + + area = FindWindow(event.where, &win); + /* Support switching between the SIOUX console + and SDL_Window by clicking in the window. + */ + if ( win && (win != FrontWindow()) ) { + SelectWindow(win); + } + switch (area) { + case inMenuBar: /* Only the apple menu exists */ + Mac_DoAppleMenu(this, MenuSelect(event.where)); + HiliteMenu(0); + break; + case inDrag: +#if TARGET_API_MAC_CARBON + DragWindow(win, event.where, NULL); +#else + DragWindow(win, event.where, &theQD->screenBits.bounds); +#endif + break; + case inGoAway: + if ( TrackGoAway(win, event.where) ) { + SDL_PrivateQuit(); + } + break; + case inContent: + myGlobalToLocal(this, &event.where); + /* Treat command-click as right mouse button */ + if ( event.modifiers & optionKey ) { + mouse_button = 2; + } else if ( event.modifiers & cmdKey ) { + mouse_button = 3; + } else { + mouse_button = 1; + } + SDL_PrivateMouseButton(SDL_PRESSED, + mouse_button, event.where.h, event.where.v); + break; + case inGrow: { + int newSize; + + /* Don't allow resize if video mode isn't resizable */ + if ( ! SDL_PublicSurface || + ! (SDL_PublicSurface->flags & SDL_RESIZABLE) ) { + break; + } +#if TARGET_API_MAC_CARBON + newSize = GrowWindow(win, event.where, NULL); +#else + newSize = GrowWindow(win, event.where, &theQD->screenBits.bounds); +#endif + if ( newSize ) { +#if !TARGET_API_MAC_CARBON + EraseRect ( &theQD->screenBits.bounds ); +#endif + SizeWindow ( win, LoWord (newSize), HiWord (newSize), 1 ); + SDL_PrivateResize ( LoWord (newSize), HiWord (newSize) ); + } + } break; + case inZoomIn: + case inZoomOut: + if ( TrackBox (win, event.where, area )) { + Rect rect; +#if !TARGET_API_MAC_CARBON + EraseRect ( &theQD->screenBits.bounds ); +#endif + ZoomWindow ( win, area, 0); + if ( area == inZoomIn ) { + GetWindowUserState(SDL_Window, &rect); + } else { + GetWindowStandardState(SDL_Window, &rect); + } + SDL_PrivateResize (rect.right-rect.left, + rect.bottom-rect.top); + } + break; +#if TARGET_API_MAC_CARBON + case inCollapseBox: + if ( TrackBox (win, event.where, area )) { + if ( IsWindowCollapsable(win) ) { + CollapseWindow (win, !IsWindowCollapsed(win)); + /* There should be something done like in inGrow case, but... */ + } + } + break; +#endif /* TARGET_API_MAC_CARBON */ + case inSysWindow: +#if TARGET_API_MAC_CARBON + /* Never happens in Carbon? */ +#else + SystemClick(&event, win); +#endif + break; + default: + break; + } + } + break; + case mouseUp: { + myGlobalToLocal(this, &event.where); + /* Release the mouse button we simulated in the last press. + The drawback of this methos is we cannot press more than + one button. However, this doesn't matter, since there is + only a single logical mouse button, even if you have a + multi-button mouse, this doesn't matter at all. + */ + SDL_PrivateMouseButton(SDL_RELEASED, + mouse_button, event.where.h, event.where.v); + } + break; +#if 0 /* Handled above the switch statement */ + case keyDown: { + SDL_keysym keysym; + + SDL_PrivateKeyboard(SDL_PRESSED, + TranslateKey((event.message&keyCodeMask)>>8 + event.modifiers, &keysym, 1)); + } + break; + case keyUp: { + SDL_keysym keysym; + + SDL_PrivateKeyboard(SDL_RELEASED, + TranslateKey((event.message&keyCodeMask)>>8 + event.modifiers, &keysym, 0)); + } + break; +#endif + case updateEvt: { + BeginUpdate(SDL_Window); + #if SDL_VIDEO_OPENGL + if (SDL_VideoSurface->flags & SDL_OPENGL) + SDL_GL_SwapBuffers(); + else + #endif + if ( (SDL_VideoSurface->flags & SDL_HWSURFACE) == + SDL_SWSURFACE ) { + SDL_UpdateRect(SDL_VideoSurface, 0, 0, 0, 0); + } + EndUpdate(SDL_Window); + } + /* If this was an update event for the SIOUX console, we return 0 + in order to stop an endless series of updates being triggered. + */ + if ( (WindowRef) event.message != SDL_Window ) { + return 0; + } + break; + case activateEvt: { + Mac_HandleActivate(!!(event.modifiers & activeFlag)); + } + break; + case diskEvt: { +#if TARGET_API_MAC_CARBON + /* What are we supposed to do? */; +#else + if ( ((event.message>>16)&0xFFFF) != noErr ) { + Point spot; + SetPt(&spot, 0x0070, 0x0050); + DIBadMount(spot, event.message); + } +#endif + } + break; + case osEvt: { + switch ((event.message>>24) & 0xFF) { +#if 0 /* Handled above the switch statement */ + case mouseMovedMessage: { + myGlobalToLocal(this, &event.where); + SDL_PrivateMouseMotion(0, 0, + event.where.h, event.where.v); + } + break; +#endif /* 0 */ + case suspendResumeMessage: { + Mac_HandleActivate(!!(event.message & resumeFlag)); + } + break; + } + } + break; + default: { + ; + } + break; + } + return (event.what != nullEvent); +} + + +void Mac_PumpEvents(_THIS) +{ + /* Process pending MacOS events */ + while ( Mac_HandleEvents(this, 0) ) { + /* Loop and check again */; + } +} + +void Mac_InitOSKeymap(_THIS) +{ + const void *KCHRPtr; + UInt32 state; + UInt32 value; + int i; + int world = SDLK_WORLD_0; + + /* Map the MAC keysyms */ + for ( i=0; i<SDL_arraysize(MAC_keymap); ++i ) + MAC_keymap[i] = SDLK_UNKNOWN; + + /* Defined MAC_* constants */ + MAC_keymap[MK_ESCAPE] = SDLK_ESCAPE; + MAC_keymap[MK_F1] = SDLK_F1; + MAC_keymap[MK_F2] = SDLK_F2; + MAC_keymap[MK_F3] = SDLK_F3; + MAC_keymap[MK_F4] = SDLK_F4; + MAC_keymap[MK_F5] = SDLK_F5; + MAC_keymap[MK_F6] = SDLK_F6; + MAC_keymap[MK_F7] = SDLK_F7; + MAC_keymap[MK_F8] = SDLK_F8; + MAC_keymap[MK_F9] = SDLK_F9; + MAC_keymap[MK_F10] = SDLK_F10; + MAC_keymap[MK_F11] = SDLK_F11; + MAC_keymap[MK_F12] = SDLK_F12; + MAC_keymap[MK_PRINT] = SDLK_PRINT; + MAC_keymap[MK_SCROLLOCK] = SDLK_SCROLLOCK; + MAC_keymap[MK_PAUSE] = SDLK_PAUSE; + MAC_keymap[MK_POWER] = SDLK_POWER; + MAC_keymap[MK_BACKQUOTE] = SDLK_BACKQUOTE; + MAC_keymap[MK_1] = SDLK_1; + MAC_keymap[MK_2] = SDLK_2; + MAC_keymap[MK_3] = SDLK_3; + MAC_keymap[MK_4] = SDLK_4; + MAC_keymap[MK_5] = SDLK_5; + MAC_keymap[MK_6] = SDLK_6; + MAC_keymap[MK_7] = SDLK_7; + MAC_keymap[MK_8] = SDLK_8; + MAC_keymap[MK_9] = SDLK_9; + MAC_keymap[MK_0] = SDLK_0; + MAC_keymap[MK_MINUS] = SDLK_MINUS; + MAC_keymap[MK_EQUALS] = SDLK_EQUALS; + MAC_keymap[MK_BACKSPACE] = SDLK_BACKSPACE; + MAC_keymap[MK_INSERT] = SDLK_INSERT; + MAC_keymap[MK_HOME] = SDLK_HOME; + MAC_keymap[MK_PAGEUP] = SDLK_PAGEUP; + MAC_keymap[MK_NUMLOCK] = SDLK_NUMLOCK; + MAC_keymap[MK_KP_EQUALS] = SDLK_KP_EQUALS; + MAC_keymap[MK_KP_DIVIDE] = SDLK_KP_DIVIDE; + MAC_keymap[MK_KP_MULTIPLY] = SDLK_KP_MULTIPLY; + MAC_keymap[MK_TAB] = SDLK_TAB; + MAC_keymap[MK_q] = SDLK_q; + MAC_keymap[MK_w] = SDLK_w; + MAC_keymap[MK_e] = SDLK_e; + MAC_keymap[MK_r] = SDLK_r; + MAC_keymap[MK_t] = SDLK_t; + MAC_keymap[MK_y] = SDLK_y; + MAC_keymap[MK_u] = SDLK_u; + MAC_keymap[MK_i] = SDLK_i; + MAC_keymap[MK_o] = SDLK_o; + MAC_keymap[MK_p] = SDLK_p; + MAC_keymap[MK_LEFTBRACKET] = SDLK_LEFTBRACKET; + MAC_keymap[MK_RIGHTBRACKET] = SDLK_RIGHTBRACKET; + MAC_keymap[MK_BACKSLASH] = SDLK_BACKSLASH; + MAC_keymap[MK_DELETE] = SDLK_DELETE; + MAC_keymap[MK_END] = SDLK_END; + MAC_keymap[MK_PAGEDOWN] = SDLK_PAGEDOWN; + MAC_keymap[MK_KP7] = SDLK_KP7; + MAC_keymap[MK_KP8] = SDLK_KP8; + MAC_keymap[MK_KP9] = SDLK_KP9; + MAC_keymap[MK_KP_MINUS] = SDLK_KP_MINUS; + MAC_keymap[MK_CAPSLOCK] = SDLK_CAPSLOCK; + MAC_keymap[MK_a] = SDLK_a; + MAC_keymap[MK_s] = SDLK_s; + MAC_keymap[MK_d] = SDLK_d; + MAC_keymap[MK_f] = SDLK_f; + MAC_keymap[MK_g] = SDLK_g; + MAC_keymap[MK_h] = SDLK_h; + MAC_keymap[MK_j] = SDLK_j; + MAC_keymap[MK_k] = SDLK_k; + MAC_keymap[MK_l] = SDLK_l; + MAC_keymap[MK_SEMICOLON] = SDLK_SEMICOLON; + MAC_keymap[MK_QUOTE] = SDLK_QUOTE; + MAC_keymap[MK_RETURN] = SDLK_RETURN; + MAC_keymap[MK_KP4] = SDLK_KP4; + MAC_keymap[MK_KP5] = SDLK_KP5; + MAC_keymap[MK_KP6] = SDLK_KP6; + MAC_keymap[MK_KP_PLUS] = SDLK_KP_PLUS; + MAC_keymap[MK_LSHIFT] = SDLK_LSHIFT; + MAC_keymap[MK_z] = SDLK_z; + MAC_keymap[MK_x] = SDLK_x; + MAC_keymap[MK_c] = SDLK_c; + MAC_keymap[MK_v] = SDLK_v; + MAC_keymap[MK_b] = SDLK_b; + MAC_keymap[MK_n] = SDLK_n; + MAC_keymap[MK_m] = SDLK_m; + MAC_keymap[MK_COMMA] = SDLK_COMMA; + MAC_keymap[MK_PERIOD] = SDLK_PERIOD; + MAC_keymap[MK_SLASH] = SDLK_SLASH; +#if 0 /* These are the same as the left versions - use left by default */ + MAC_keymap[MK_RSHIFT] = SDLK_RSHIFT; +#endif + MAC_keymap[MK_UP] = SDLK_UP; + MAC_keymap[MK_KP1] = SDLK_KP1; + MAC_keymap[MK_KP2] = SDLK_KP2; + MAC_keymap[MK_KP3] = SDLK_KP3; + MAC_keymap[MK_KP_ENTER] = SDLK_KP_ENTER; + MAC_keymap[MK_LCTRL] = SDLK_LCTRL; + MAC_keymap[MK_LALT] = SDLK_LALT; + MAC_keymap[MK_LMETA] = SDLK_LMETA; + MAC_keymap[MK_SPACE] = SDLK_SPACE; +#if 0 /* These are the same as the left versions - use left by default */ + MAC_keymap[MK_RMETA] = SDLK_RMETA; + MAC_keymap[MK_RALT] = SDLK_RALT; + MAC_keymap[MK_RCTRL] = SDLK_RCTRL; +#endif + MAC_keymap[MK_LEFT] = SDLK_LEFT; + MAC_keymap[MK_DOWN] = SDLK_DOWN; + MAC_keymap[MK_RIGHT] = SDLK_RIGHT; + MAC_keymap[MK_KP0] = SDLK_KP0; + MAC_keymap[MK_KP_PERIOD] = SDLK_KP_PERIOD; + +#if defined(__APPLE__) && defined(__MACH__) + /* Wierd, these keys are on my iBook under Mac OS X + Note that the left arrow keysym is the same as left ctrl!? + */ + MAC_keymap[MK_IBOOK_ENTER] = SDLK_KP_ENTER; + MAC_keymap[MK_IBOOK_RIGHT] = SDLK_RIGHT; + MAC_keymap[MK_IBOOK_DOWN] = SDLK_DOWN; + MAC_keymap[MK_IBOOK_UP] = SDLK_UP; + MAC_keymap[MK_IBOOK_LEFT] = SDLK_LEFT; +#endif /* Mac OS X */ + + /* Up there we setup a static scancode->keysym map. However, it will not + * work very well on international keyboard. Hence we now query MacOS + * for its own keymap to adjust our own mapping table. However, this is + * bascially only useful for ascii char keys. This is also the reason + * why we keep the static table, too. + */ + + /* Get a pointer to the systems cached KCHR */ + KCHRPtr = (void *)GetScriptManagerVariable(smKCHRCache); + if (KCHRPtr) + { + /* Loop over all 127 possible scan codes */ + for (i = 0; i < 0x7F; i++) + { + /* We pretend a clean start to begin with (i.e. no dead keys active */ + state = 0; + + /* Now translate the key code to a key value */ + value = KeyTranslate(KCHRPtr, i, &state) & 0xff; + + /* If the state become 0, it was a dead key. We need to translate again, + passing in the new state, to get the actual key value */ + if (state != 0) + value = KeyTranslate(KCHRPtr, i, &state) & 0xff; + + /* Now we should have an ascii value, or 0. Try to figure out to which SDL symbol it maps */ + if (value >= 128) /* Some non-ASCII char, map it to SDLK_WORLD_* */ + MAC_keymap[i] = world++; + else if (value >= 32) /* non-control ASCII char */ + MAC_keymap[i] = value; + } + } + + /* The keypad codes are re-setup here, because the loop above cannot + * distinguish between a key on the keypad and a regular key. We maybe + * could get around this problem in another fashion: NSEvent's flags + * include a "NSNumericPadKeyMask" bit; we could check that and modify + * the symbol we return on the fly. However, this flag seems to exhibit + * some weird behaviour related to the num lock key + */ + MAC_keymap[MK_KP0] = SDLK_KP0; + MAC_keymap[MK_KP1] = SDLK_KP1; + MAC_keymap[MK_KP2] = SDLK_KP2; + MAC_keymap[MK_KP3] = SDLK_KP3; + MAC_keymap[MK_KP4] = SDLK_KP4; + MAC_keymap[MK_KP5] = SDLK_KP5; + MAC_keymap[MK_KP6] = SDLK_KP6; + MAC_keymap[MK_KP7] = SDLK_KP7; + MAC_keymap[MK_KP8] = SDLK_KP8; + MAC_keymap[MK_KP9] = SDLK_KP9; + MAC_keymap[MK_KP_MINUS] = SDLK_KP_MINUS; + MAC_keymap[MK_KP_PLUS] = SDLK_KP_PLUS; + MAC_keymap[MK_KP_PERIOD] = SDLK_KP_PERIOD; + MAC_keymap[MK_KP_EQUALS] = SDLK_KP_EQUALS; + MAC_keymap[MK_KP_DIVIDE] = SDLK_KP_DIVIDE; + MAC_keymap[MK_KP_MULTIPLY] = SDLK_KP_MULTIPLY; + MAC_keymap[MK_KP_ENTER] = SDLK_KP_ENTER; +} + +static SDL_keysym *TranslateKey(int scancode, int modifiers, + SDL_keysym *keysym, int pressed) +{ + /* Set the keysym information */ + keysym->scancode = scancode; + keysym->sym = MAC_keymap[keysym->scancode]; + keysym->mod = KMOD_NONE; + keysym->unicode = 0; + if ( pressed && SDL_TranslateUNICODE ) { + static unsigned long state = 0; + static Ptr keymap = nil; + Ptr new_keymap; + + /* Get the current keyboard map resource */ + new_keymap = (Ptr)GetScriptManagerVariable(smKCHRCache); + if ( new_keymap != keymap ) { + keymap = new_keymap; + state = 0; + } + keysym->unicode = KeyTranslate(keymap, + keysym->scancode|modifiers, &state) & 0xFFFF; + } + return(keysym); +} + +void Mac_InitEvents(_THIS) +{ + /* Create apple menu bar */ + apple_menu = GetMenu(mApple); + if ( apple_menu != nil ) { + AppendResMenu(apple_menu, 'DRVR'); + InsertMenu(apple_menu, 0); + } + DrawMenuBar(); + + /* Get rid of spurious events at startup */ + FlushEvents(everyEvent, 0); + + /* Allow every event but keyrepeat */ + SetEventMask(everyEvent & ~autoKeyMask); +} + +void Mac_QuitEvents(_THIS) +{ + ClearMenuBar(); + if ( apple_menu != nil ) { + ReleaseResource((char **)apple_menu); + } + + /* Clean up pending events */ + FlushEvents(everyEvent, 0); +} + +static void Mac_DoAppleMenu(_THIS, long choice) +{ +#if !TARGET_API_MAC_CARBON /* No Apple menu in OS X */ + short menu, item; + + item = (choice&0xFFFF); + choice >>= 16; + menu = (choice&0xFFFF); + + switch (menu) { + case mApple: { + switch (item) { + case iAbout: { + /* Run the about box */; + } + break; + default: { + Str255 name; + + GetMenuItemText(apple_menu, item, name); + OpenDeskAcc(name); + } + break; + } + } + break; + default: { + /* Ignore other menus */; + } + } +#endif /* !TARGET_API_MAC_CARBON */ +} + +#if !TARGET_API_MAC_CARBON +/* Since we don't initialize QuickDraw, we need to get a pointer to qd */ +struct QDGlobals *theQD = NULL; +#endif + +/* Exported to the macmain code */ +void SDL_InitQuickDraw(struct QDGlobals *the_qd) +{ +#if !TARGET_API_MAC_CARBON + theQD = the_qd; +#endif +} diff --git a/3rdparty/SDL/src/video/maccommon/SDL_macevents_c.h b/3rdparty/SDL/src/video/maccommon/SDL_macevents_c.h new file mode 100644 index 0000000..f9a983b --- /dev/null +++ b/3rdparty/SDL/src/video/maccommon/SDL_macevents_c.h @@ -0,0 +1,32 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#include "../macrom/SDL_romvideo.h" + +/* Functions exported by SDL_macevents.c for the video subsystem +*/ +extern void Mac_InitEvents(_THIS); +extern void Mac_QuitEvents(_THIS); + +extern void Mac_InitOSKeymap(_THIS); +extern void Mac_PumpEvents(_THIS); diff --git a/3rdparty/SDL/src/video/maccommon/SDL_macgl.c b/3rdparty/SDL/src/video/maccommon/SDL_macgl.c new file mode 100644 index 0000000..b7ded9b --- /dev/null +++ b/3rdparty/SDL/src/video/maccommon/SDL_macgl.c @@ -0,0 +1,197 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* AGL implementation of SDL OpenGL support */ + +#include "SDL_lowvideo.h" +#include "SDL_macgl_c.h" +#include "SDL_loadso.h" + + +/* krat: adding OpenGL support */ +int Mac_GL_Init(_THIS) +{ +#if SDL_VIDEO_OPENGL + AGLPixelFormat format; + int i = 0; + GLint attributes [ 26 ]; /* 26 is max possible in this setup */ + GLboolean noerr; + + /* load the gl driver from a default path */ + if ( ! this->gl_config.driver_loaded ) { + /* no driver has been loaded, use default (ourselves) */ + if ( Mac_GL_LoadLibrary(this, NULL) < 0 ) { + return(-1); + } + } + + attributes[i++] = AGL_RGBA; + if ( this->gl_config.red_size != 0 && + this->gl_config.blue_size != 0 && + this->gl_config.green_size != 0 ) { + attributes[i++] = AGL_RED_SIZE; + attributes[i++] = this->gl_config.red_size; + attributes[i++] = AGL_GREEN_SIZE; + attributes[i++] = this->gl_config.green_size; + attributes[i++] = AGL_BLUE_SIZE; + attributes[i++] = this->gl_config.blue_size; + attributes[i++] = AGL_ALPHA_SIZE; + attributes[i++] = this->gl_config.alpha_size; + } + if ( this->gl_config.double_buffer ) { + attributes[i++] = AGL_DOUBLEBUFFER; + } + if ( this->gl_config.depth_size != 0 ) { + attributes[i++] = AGL_DEPTH_SIZE; + attributes[i++] = this->gl_config.depth_size; + } + if ( this->gl_config.stencil_size != 0 ) { + attributes[i++] = AGL_STENCIL_SIZE; + attributes[i++] = this->gl_config.stencil_size; + } + if ( this->gl_config.accum_red_size != 0 && + this->gl_config.accum_blue_size != 0 && + this->gl_config.accum_green_size != 0 ) { + + attributes[i++] = AGL_ACCUM_RED_SIZE; + attributes[i++] = this->gl_config.accum_red_size; + attributes[i++] = AGL_ACCUM_GREEN_SIZE; + attributes[i++] = this->gl_config.accum_green_size; + attributes[i++] = AGL_ACCUM_BLUE_SIZE; + attributes[i++] = this->gl_config.accum_blue_size; + attributes[i++] = AGL_ACCUM_ALPHA_SIZE; + attributes[i++] = this->gl_config.accum_alpha_size; + } + if ( this->gl_config.stereo ) { + attributes[i++] = AGL_STEREO; + } +#if defined(AGL_SAMPLE_BUFFERS_ARB) && defined(AGL_SAMPLES_ARB) + if ( this->gl_config.multisamplebuffers != 0 ) { + attributes[i++] = AGL_SAMPLE_BUFFERS_ARB; + attributes[i++] = this->gl_config.multisamplebuffers; + } + if ( this->gl_config.multisamplesamples != 0 ) { + attributes[i++] = AGL_SAMPLES_ARB; + attributes[i++] = this->gl_config.multisamplesamples; + } +#endif + if ( this->gl_config.accelerated > 0 ) { + attributes[i++] = AGL_ACCELERATED; + attributes[i++] = AGL_NO_RECOVERY; + } + + attributes[i++] = AGL_ALL_RENDERERS; + attributes[i] = AGL_NONE; + + format = aglChoosePixelFormat(NULL, 0, attributes); + if ( format == NULL ) { + SDL_SetError("Couldn't match OpenGL desired format"); + return(-1); + } + + glContext = aglCreateContext(format, NULL); + if ( glContext == NULL ) { + SDL_SetError("Couldn't create OpenGL context"); + return(-1); + } + aglDestroyPixelFormat(format); + + #if TARGET_API_MAC_CARBON + noerr = aglSetDrawable(glContext, GetWindowPort(SDL_Window)); + #else + noerr = aglSetDrawable(glContext, (AGLDrawable)SDL_Window); + #endif + + if(!noerr) { + SDL_SetError("Unable to bind GL context to window"); + return(-1); + } + return(0); +#else + SDL_SetError("OpenGL support not configured"); + return(-1); +#endif +} + +void Mac_GL_Quit(_THIS) +{ +#if SDL_VIDEO_OPENGL + if ( glContext != NULL ) { + aglSetCurrentContext(NULL); + aglSetDrawable(glContext, NULL); + aglDestroyContext(glContext); + glContext = NULL; + } +#endif +} + +#if SDL_VIDEO_OPENGL + +/* Make the current context active */ +int Mac_GL_MakeCurrent(_THIS) +{ + int retval; + + retval = 0; + if( ! aglSetCurrentContext(glContext) ) { + SDL_SetError("Unable to make GL context current"); + retval = -1; + } + return(retval); +} + +void Mac_GL_SwapBuffers(_THIS) +{ + aglSwapBuffers(glContext); +} + +int Mac_GL_LoadLibrary(_THIS, const char *location) +{ + if (location == NULL) +#if __MACH__ + location = "/System/Library/Frameworks/OpenGL.framework/OpenGL"; +#else + location = "OpenGLLibrary"; +#endif + + this->hidden->libraryHandle = SDL_LoadObject(location); + + this->gl_config.driver_loaded = 1; + return (this->hidden->libraryHandle != NULL) ? 0 : -1; +} + +void Mac_GL_UnloadLibrary(_THIS) +{ + SDL_UnloadObject(this->hidden->libraryHandle); + + this->hidden->libraryHandle = NULL; + this->gl_config.driver_loaded = 0; +} + +void* Mac_GL_GetProcAddress(_THIS, const char *proc) +{ + return SDL_LoadFunction( this->hidden->libraryHandle, proc ); +} + +#endif /* SDL_VIDEO_OPENGL */ + diff --git a/3rdparty/SDL/src/video/maccommon/SDL_macgl_c.h b/3rdparty/SDL/src/video/maccommon/SDL_macgl_c.h new file mode 100644 index 0000000..42cd70f --- /dev/null +++ b/3rdparty/SDL/src/video/maccommon/SDL_macgl_c.h @@ -0,0 +1,47 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ + +/* AGL implementation of SDL OpenGL support */ + +#include "SDL_config.h" + +#if SDL_VIDEO_OPENGL +#include "SDL_opengl.h" +#if __MACOSX__ +#include <AGL/agl.h> /* AGL.framework */ +#else +#include <agl.h> +#endif +#endif /* SDL_VIDEO_OPENGL */ + +/* OpenGL functions */ +extern int Mac_GL_Init(_THIS); +extern void Mac_GL_Quit(_THIS); +#if SDL_VIDEO_OPENGL +extern int Mac_GL_MakeCurrent(_THIS); +extern int Mac_GL_GetAttribute(_THIS, SDL_GLattr attrib, int* value); +extern void Mac_GL_SwapBuffers(_THIS); +extern int Mac_GL_LoadLibrary(_THIS, const char *location); +extern void Mac_GL_UnloadLibrary(_THIS); +extern void* Mac_GL_GetProcAddress(_THIS, const char *proc); +#endif + diff --git a/3rdparty/SDL/src/video/maccommon/SDL_mackeys.h b/3rdparty/SDL/src/video/maccommon/SDL_mackeys.h new file mode 100644 index 0000000..dfed30d --- /dev/null +++ b/3rdparty/SDL/src/video/maccommon/SDL_mackeys.h @@ -0,0 +1,140 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ + +/* These are the Macintosh key scancode constants -- from Inside Macintosh */ + +#define MK_ESCAPE 0x35 +#define MK_F1 0x7A +#define MK_F2 0x78 +#define MK_F3 0x63 +#define MK_F4 0x76 +#define MK_F5 0x60 +#define MK_F6 0x61 +#define MK_F7 0x62 +#define MK_F8 0x64 +#define MK_F9 0x65 +#define MK_F10 0x6D +#define MK_F11 0x67 +#define MK_F12 0x6F +#define MK_PRINT 0x69 +#define MK_SCROLLOCK 0x6B +#define MK_PAUSE 0x71 +#define MK_POWER 0x7F +#define MK_BACKQUOTE 0x32 +#define MK_1 0x12 +#define MK_2 0x13 +#define MK_3 0x14 +#define MK_4 0x15 +#define MK_5 0x17 +#define MK_6 0x16 +#define MK_7 0x1A +#define MK_8 0x1C +#define MK_9 0x19 +#define MK_0 0x1D +#define MK_MINUS 0x1B +#define MK_EQUALS 0x18 +#define MK_BACKSPACE 0x33 +#define MK_INSERT 0x72 +#define MK_HOME 0x73 +#define MK_PAGEUP 0x74 +#define MK_NUMLOCK 0x47 +#define MK_KP_EQUALS 0x51 +#define MK_KP_DIVIDE 0x4B +#define MK_KP_MULTIPLY 0x43 +#define MK_TAB 0x30 +#define MK_q 0x0C +#define MK_w 0x0D +#define MK_e 0x0E +#define MK_r 0x0F +#define MK_t 0x11 +#define MK_y 0x10 +#define MK_u 0x20 +#define MK_i 0x22 +#define MK_o 0x1F +#define MK_p 0x23 +#define MK_LEFTBRACKET 0x21 +#define MK_RIGHTBRACKET 0x1E +#define MK_BACKSLASH 0x2A +#define MK_DELETE 0x75 +#define MK_END 0x77 +#define MK_PAGEDOWN 0x79 +#define MK_KP7 0x59 +#define MK_KP8 0x5B +#define MK_KP9 0x5C +#define MK_KP_MINUS 0x4E +#define MK_CAPSLOCK 0x39 +#define MK_a 0x00 +#define MK_s 0x01 +#define MK_d 0x02 +#define MK_f 0x03 +#define MK_g 0x05 +#define MK_h 0x04 +#define MK_j 0x26 +#define MK_k 0x28 +#define MK_l 0x25 +#define MK_SEMICOLON 0x29 +#define MK_QUOTE 0x27 +#define MK_RETURN 0x24 +#define MK_KP4 0x56 +#define MK_KP5 0x57 +#define MK_KP6 0x58 +#define MK_KP_PLUS 0x45 +#define MK_LSHIFT 0x38 +#define MK_z 0x06 +#define MK_x 0x07 +#define MK_c 0x08 +#define MK_v 0x09 +#define MK_b 0x0B +#define MK_n 0x2D +#define MK_m 0x2E +#define MK_COMMA 0x2B +#define MK_PERIOD 0x2F +#define MK_SLASH 0x2C +#if 0 /* These are the same as the left versions - use left by default */ +#define MK_RSHIFT 0x38 +#endif +#define MK_UP 0x7E +#define MK_KP1 0x53 +#define MK_KP2 0x54 +#define MK_KP3 0x55 +#define MK_KP_ENTER 0x4C +#define MK_LCTRL 0x3B +#define MK_LALT 0x3A +#define MK_LMETA 0x37 +#define MK_SPACE 0x31 +#if 0 /* These are the same as the left versions - use left by default */ +#define MK_RMETA 0x37 +#define MK_RALT 0x3A +#define MK_RCTRL 0x3B +#endif +#define MK_LEFT 0x7B +#define MK_DOWN 0x7D +#define MK_RIGHT 0x7C +#define MK_KP0 0x52 +#define MK_KP_PERIOD 0x41 + +/* Wierd, these keys are on my iBook under Mac OS X */ +#define MK_IBOOK_ENTER 0x34 +#define MK_IBOOK_LEFT 0x3B +#define MK_IBOOK_RIGHT 0x3C +#define MK_IBOOK_DOWN 0x3D +#define MK_IBOOK_UP 0x3E diff --git a/3rdparty/SDL/src/video/maccommon/SDL_macmouse.c b/3rdparty/SDL/src/video/maccommon/SDL_macmouse.c new file mode 100644 index 0000000..f19ad1b --- /dev/null +++ b/3rdparty/SDL/src/video/maccommon/SDL_macmouse.c @@ -0,0 +1,129 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#if defined(__APPLE__) && defined(__MACH__) +#include <Carbon/Carbon.h> +#elif TARGET_API_MAC_CARBON && (UNIVERSAL_INTERFACES_VERSION > 0x0335) +#include <Carbon.h> +#else +#include <Quickdraw.h> +#endif + +/* Routines that are not supported by the Carbon API... */ +#if !TARGET_API_MAC_CARBON +#include <CursorDevices.h> +#endif + +#include "SDL_mouse.h" +#include "SDL_macmouse_c.h" + + +/* The implementation dependent data for the window manager cursor */ +struct WMcursor { + Cursor curs; +}; + + +void Mac_FreeWMCursor(_THIS, WMcursor *cursor) +{ + SDL_free(cursor); +} + +WMcursor *Mac_CreateWMCursor(_THIS, + Uint8 *data, Uint8 *mask, int w, int h, int hot_x, int hot_y) +{ + WMcursor *cursor; + int row, bytes; + + /* Allocate the cursor memory */ + cursor = (WMcursor *)SDL_malloc(sizeof(WMcursor)); + if ( cursor == NULL ) { + SDL_OutOfMemory(); + return(NULL); + } + SDL_memset(cursor, 0, sizeof(*cursor)); + + if (w > 16) + w = 16; + + if (h > 16) + h = 16; + + bytes = (w+7)/8; + + for ( row=0; row<h; ++row ) { + SDL_memcpy(&cursor->curs.data[row], data, bytes); + data += bytes; + } + for ( row=0; row<h; ++row ) { + SDL_memcpy(&cursor->curs.mask[row], mask, bytes); + mask += bytes; + } + cursor->curs.hotSpot.h = hot_x; + cursor->curs.hotSpot.v = hot_y; + + /* That was easy. :) */ + return(cursor); +} + +int Mac_cursor_showing = 1; + +int Mac_ShowWMCursor(_THIS, WMcursor *cursor) +{ + if ( cursor == NULL ) { + if ( Mac_cursor_showing ) { + HideCursor(); + Mac_cursor_showing = 0; + } + } else { + SetCursor(&cursor->curs); + if ( ! Mac_cursor_showing ) { + ShowCursor(); + Mac_cursor_showing = 1; + } + } + return(1); +} + +void Mac_WarpWMCursor(_THIS, Uint16 x, Uint16 y) +{ +#if !TARGET_API_MAC_CARBON + CursorDevice *cursordevice; + + cursordevice = nil; + CursorDeviceNextDevice(&cursordevice); + if ( cursordevice != nil ) { + WindowPtr saveport; + Point where; + + GetPort(&saveport); + SetPort(SDL_Window); + where.h = x; + where.v = y; + LocalToGlobal(&where); + SetPort(saveport); + CursorDeviceMoveTo(cursordevice, where.h, where.v); + } +#endif /* !TARGET_API_MAC_CARBON */ +} + diff --git a/3rdparty/SDL/src/video/maccommon/SDL_macmouse_c.h b/3rdparty/SDL/src/video/maccommon/SDL_macmouse_c.h new file mode 100644 index 0000000..18fb438 --- /dev/null +++ b/3rdparty/SDL/src/video/maccommon/SDL_macmouse_c.h @@ -0,0 +1,34 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#include "../macrom/SDL_romvideo.h" + +/* Functions to be exported */ +extern void Mac_FreeWMCursor(_THIS, WMcursor *cursor); +extern WMcursor *Mac_CreateWMCursor(_THIS, + Uint8 *data, Uint8 *mask, int w, int h, int hot_x, int hot_y); +extern int Mac_ShowWMCursor(_THIS, WMcursor *cursor); +extern void Mac_WarpWMCursor(_THIS, Uint16 x, Uint16 y); + +/* Data to be exported */ +extern int Mac_cursor_showing; diff --git a/3rdparty/SDL/src/video/maccommon/SDL_macwm.c b/3rdparty/SDL/src/video/maccommon/SDL_macwm.c new file mode 100644 index 0000000..6f485a3 --- /dev/null +++ b/3rdparty/SDL/src/video/maccommon/SDL_macwm.c @@ -0,0 +1,442 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#if defined(__APPLE__) && defined(__MACH__) +#include <Carbon/Carbon.h> +#elif TARGET_API_MAC_CARBON && (UNIVERSAL_INTERFACES_VERSION > 0x0335) +#include <Carbon.h> +#else +#include <Windows.h> +#include <Strings.h> +#endif + +#if SDL_MACCLASSIC_GAMMA_SUPPORT +#include <Devices.h> +#include <Files.h> +#include <MacTypes.h> +#include <QDOffscreen.h> +#include <Quickdraw.h> +#include <Video.h> +#endif + +#include "SDL_stdinc.h" +#include "SDL_macwm_c.h" + +void Mac_SetCaption(_THIS, const char *title, const char *icon) +{ + /* Don't convert C to P string in place, because it may be read-only */ + Str255 ptitle; /* MJS */ + ptitle[0] = strlen (title); + SDL_memcpy(ptitle+1, title, ptitle[0]); /* MJS */ + if (SDL_Window) + SetWTitle(SDL_Window, ptitle); /* MJS */ +} + +#if SDL_MACCLASSIC_GAMMA_SUPPORT +/* + * ADC Gamma Ramp support... + * + * Mac Gamma Ramp code was originally from sample code provided by + * Apple Developer Connection, and not written specifically for SDL: + * "Contains: Functions to enable Mac OS device gamma adjustments using 3 channel 256 element 8 bit gamma ramps + * Written by: Geoff Stahl (ggs) + * Copyright: Copyright (c) 1999 Apple Computer, Inc., All Rights Reserved + * Disclaimer: You may incorporate this sample code into your applications without + * restriction, though the sample code has been provided "AS IS" and the + * responsibility for its operation is 100% yours. However, what you are + * not permitted to do is to redistribute the source as "DSC Sample Code" + * after having made changes. If you're going to re-distribute the source, + * we require that you make it clear in the source that the code was + * descended from Apple Sample Code, but that you've made changes." + * (The sample code has been integrated into this file, and thus is modified from the original Apple sources.) + */ + +typedef struct recDeviceGamma /* storage for device handle and gamma table */ +{ + GDHandle hGD; /* handle to device */ + GammaTblPtr pDeviceGamma; /* pointer to device gamma table */ +} recDeviceGamma; +typedef recDeviceGamma * precDeviceGamma; + +typedef struct recSystemGamma /* storage for system devices and gamma tables */ +{ + short numDevices; /* number of devices */ + precDeviceGamma * devGamma; /* array of pointers to device gamma records */ +} recSystemGamma; +typedef recSystemGamma * precSystemGamma; + +static Ptr CopyGammaTable (GammaTblPtr pTableGammaIn) +{ + GammaTblPtr pTableGammaOut = NULL; + short tableSize, dataWidth; + + if (pTableGammaIn) /* if there is a table to copy */ + { + dataWidth = (pTableGammaIn->gDataWidth + 7) / 8; /* number of bytes per entry */ + tableSize = sizeof (GammaTbl) + pTableGammaIn->gFormulaSize + + (pTableGammaIn->gChanCnt * pTableGammaIn->gDataCnt * dataWidth); + pTableGammaOut = (GammaTblPtr) NewPtr (tableSize); /* allocate new table */ + if (pTableGammaOut) + BlockMove( (Ptr)pTableGammaIn, (Ptr)pTableGammaOut, tableSize); /* move everything */ + } + return (Ptr)pTableGammaOut; /* return whatever we allocated, could be NULL */ +} + +static OSErr GetGammaTable (GDHandle hGD, GammaTblPtr * ppTableGammaOut) +{ + VDGammaRecord DeviceGammaRec; + CntrlParam cParam; + OSErr err; + + cParam.ioCompletion = NULL; /* set up control params */ + cParam.ioNamePtr = NULL; + cParam.ioVRefNum = 0; + cParam.ioCRefNum = (**hGD).gdRefNum; + cParam.csCode = cscGetGamma; /* Get Gamma commnd to device */ + *(Ptr *)cParam.csParam = (Ptr) &DeviceGammaRec; /* record for gamma */ + + err = PBStatusSync( (ParmBlkPtr)&cParam ); /* get gamma */ + + *ppTableGammaOut = (GammaTblPtr)(DeviceGammaRec.csGTable); /* pull table out of record */ + + return err; +} + +static Ptr GetDeviceGamma (GDHandle hGD) +{ + GammaTblPtr pTableGammaDevice = NULL; + GammaTblPtr pTableGammaReturn = NULL; + OSErr err; + + err = GetGammaTable (hGD, &pTableGammaDevice); /* get a pointer to the devices table */ + if ((noErr == err) && pTableGammaDevice) /* if succesful */ + pTableGammaReturn = (GammaTblPtr) CopyGammaTable (pTableGammaDevice); /* copy to global */ + + return (Ptr) pTableGammaReturn; +} + +static void DisposeGammaTable (Ptr pGamma) +{ + if (pGamma) + DisposePtr((Ptr) pGamma); /* get rid of it */ +} + +static void DisposeSystemGammas (Ptr* ppSystemGammas) +{ + precSystemGamma pSysGammaIn; + if (ppSystemGammas) + { + pSysGammaIn = (precSystemGamma) *ppSystemGammas; + if (pSysGammaIn) + { + short i; + for (i = 0; i < pSysGammaIn->numDevices; i++) /* for all devices */ + if (pSysGammaIn->devGamma [i]) /* if pointer is valid */ + { + DisposeGammaTable ((Ptr) pSysGammaIn->devGamma [i]->pDeviceGamma); /* dump gamma table */ + DisposePtr ((Ptr) pSysGammaIn->devGamma [i]); /* dump device info */ + } + DisposePtr ((Ptr) pSysGammaIn->devGamma); /* dump device pointer array */ + DisposePtr ((Ptr) pSysGammaIn); /* dump system structure */ + *ppSystemGammas = NULL; + } + } +} + +static Boolean GetDeviceGammaRampGD (GDHandle hGD, Ptr pRamp) +{ + GammaTblPtr pTableGammaTemp = NULL; + long indexChan, indexEntry; + OSErr err; + + if (pRamp) /* ensure pRamp is allocated */ + { + err = GetGammaTable (hGD, &pTableGammaTemp); /* get a pointer to the current gamma */ + if ((noErr == err) && pTableGammaTemp) /* if successful */ + { + /* fill ramp */ + unsigned char * pEntry = (unsigned char *) &pTableGammaTemp->gFormulaData + pTableGammaTemp->gFormulaSize; /* base of table */ + short bytesPerEntry = (pTableGammaTemp->gDataWidth + 7) / 8; /* size, in bytes, of the device table entries */ + short shiftRightValue = pTableGammaTemp->gDataWidth - 8; /* number of right shifts device -> ramp */ + short channels = pTableGammaTemp->gChanCnt; + short entries = pTableGammaTemp->gDataCnt; + if (3 == channels) /* RGB format */ + { /* note, this will create runs of entries if dest. is bigger (not linear interpolate) */ + for (indexChan = 0; indexChan < channels; indexChan++) + for (indexEntry = 0; indexEntry < 256; indexEntry++) + *((unsigned char *) pRamp + (indexChan * 256) + indexEntry) = + *(pEntry + indexChan * entries * bytesPerEntry + indexEntry * entries * bytesPerEntry / 256) >> shiftRightValue; + } + else /* single channel format */ + { + for (indexChan = 0; indexChan < 768; indexChan += 256) /* repeat for all 3 channels (step by ramp size) */ + for (indexEntry = 0; indexEntry < 256; indexEntry++) /* for all entries set vramp value */ + *((unsigned char *) pRamp + indexChan + indexEntry) = + *(pEntry + indexEntry * entries * bytesPerEntry / 256) >> shiftRightValue; + } + return true; + } + } + return false; +} + +static Ptr GetSystemGammas (void) +{ + precSystemGamma pSysGammaOut; /* return pointer to system device gamma info */ + short devCount = 0; /* number of devices attached */ + Boolean fail = false; + GDHandle hGDevice; + + pSysGammaOut = (precSystemGamma) NewPtr (sizeof (recSystemGamma)); /* allocate for structure */ + + hGDevice = GetDeviceList (); /* top of device list */ + do /* iterate */ + { + devCount++; /* count devices */ + hGDevice = GetNextDevice (hGDevice); /* next device */ + } while (hGDevice); + + pSysGammaOut->devGamma = (precDeviceGamma *) NewPtr (sizeof (precDeviceGamma) * devCount); /* allocate for array of pointers to device records */ + if (pSysGammaOut) + { + pSysGammaOut->numDevices = devCount; /* stuff count */ + + devCount = 0; /* reset iteration */ + hGDevice = GetDeviceList (); + do + { + pSysGammaOut->devGamma [devCount] = (precDeviceGamma) NewPtr (sizeof (recDeviceGamma)); /* new device record */ + if (pSysGammaOut->devGamma [devCount]) /* if we actually allocated memory */ + { + pSysGammaOut->devGamma [devCount]->hGD = hGDevice; /* stuff handle */ + pSysGammaOut->devGamma [devCount]->pDeviceGamma = (GammaTblPtr)GetDeviceGamma (hGDevice); /* copy gamma table */ + } + else /* otherwise dump record on exit */ + fail = true; + devCount++; /* next device */ + hGDevice = GetNextDevice (hGDevice); + } while (hGDevice); + } + if (!fail) /* if we did not fail */ + return (Ptr) pSysGammaOut; /* return pointer to structure */ + else + { + DisposeSystemGammas ((Ptr *) &pSysGammaOut); /* otherwise dump the current structures (dispose does error checking) */ + return NULL; /* could not complete */ + } +} + +static void RestoreDeviceGamma (GDHandle hGD, Ptr pGammaTable) +{ + VDSetEntryRecord setEntriesRec; + VDGammaRecord gameRecRestore; + CTabHandle hCTabDeviceColors; + Ptr csPtr; + OSErr err = noErr; + + if (pGammaTable) /* if we have a table to restore */ + { + gameRecRestore.csGTable = pGammaTable; /* setup restore record */ + csPtr = (Ptr) &gameRecRestore; + err = Control((**hGD).gdRefNum, cscSetGamma, (Ptr) &csPtr); /* restore gamma */ + + if ((noErr == err) && (8 == (**(**hGD).gdPMap).pixelSize)) /* if successful and on an 8 bit device */ + { + hCTabDeviceColors = (**(**hGD).gdPMap).pmTable; /* do SetEntries to force CLUT update */ + setEntriesRec.csTable = (ColorSpec *) &(**hCTabDeviceColors).ctTable; + setEntriesRec.csStart = 0; + setEntriesRec.csCount = (**hCTabDeviceColors).ctSize; + csPtr = (Ptr) &setEntriesRec; + + err = Control((**hGD).gdRefNum, cscSetEntries, (Ptr) &csPtr); /* SetEntries in CLUT */ + } + } +} + +static void RestoreSystemGammas (Ptr pSystemGammas) +{ + short i; + precSystemGamma pSysGammaIn = (precSystemGamma) pSystemGammas; + if (pSysGammaIn) + for (i = 0; i < pSysGammaIn->numDevices; i++) /* for all devices */ + RestoreDeviceGamma (pSysGammaIn->devGamma [i]->hGD, (Ptr) pSysGammaIn->devGamma [i]->pDeviceGamma); /* restore gamma */ +} + +static Ptr CreateEmptyGammaTable (short channels, short entries, short bits) +{ + GammaTblPtr pTableGammaOut = NULL; + short tableSize, dataWidth; + + dataWidth = (bits + 7) / 8; /* number of bytes per entry */ + tableSize = sizeof (GammaTbl) + (channels * entries * dataWidth); + pTableGammaOut = (GammaTblPtr) NewPtrClear (tableSize); /* allocate new tabel */ + + if (pTableGammaOut) /* if we successfully allocated */ + { + pTableGammaOut->gVersion = 0; /* set parameters based on input */ + pTableGammaOut->gType = 0; + pTableGammaOut->gFormulaSize = 0; + pTableGammaOut->gChanCnt = channels; + pTableGammaOut->gDataCnt = entries; + pTableGammaOut->gDataWidth = bits; + } + return (Ptr)pTableGammaOut; /* return whatever we allocated */ +} + +static Boolean SetDeviceGammaRampGD (GDHandle hGD, Ptr pRamp) +{ + VDSetEntryRecord setEntriesRec; + VDGammaRecord gameRecRestore; + GammaTblPtr pTableGammaNew; + GammaTblPtr pTableGammaCurrent = NULL; + CTabHandle hCTabDeviceColors; + Ptr csPtr; + OSErr err; + short dataBits, entries, channels = 3; /* force three channels in the gamma table */ + + if (pRamp) /* ensure pRamp is allocated */ + { + err= GetGammaTable (hGD, &pTableGammaCurrent); /* get pointer to current table */ + if ((noErr == err) && pTableGammaCurrent) + { + dataBits = pTableGammaCurrent->gDataWidth; /* table must have same data width */ + entries = pTableGammaCurrent->gDataCnt; /* table must be same size */ + pTableGammaNew = (GammaTblPtr) CreateEmptyGammaTable (channels, entries, dataBits); /* our new table */ + if (pTableGammaNew) /* if successful fill table */ + { + unsigned char * pGammaBase = (unsigned char *) &pTableGammaNew->gFormulaData + pTableGammaNew->gFormulaSize; /* base of table */ + if ((256 == entries) && (8 == dataBits)) /* simple case: direct mapping */ + BlockMove ((Ptr)pRamp, (Ptr)pGammaBase, channels * entries); /* move everything */ + else /* tough case handle entry, channel and data size disparities */ + { + short indexChan, indexEntry; + short bytesPerEntry = (dataBits + 7) / 8; /* size, in bytes, of the device table entries */ + short shiftRightValue = 8 - dataBits; /* number of right shifts ramp -> device */ + shiftRightValue += ((bytesPerEntry - 1) * 8); /* multibyte entries and the need to map a byte at a time most sig. to least sig. */ + for (indexChan = 0; indexChan < channels; indexChan++) /* for all the channels */ + for (indexEntry = 0; indexEntry < entries; indexEntry++) /* for all the entries */ + { + short currentShift = shiftRightValue; /* reset current bit shift */ + long temp = *((unsigned char *)pRamp + (indexChan << 8) + (indexEntry << 8) / entries); /* get data from ramp */ + short indexByte; + for (indexByte = 0; indexByte < bytesPerEntry; indexByte++) /* for all bytes */ + { + if (currentShift < 0) /* shift data correctly for current byte */ + *(pGammaBase++) = temp << -currentShift; + else + *(pGammaBase++) = temp >> currentShift; + currentShift -= 8; /* increment shift to align to next less sig. byte */ + } + } + } + + /* set gamma */ + gameRecRestore.csGTable = (Ptr) pTableGammaNew; /* setup restore record */ + csPtr = (Ptr) &gameRecRestore; + err = Control((**hGD).gdRefNum, cscSetGamma, (Ptr) &csPtr); /* restore gamma (note, display drivers may delay returning from this until VBL) */ + + if ((8 == (**(**hGD).gdPMap).pixelSize) && (noErr == err)) /* if successful and on an 8 bit device */ + { + hCTabDeviceColors = (**(**hGD).gdPMap).pmTable; /* do SetEntries to force CLUT update */ + setEntriesRec.csTable = (ColorSpec *) &(**hCTabDeviceColors).ctTable; + setEntriesRec.csStart = 0; + setEntriesRec.csCount = (**hCTabDeviceColors).ctSize; + csPtr = (Ptr) &setEntriesRec; + err = Control((**hGD).gdRefNum, cscSetEntries, (Ptr) &csPtr); /* SetEntries in CLUT */ + } + DisposeGammaTable ((Ptr) pTableGammaNew); /* dump table */ + if (noErr == err) + return true; + } + } + } + else /* set NULL gamma -> results in linear map */ + { + gameRecRestore.csGTable = (Ptr) NULL; /* setup restore record */ + csPtr = (Ptr) &gameRecRestore; + err = Control((**hGD).gdRefNum, cscSetGamma, (Ptr) &csPtr); /* restore gamma */ + + if ((8 == (**(**hGD).gdPMap).pixelSize) && (noErr == err)) /* if successful and on an 8 bit device */ + { + hCTabDeviceColors = (**(**hGD).gdPMap).pmTable; /* do SetEntries to force CLUT update */ + setEntriesRec.csTable = (ColorSpec *) &(**hCTabDeviceColors).ctTable; + setEntriesRec.csStart = 0; + setEntriesRec.csCount = (**hCTabDeviceColors).ctSize; + csPtr = (Ptr) &setEntriesRec; + err = Control((**hGD).gdRefNum, cscSetEntries, (Ptr) &csPtr); /* SetEntries in CLUT */ + } + if (noErr == err) + return true; + } + return false; /* memory allocation or device control failed if we get here */ +} + +/* end of ADC Gamma Ramp support code... */ + +static Ptr systemGammaPtr; + +void Mac_QuitGamma(_THIS) +{ + if (systemGammaPtr) + { + RestoreSystemGammas(systemGammaPtr); + DisposeSystemGammas(&systemGammaPtr); + } +} + +static unsigned char shiftedRamp[3 * 256]; + +int Mac_SetGammaRamp(_THIS, Uint16 *ramp) +{ + int i; + if (!systemGammaPtr) + systemGammaPtr = GetSystemGammas(); + for (i = 0; i < 3 * 256; i++) + { + shiftedRamp[i] = ramp[i] >> 8; + } + + if (SetDeviceGammaRampGD(GetMainDevice(), (Ptr) shiftedRamp)) + return 0; + else + return -1; +} + +int Mac_GetGammaRamp(_THIS, Uint16 *ramp) +{ + if (GetDeviceGammaRampGD(GetMainDevice(), (Ptr) shiftedRamp)) + { + int i; + for (i = 0; i < 3 * 256; i++) + { + ramp[i] = shiftedRamp[i] << 8; + } + return 0; + } + else + return -1; +} + +#endif /* SDL_MACCLASSIC_GAMMA_SUPPORT */ + + diff --git a/3rdparty/SDL/src/video/maccommon/SDL_macwm_c.h b/3rdparty/SDL/src/video/maccommon/SDL_macwm_c.h new file mode 100644 index 0000000..a0554d1 --- /dev/null +++ b/3rdparty/SDL/src/video/maccommon/SDL_macwm_c.h @@ -0,0 +1,41 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#include "../macrom/SDL_romvideo.h" + +/* Functions to be exported */ +extern void Mac_SetCaption(_THIS, const char *title, const char *icon); + +/* + * There's no Carbonized gamma support in Mac OS X, since PBStatusSync() and + * Control() aren't supported in OS X's Carbonlib. Use the Quartz driver + * instead. + */ +#define SDL_MACCLASSIC_GAMMA_SUPPORT ((defined(__APPLE__) && defined(__MACH__)) == 0) + +#if SDL_MACCLASSIC_GAMMA_SUPPORT +extern void Mac_QuitGamma(_THIS); +extern int Mac_SetGammaRamp(_THIS, Uint16 *ramp); +extern int Mac_GetGammaRamp(_THIS, Uint16 *ramp); +#endif + diff --git a/3rdparty/SDL/src/video/macdsp/SDL_dspvideo.c b/3rdparty/SDL/src/video/macdsp/SDL_dspvideo.c new file mode 100644 index 0000000..aa31127 --- /dev/null +++ b/3rdparty/SDL/src/video/macdsp/SDL_dspvideo.c @@ -0,0 +1,1422 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* + Written by Darrell Walisser <dwaliss1@purdue.edu> + + Implementation notes ---------------------------------------------------------------------- + + A bit on GWorlds in VRAM from technote 1182: + + There are two important things to note about GWorld's allocated in + VRAM. First, the base address retrieved through GetPixBaseAddr or + read directly from the PixMap structure can become invalid anytime + memory is allocated in VRAM. This can occur either by explicit + allocations, such as calls to NewGWorld, or by implicit ones, such as + those associated with the internal texture allocation of OpenGL. The + stored pixel images themselves will still be valid but may have been + moved in VRAM, thus rendering any stored base addresses invalid. + You should never store an image's base address for longer than is + necessary and especially never across calls to NewGWorld or + texture-creation routines. + + Secondly, an offscreen pixel image allocated in VRAM can be + purged at system task time by the display driver. This means any + time your application yields time such by calling WaitNextEvent or + SystemTask you can lose your VRAM GWorld contents. While this + happens infrequently, usually associated with display resolution or + pixel depth changes you must code for this eventuality. This purge + can occur whether or not the GWorld is locked or not. A return value + of false from LockPixels, a NULL return value from GetPixBaseAddr + or NULL in the baseAddr field of the PixMap mean that the pixel + image has been purged. To reallocate it you can either call + UpdateGWorld or Dispose your current GWorld through + DisposeGWorld and reallocate it via NewGWorld. Either way you must + then rebuild the pixel image. + +------------------------------------------------------------------------------------ + + Currently, I don't account for (1). In my testing, NewGWorld never invalidated + other existing GWorlds in VRAM. However, I do have protection for (2). + Namely, I am using GetOSEvent() instead of WaitNextEvent() so that there are no + context switches (the app hogs the CPU). Eventually a book-keeping system should + be coded to take care of (1) and (2). + +------------------------------------------------------------------------------------ + + System requirements (* denotes optional): + + 1. DrawSprocket 1.7.3 + 2. *MacOS 9 or later (but *not* Mac OS X) for hardware accelerated blit / fill + 3. *May also require certain graphics hardware for (2). I trust that all Apple OEM + hardware will work. Third party accelerators may work if they have QuickDraw + acceleration in the drivers and the drivers have been updated for OS 9. The current + Voodoo 3 drivers (1.0b12) do not work. + + Coding suggestions: + + 1. Use SDL_UpdateRects ! + + If no QuickDraw acceleration is present, double-buffered surfaces will use a back buffer + in System memory. I recommend you use SDL_UpdateRects with double-buffered surfaces + for best performance on these cards, since the overhead is nearly zero for VRAM back buffer. + + 2. Load most-resident surfaces first. + + If you fill up VRAM or AGP memory, there is no contingency for purging to make room for the next one. + Therefore, you should load the surfaces you plan to use the most frequently first. + Sooner or later, I will code LRU replacement to help this. + + TODO: + Some kind of posterized mode for resolutions < 640x480. + Window support / fullscreen toggle. + Figure out how much VRAM is available. Put in video->info->video_mem. + Track VRAM usage. + + BUGS: + I can't create a hardware surface the same size as the screen?! How to fix? + + + + COMPILE OPTIONS: + + DSP_TRY_CC_AND_AA - Define if you want to try HWA color-key and alpha blitters + HW color-key blitting gives substantial improvements, + but hw alpha is neck-and-neck with SDL's soft bitter. + + DSP_NO_SYNC_VBL - Define for HWA double-buffered surfaces: don't sync + pseudo-flip to monitor redraw. + + DSP_NO_SYNC_OPENGL - Define for OpenGL surfaces: don't sync buffer swap. Synching buffer + swap may result in reduced performance, but can eliminate some + tearing artifacts. + CHANGELOG: + 09/17/00 Lots of little tweaks. Build modelist in reverse order so largest contexts + list first. Compared various methods with ROM methods and fixed rez switch + crashing bug in GL Tron. (Woohoo!) +*/ + +#define DSP_TRY_CC_AND_AA + +/* #define DSP_NO_SYNC_VBL */ + +#define DSP_NO_SYNC_OPENGL + + +#if defined(__APPLE__) && defined(__MACH__) +#include <Carbon/Carbon.h> +#include <DrawSprocket/DrawSprocket.h> +#elif TARGET_API_MAC_CARBON && (UNIVERSAL_INTERFACES_VERSION > 0x0335) +#include <Carbon.h> +#include <DrawSprocket.h> +#else +#include <LowMem.h> +#include <Gestalt.h> +#include <Devices.h> +#include <DiskInit.h> +#include <QDOffscreen.h> +#include <DrawSprocket.h> +#endif + +#include "SDL_video.h" +#include "SDL_syswm.h" +#include "../SDL_sysvideo.h" +#include "../SDL_blit.h" +#include "../SDL_pixels_c.h" +#include "SDL_dspvideo.h" +#include "../maccommon/SDL_macgl_c.h" +#include "../maccommon/SDL_macwm_c.h" +#include "../maccommon/SDL_macmouse_c.h" +#include "../maccommon/SDL_macevents_c.h" + +/* Initialization/Query functions */ +static int DSp_VideoInit(_THIS, SDL_PixelFormat *vformat); +static SDL_Rect **DSp_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags); +static SDL_Surface *DSp_SetVideoMode(_THIS, SDL_Surface *current, int width, int height, int bpp, Uint32 flags); +static int DSp_SetColors(_THIS, int firstcolor, int ncolors, + SDL_Color *colors); +static int DSp_CreatePalette(_THIS); +static int DSp_DestroyPalette(_THIS); +static void DSp_VideoQuit(_THIS); + +static int DSp_GetMainDevice (_THIS, GDHandle *device); +static void DSp_IsHWAvailable (_THIS, SDL_PixelFormat *vformat); +static void DSp_DSpUpdate(_THIS, int numrects, SDL_Rect *sdl_rects); +static void DSp_DirectUpdate(_THIS, int numrects, SDL_Rect *sdl_rects); + +/* Hardware surface functions */ +static int DSp_SetHWAlpha(_THIS, SDL_Surface *surface, UInt8 alpha); +static int DSp_SetHWColorKey(_THIS, SDL_Surface *surface, Uint32 key); +static int DSp_NewHWSurface(_THIS, CGrafPtr *port, int depth, int width, int height); +static int DSp_AllocHWSurface(_THIS, SDL_Surface *surface); +static int DSp_LockHWSurface(_THIS, SDL_Surface *surface); +static void DSp_UnlockHWSurface(_THIS, SDL_Surface *surface); +static void DSp_FreeHWSurface(_THIS, SDL_Surface *surface); +static int DSp_FlipHWSurface(_THIS, SDL_Surface *surface); +static int DSp_CheckHWBlit(_THIS, SDL_Surface *src, SDL_Surface *dest); +static int DSp_HWAccelBlit(SDL_Surface *src, SDL_Rect *srcrect, + SDL_Surface *dst, SDL_Rect *dstrect); +static int DSp_FillHWRect(_THIS, SDL_Surface *dst, SDL_Rect *rect, Uint32 color); + +#if SDL_VIDEO_OPENGL + static void DSp_GL_SwapBuffers (_THIS); +#endif + +#if ! TARGET_API_MAC_CARBON + + #define GetPortPixRowBytes(x) ( (*(x->portPixMap))->rowBytes ) + #define GetGDevPixMap(x) ((**(x)).gdPMap) + #define GetPortPixMap(x) ((*(x)).portPixMap) + + #define GetPixDepth(y) ((**(y)).pixelSize) + //#define GetPixRowBytes(y) ((**(y)).rowBytes) + //#define GetPixBaseAddr(y) ((**(y)).baseAddr) + #define GetPixCTab(y) ((**(y)).pmTable) + #define GetPortBitMapForCopyBits(x) (&(((GrafPtr)(x))->portBits)) + +#else + #define GetPortPixRowBytes(x) (GetPixRowBytes(GetPortPixMap(x)) ) + #define GetGDevPixMap(x) ((**(x)).gdPMap) + +#endif + +typedef struct private_hwdata { + + GWorldPtr offscreen; // offscreen gworld in VRAM or AGP + + #ifdef DSP_TRY_CC_AND_AA + GWorldPtr mask; // transparent mask + RGBColor alpha; // alpha color + RGBColor trans; // transparent color + #endif + +} private_hwdata; + +typedef private_hwdata private_swdata ; /* have same fields */ + +/* Macintosh toolbox driver bootstrap functions */ + +static int DSp_Available(void) +{ + /* Check for DrawSprocket */ +#if ! TARGET_API_MAC_OSX + /* This check is only meaningful if you weak-link DrawSprocketLib */ + return ((Ptr)DSpStartup != (Ptr)kUnresolvedCFragSymbolAddress); +#else + return 1; // DrawSprocket.framework doesn't have it all, but it's there +#endif +} + +static void DSp_DeleteDevice(SDL_VideoDevice *device) +{ + /* -dw- taking no chances with null pointers */ + if (device) { + + if (device->hidden) { + + if (device->hidden->dspinfo) + SDL_free(device->hidden->dspinfo); + + SDL_free(device->hidden); + } + SDL_free(device); + } +} + +static SDL_VideoDevice *DSp_CreateDevice(int devindex) +{ + SDL_VideoDevice *device; + + /* Initialize all variables that we clean on shutdown */ + device = (SDL_VideoDevice *)SDL_malloc(sizeof(SDL_VideoDevice)); + if ( device ) { + SDL_memset(device, 0, sizeof (*device)); + device->hidden = (struct SDL_PrivateVideoData *) + SDL_malloc((sizeof *device->hidden)); + if (device->hidden) + SDL_memset(device->hidden, 0, sizeof ( *(device->hidden) ) ); + } + if ( (device == NULL) || (device->hidden == NULL) ) { + SDL_OutOfMemory(); + + if ( device ) { + + if (device->hidden) + SDL_free(device->hidden); + + SDL_free(device); + } + + return(NULL); + } + + /* Allocate DrawSprocket information */ + device->hidden->dspinfo = (struct DSpInfo *)SDL_malloc( + (sizeof *device->hidden->dspinfo)); + if ( device->hidden->dspinfo == NULL ) { + SDL_OutOfMemory(); + SDL_free(device->hidden); + SDL_free(device); + return(0); + } + SDL_memset(device->hidden->dspinfo, 0, (sizeof *device->hidden->dspinfo)); + + /* Set the function pointers */ + device->VideoInit = DSp_VideoInit; + device->ListModes = DSp_ListModes; + device->SetVideoMode = DSp_SetVideoMode; + device->SetColors = DSp_SetColors; + device->UpdateRects = NULL; + device->VideoQuit = DSp_VideoQuit; + device->AllocHWSurface = DSp_AllocHWSurface; + device->CheckHWBlit = NULL; + device->FillHWRect = NULL; + device->SetHWColorKey = NULL; + device->SetHWAlpha = NULL; + device->LockHWSurface = DSp_LockHWSurface; + device->UnlockHWSurface = DSp_UnlockHWSurface; + device->FlipHWSurface = DSp_FlipHWSurface; + device->FreeHWSurface = DSp_FreeHWSurface; +#if SDL_MACCLASSIC_GAMMA_SUPPORT + device->SetGammaRamp = Mac_SetGammaRamp; + device->GetGammaRamp = Mac_GetGammaRamp; +#endif +#if SDL_VIDEO_OPENGL + device->GL_MakeCurrent = Mac_GL_MakeCurrent; + device->GL_SwapBuffers = DSp_GL_SwapBuffers; + device->GL_LoadLibrary = Mac_GL_LoadLibrary; + device->GL_GetProcAddress = Mac_GL_GetProcAddress; +#endif + device->SetCaption = NULL; + device->SetIcon = NULL; + device->IconifyWindow = NULL; + device->GrabInput = NULL; + device->GetWMInfo = NULL; + device->FreeWMCursor = Mac_FreeWMCursor; + device->CreateWMCursor = Mac_CreateWMCursor; + device->ShowWMCursor = Mac_ShowWMCursor; + device->WarpWMCursor = Mac_WarpWMCursor; + device->InitOSKeymap = Mac_InitOSKeymap; + device->PumpEvents = Mac_PumpEvents; + + device->GrabInput = NULL; + device->CheckMouseMode = NULL; + + device->free = DSp_DeleteDevice; + + return device; +} + +VideoBootStrap DSp_bootstrap = { + "DSp", "MacOS DrawSprocket", + DSp_Available, DSp_CreateDevice +}; + +/* Use DSp/Display Manager to build mode list for given screen */ +static SDL_Rect** DSp_BuildModeList (const GDHandle gDevice, int *displayWidth, int *displayHeight) +{ + DSpContextAttributes attributes; + DSpContextReference context; + DisplayIDType displayID; + SDL_Rect temp_list [16]; + SDL_Rect **mode_list; + int width, height, i, j; + + #if TARGET_API_MAC_OSX + + displayID = 0; + + #else + /* Ask Display Manager for integer id of screen device */ + if ( DMGetDisplayIDByGDevice (gDevice, &displayID, SDL_TRUE) != noErr ) { + return NULL; + } + #endif + /* Get the first possible DSp context on this device */ + if ( DSpGetFirstContext (displayID, &context) != noErr ) { + return NULL; + } + + if ( DSpContext_GetAttributes (context, &attributes) != noErr ) + return NULL; + + *displayWidth = attributes.displayWidth; + *displayHeight = attributes.displayHeight; + + for ( i = 0; i < SDL_arraysize(temp_list); i++ ) { + width = attributes.displayWidth; + height = attributes.displayHeight; + + temp_list [i].x = 0 | attributes.displayBestDepth; + temp_list [i].y = 0; + temp_list [i].w = width; + temp_list [i].h = height; + + /* DSp will report many different contexts with the same width and height. */ + /* They will differ in bit depth and refresh rate. */ + /* We will ignore them until we reach one with a different width/height */ + /* When there are no more contexts to look at, we will quit building the list*/ + while ( width == attributes.displayWidth && height == attributes.displayHeight ) { + + OSStatus err = DSpGetNextContext (context, &context); + if (err != noErr) + if (err == kDSpContextNotFoundErr) + goto done; + else + return NULL; + + if ( DSpContext_GetAttributes (context, &attributes) != noErr ) + return NULL; + + temp_list [i].x |= attributes.displayBestDepth; + } + } +done: + i++; /* i was not incremented before kicking out of the loop */ + + mode_list = (SDL_Rect**) SDL_malloc (sizeof (SDL_Rect*) * (i+1)); + if (mode_list) { + + /* -dw- new stuff: build in reverse order so largest sizes list first */ + for (j = i-1; j >= 0; j--) { + mode_list [j] = (SDL_Rect*) SDL_malloc (sizeof (SDL_Rect)); + if (mode_list [j]) + SDL_memcpy (mode_list [j], &(temp_list [j]), sizeof (SDL_Rect)); + else { + SDL_OutOfMemory (); + return NULL; + } + } + mode_list [i] = NULL; /* append null to the end */ + } + else { + SDL_OutOfMemory (); + return NULL; + } + + return mode_list; +} + +static void DSp_IsHWAvailable (_THIS, SDL_PixelFormat *vformat) +{ + /* + VRAM GWorlds are only available on OS 9 or later. + Even with OS 9, some display drivers won't support it, + so we create a test GWorld and check for errors. + */ + + long versionSystem; + + dsp_vram_available = SDL_FALSE; + dsp_agp_available = SDL_FALSE; + + Gestalt ('sysv', &versionSystem); + if (0x00000860 < (versionSystem & 0x0000FFFF)) { + + GWorldPtr offscreen; + OSStatus err; + Rect bounds; + + SetRect (&bounds, 0, 0, 320, 240); + +#if useDistantHdwrMem && useLocalHdwrMem + err = NewGWorld (&offscreen, vformat->BitsPerPixel, &bounds, NULL, SDL_Display, useDistantHdwrMem | noNewDevice); + if (err == noErr) { + dsp_vram_available = SDL_TRUE; + DisposeGWorld (offscreen); + } + + err = NewGWorld (&offscreen, vformat->BitsPerPixel, &bounds, NULL, SDL_Display, useLocalHdwrMem | noNewDevice); + if (err == noErr) { + DisposeGWorld (offscreen); + dsp_agp_available = SDL_TRUE; + } +#endif + } +} + +static int DSp_GetMainDevice (_THIS, GDHandle *device) +{ + +#if TARGET_API_MAC_OSX + /* DSpUserSelectContext not available on OS X */ + *device = GetMainDevice(); + return 0; +#else + + DSpContextAttributes attrib; + DSpContextReference context; + DisplayIDType display_id; + GDHandle main_device; + GDHandle device_list; + + device_list = GetDeviceList (); + main_device = GetMainDevice (); + + /* Quick check to avoid slower method when only one display exists */ + if ( (**device_list).gdNextGD == NULL ) { + *device = main_device; + return 0; + } + + SDL_memset (&attrib, 0, sizeof (DSpContextAttributes)); + + /* These attributes are hopefully supported on all devices...*/ + attrib.displayWidth = 640; + attrib.displayHeight = 480; + attrib.displayBestDepth = 8; + attrib.backBufferBestDepth = 8; + attrib.displayDepthMask = kDSpDepthMask_All; + attrib.backBufferDepthMask = kDSpDepthMask_All; + attrib.colorNeeds = kDSpColorNeeds_Require; + attrib.pageCount = 1; + + if (noErr != DMGetDisplayIDByGDevice (main_device, &display_id, SDL_FALSE)) { + SDL_SetError ("Display Manager couldn't associate GDevice with a Display ID"); + return (-1); + } + + /* Put up dialog on main display to select which display to use */ + if (noErr != DSpUserSelectContext (&attrib, display_id, NULL, &context)) { + SDL_SetError ("DrawSprocket couldn't create a context"); + return (-1); + } + + if (noErr != DSpContext_GetDisplayID (context, &display_id)) { + SDL_SetError ("DrawSprocket couldn't get display ID"); + return (-1); + } + + if (noErr != DMGetGDeviceByDisplayID (display_id, &main_device, SDL_FALSE)) { + SDL_SetError ("Display Manager couldn't associate Display ID with GDevice"); + return (-1); + } + + *device = main_device; + return (0); +#endif +} + +static int DSp_VideoInit(_THIS, SDL_PixelFormat *vformat) +{ + NumVersion dsp_version = { 0x01, 0x00, 0x00, 0x00 }; + +#if UNIVERSAL_INTERFACES_VERSION > 0x0320 + dsp_version = DSpGetVersion (); +#endif + + if ( (dsp_version.majorRev == 1 && dsp_version.minorAndBugRev < 0x73) || + (dsp_version.majorRev < 1) ) { + + /* StandardAlert (kAlertStopAlert, "\pError!", + "\pI need DrawSprocket 1.7.3 or later!\n" + "You can find a newer version at http://www.apple.com/swupdates.", + NULL, NULL); + */ + SDL_SetError ("DrawSprocket version is too old. Need 1.7.3 or later."); + return (-1); + } + + if ( DSpStartup () != noErr ) { + SDL_SetError ("DrawSprocket couldn't startup"); + return(-1); + } + + /* Start DSpintosh events */ + Mac_InitEvents(this); + + /* Get a handle to the main monitor, or choose one on multiple monitor setups */ + if ( DSp_GetMainDevice(this, &SDL_Display) < 0) + return (-1); + + /* Determine pixel format */ + vformat->BitsPerPixel = GetPixDepth ( (**SDL_Display).gdPMap ); + dsp_old_depth = vformat->BitsPerPixel; + + switch (vformat->BitsPerPixel) { + case 16: + vformat->Rmask = 0x00007c00; + vformat->Gmask = 0x000003e0; + vformat->Bmask = 0x0000001f; + break; + default: + break; + } + + if ( DSp_CreatePalette (this) < 0 ) { + SDL_SetError ("Could not create palette"); + return (-1); + } + + /* Get a list of available fullscreen modes */ + SDL_modelist = DSp_BuildModeList (SDL_Display, + &this->info.current_w, &this->info.current_h); + if (SDL_modelist == NULL) { + SDL_SetError ("DrawSprocket could not build a mode list"); + return (-1); + } + + /* Check for VRAM and AGP GWorlds for HW Blitting */ + DSp_IsHWAvailable (this, vformat); + + this->info.wm_available = 0; + + if (dsp_vram_available || dsp_agp_available) { + + this->info.hw_available = SDL_TRUE; + + this->CheckHWBlit = DSp_CheckHWBlit; + this->info.blit_hw = SDL_TRUE; + + this->FillHWRect = DSp_FillHWRect; + this->info.blit_fill = SDL_TRUE; + + #ifdef DSP_TRY_CC_AND_AA + this->SetHWColorKey = DSp_SetHWColorKey; + this->info.blit_hw_CC = SDL_TRUE; + + this->SetHWAlpha = DSp_SetHWAlpha; + this->info.blit_hw_A = SDL_TRUE; + #endif + + } + + return(0); +} + +static SDL_Rect **DSp_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags) +{ + static SDL_Rect *dsp_modes[16]; + int i = 0, j = 0; + + if ( format->BitsPerPixel == 0 ) + return ( (SDL_Rect**) NULL ); + + while (SDL_modelist[i] != NULL) { + + if (SDL_modelist[i]->x & format->BitsPerPixel) { + dsp_modes[j] = SDL_modelist[i]; + j++; + } + i++; + } + + dsp_modes[j] = NULL; + + return dsp_modes; +} + +/* Various screen update functions available */ +static void DSp_DirectUpdate(_THIS, int numrects, SDL_Rect *rects); + +#if ! TARGET_API_MAC_OSX + +static volatile unsigned int retrace_count = 0; /* -dw- need volatile because it updates asychronously */ + +Boolean DSp_VBLProc ( DSpContextReference context, void *ref_con ) +{ + retrace_count++; + + return 1; /* Darrell, is this right? */ +} + +static void DSp_SetHWError (OSStatus err, int is_agp) +{ + char message[1024]; + const char *fmt, *mem; + + if ( is_agp ) { + mem = "AGP Memory"; + } else { + mem = "VRAM"; + } + switch(err) { + case memFullErr: + fmt = "Hardware surface possible but not enough %s available"; + break; + case cDepthErr: + fmt = "Hardware surface possible but invalid color depth"; + break; + default: + fmt = "Hardware surface could not be allocated in %s - unknown error"; + break; + } + SDL_snprintf(message, SDL_arraysize(message), fmt, mem); + SDL_SetError(message); +} +#endif // TARGET_API_MAC_OSX + +/* put up a dialog to verify display change */ +static int DSp_ConfirmSwitch () { + + /* resource id's for dialog */ + const int rDialog = 1002; + const int bCancel = 1; + const int bOK = 2; + + DialogPtr dialog; + OSStatus err; + SInt32 response; + DialogItemIndex item = 0; + GrafPtr savePort; + + GetPort (&savePort); + + dialog = GetNewDialog (rDialog, NULL, (WindowPtr) -1); + if (dialog == NULL) + return (0); + +#if TARGET_API_MAC_CARBON + SetPort (GetDialogPort(dialog)); +#else + SetPort ((WindowPtr) dialog); +#endif + + SetDialogDefaultItem (dialog, bCancel); + SetDialogCancelItem (dialog, bCancel); + + SetEventMask (everyEvent); + FlushEvents (everyEvent, 0); + + /* On MacOS 8.5 or later, we can make the dialog go away after 15 seconds */ + /* This is good since it's possible user can't even see the dialog! */ + /* Requires linking to DialogsLib */ + err = Gestalt(gestaltSystemVersion,&response); + if (err == noErr && response >= 0x00000850) { + SetDialogTimeout(dialog, bCancel, 15); + } + + do { + + ModalDialog ( NULL, &item ); + + } while ( item != bCancel && item != bOK && err != noErr); + + + DisposeDialog (dialog); + SetPort (savePort); + + SetEventMask(everyEvent - autoKeyMask); + FlushEvents(everyEvent, 0); + + return (item - 1); +} + +static void DSp_UnsetVideoMode(_THIS, SDL_Surface *current) +{ + + + if ( current->flags & SDL_OPENGL ) { + Mac_GL_Quit (this); + } + + if (dsp_context != NULL) { + + GWorldPtr front; + DSpContext_GetFrontBuffer (dsp_context, &front); + + if (front != dsp_back_buffer) + DisposeGWorld (dsp_back_buffer); + + if (current->hwdata) + SDL_free(current->hwdata); + + DSpContext_SetState (dsp_context, kDSpContextState_Inactive ); + DSpContext_Release (dsp_context); + + dsp_context = NULL; + } + + if (SDL_Window != NULL) { + DisposeWindow (SDL_Window); + SDL_Window = NULL; + } + + current->pixels = NULL; + current->flags = 0; +} + +static SDL_Surface *DSp_SetVideoMode(_THIS, + SDL_Surface *current, int width, int height, int bpp, Uint32 flags) +{ + +#if !TARGET_API_MAC_OSX + DisplayIDType display_id; + Fixed freq; +#endif + DSpContextAttributes attrib; + OSStatus err; + UInt32 rmask = 0, gmask = 0, bmask = 0; + + int page_count; + int double_buf; + int hw_surface; + int use_dsp_back_buffer; + + DSp_UnsetVideoMode (this, current); + + if (bpp != dsp_old_depth) + DSp_DestroyPalette (this); + + double_buf = (flags & SDL_DOUBLEBUF) != 0; + hw_surface = (flags & SDL_HWSURFACE) != 0; + use_dsp_back_buffer = !dsp_vram_available || !hw_surface ; + + current->flags |= SDL_FULLSCREEN; + +rebuild: + + if ( double_buf && use_dsp_back_buffer ) { + page_count = 2; + } else { + page_count = 1; + } + + SDL_memset (&attrib, 0, sizeof (DSpContextAttributes)); + attrib.displayWidth = width; + attrib.displayHeight = height; + attrib.displayBestDepth = bpp; + attrib.backBufferBestDepth = bpp; + attrib.displayDepthMask = kDSpDepthMask_All; + attrib.backBufferDepthMask = kDSpDepthMask_All; + attrib.colorNeeds = kDSpColorNeeds_Require; + attrib.colorTable = 0; + attrib.pageCount = page_count; + #if TARGET_API_MAC_OSX || UNIVERSAL_INTERFACES_VERSION == 0x0320 + + if ( DSpFindBestContext (&attrib, &dsp_context) != noErr ) { + SDL_SetError ("DrawSprocket couldn't find a context"); + return NULL; + } + + #else + if ( noErr != DMGetDisplayIDByGDevice (SDL_Display, &display_id, SDL_FALSE) ) { + SDL_SetError ("Display Manager couldn't associate GDevice with display_id"); + return NULL; + } + if ( DSpFindBestContextOnDisplayID(&attrib, &dsp_context, display_id) != noErr ) { + SDL_SetError ("DrawSprocket couldn't find a suitable context on given display"); + return NULL; + } + + #endif + if ( DSpContext_Reserve (dsp_context, &attrib) != noErr ) { + SDL_SetError ("DrawSprocket couldn't get the needed resources to build the display"); + return NULL; + } + + if ( (err = DSpContext_SetState (dsp_context, kDSpContextState_Active)) != noErr ) { + + if (err == kDSpConfirmSwitchWarning) { + + if ( ! DSp_ConfirmSwitch () ) { + + DSpContext_Release (dsp_context); + dsp_context = NULL; + SDL_SetError ("User cancelled display switch"); + return NULL; + } + else + /* Have to reactivate context. Why? */ + DSpContext_SetState (dsp_context, kDSpContextState_Active); + + } + else { + SDL_SetError ("DrawSprocket couldn't activate the context"); + return NULL; + } + } + + + if (bpp != dsp_old_depth) { + + DSp_CreatePalette (this); + + /* update format if display depth changed */ + if (bpp == 16) { + + rmask = 0x00007c00; + gmask = 0x000003e0; + bmask = 0x0000001f; + } + if ( ! SDL_ReallocFormat (current, bpp, rmask, gmask, bmask, 0 ) ) { + + SDL_SetError ("Could not reallocate video format."); + return(NULL); + } + } + + if (!double_buf) { + + /* single-buffer context */ + DSpContext_GetFrontBuffer (dsp_context, &dsp_back_buffer); + + current->hwdata = (private_hwdata*) SDL_malloc (sizeof (private_hwdata)); + if (current ->hwdata == NULL) { + SDL_OutOfMemory (); + return NULL; + } + current->hwdata->offscreen = dsp_back_buffer; + current->flags |= SDL_HWSURFACE; + this->UpdateRects = DSp_DirectUpdate; + } + else if ( use_dsp_back_buffer ) { + + DSpContext_GetBackBuffer (dsp_context, kDSpBufferKind_Normal, &dsp_back_buffer); + + current->flags |= SDL_DOUBLEBUF | SDL_SWSURFACE; /* only front buffer is in VRAM */ + this->UpdateRects = DSp_DSpUpdate; + } + else if ( DSp_NewHWSurface(this, &dsp_back_buffer, bpp, width-1, height-1) == 0 ) { + + current->hwdata = (private_hwdata*) SDL_malloc (sizeof (private_hwdata)); + if (current ->hwdata == NULL) { + SDL_OutOfMemory (); + return NULL; + } + + SDL_memset (current->hwdata, 0, sizeof (private_hwdata)); + current->hwdata->offscreen = dsp_back_buffer; + current->flags |= SDL_DOUBLEBUF | SDL_HWSURFACE; + this->UpdateRects = DSp_DirectUpdate; /* hardware doesn't do update rects, must be page-flipped */ + } + else { + + DSpContext_Release (dsp_context); + use_dsp_back_buffer = SDL_TRUE; + goto rebuild; + } + + current->pitch = GetPortPixRowBytes(dsp_back_buffer) & 0x3FFF; + current->pixels = GetPixBaseAddr(GetPortPixMap(dsp_back_buffer)); + + current->w = width; + current->h = height; + + #if ! TARGET_API_MAC_OSX + + if (use_dsp_back_buffer) { + + DSpContext_GetMonitorFrequency (dsp_context, &freq); + DSpContext_SetMaxFrameRate (dsp_context, freq >> 16); + } + + + if ( (current->flags & SDL_HWSURFACE) || (current->flags & SDL_OPENGL) ) + DSpContext_SetVBLProc (dsp_context, DSp_VBLProc, NULL); + #endif + + if (bpp == 8) + current->flags |= SDL_HWPALETTE; + + if (flags & SDL_OPENGL) { + + Rect rect; + RGBColor rgb = { 0.0, 0.0, 0.0 }; + GrafPtr save_port; + + SetRect (&rect, 0, 0, width, height); + SDL_Window = NewCWindow(nil, &( (**SDL_Display).gdRect), "\p", SDL_TRUE, plainDBox, (WindowPtr)-1, SDL_FALSE, 0); + + if (SDL_Window == NULL) { + + SDL_SetError ("DSp_SetVideoMode : OpenGL window could not be created."); + return NULL; + } + + /* Set window color to black to avoid white flash*/ + GetPort (&save_port); +#if TARGET_API_MAC_CARBON + SetPort (GetWindowPort(SDL_Window)); +#else + SetPort (SDL_Window); +#endif + RGBForeColor (&rgb); + PaintRect (&rect); + SetPort (save_port); + + SetPortWindowPort (SDL_Window); + SelectWindow (SDL_Window); + + if ( Mac_GL_Init (this) < 0 ) { + + SDL_SetError ("DSp_SetVideoMode : could not create OpenGL context."); + return NULL; + } + + current->flags |= SDL_OPENGL; + } + + return current; +} + +#ifdef DSP_TRY_CC_AND_AA + +static int DSp_MakeHWMask (_THIS, SDL_Surface *surface) +{ + GDHandle save_device; + CGrafPtr save_port; + GWorldPtr temp; + RGBColor black = { 0, 0, 0 }; + RGBColor white = { 0xFFFF, 0xFFFF, 0xFFFF }; + Rect rect; + + Uint32 depth = GetPixDepth ( GetGDevPixMap (SDL_Display) ); + + SetRect (&rect, 0, 0, surface->w, surface->h); + + if ( noErr != NewGWorld (&(surface->hwdata->mask), depth, &rect, 0, SDL_Display, 0 ) < 0 ) { + + SDL_OutOfMemory (); + return (-1); + } + + if ( noErr != NewGWorld (&temp, depth, &rect, 0 , SDL_Display, 0 ) ) { + + SDL_OutOfMemory (); + return (-1); + } + + + GetGWorld (&save_port, &save_device); + SetGWorld (surface->hwdata->mask, SDL_Display); + + RGBForeColor (&white); + PaintRect (&rect); + + RGBBackColor (&(surface->hwdata->trans)); + + CopyBits ( GetPortBitMapForCopyBits(surface->hwdata->offscreen), + GetPortBitMapForCopyBits(surface->hwdata->mask), + &rect, &rect, transparent, NULL ); + + SetGWorld (surface->hwdata->mask, SDL_Display); + SetGWorld (save_port, save_device); + return (0); +} + +static int DSp_SetHWAlpha(_THIS, SDL_Surface *surface, UInt8 alpha) +{ + surface->hwdata->alpha.red = (alpha / 255.0) * 65535; + surface->hwdata->alpha.blue = (alpha / 255.0) * 65535; + surface->hwdata->alpha.green = (alpha / 255.0) * 65535; + + surface->flags |= SDL_SRCALPHA; + + if (surface->flags & SDL_SRCCOLORKEY) { + return(DSp_MakeHWMask (this, surface)); + } + return(0); +} + +static int DSp_SetHWColorKey(_THIS, SDL_Surface *surface, Uint32 key) +{ + CGrafPtr save_port; + GDHandle save_device; + + GetGWorld (&save_port, &save_device); + SetGWorld (surface->hwdata->offscreen, NULL); + + Index2Color (key, &(surface->hwdata->trans)); + surface->flags |= SDL_SRCCOLORKEY; + + SetGWorld (save_port, save_device); + + if ( surface->flags & SDL_SRCALPHA ) { + return(DSp_MakeHWMask (this, surface)); + } + return(0); +} + +#endif /* DSP_TRY_CC_AND_AA */ + +static int DSp_NewHWSurface(_THIS, CGrafPtr *port, int depth, int width, int height) { + + OSStatus err; + Rect bounds; + + SetRect (&bounds, 0, 0, width, height); + + #if useDistantHdwrMem && useLocalHdwrMem + if (dsp_vram_available) { + /* try VRAM */ + err = NewGWorld (port, depth, &bounds, 0 , SDL_Display, useDistantHdwrMem | noNewDevice ); + if (err != noErr) + DSp_SetHWError (err, SDL_FALSE); + else + return (0); + } + + if (dsp_agp_available) { + /* try AGP */ + err = NewGWorld (port, depth, &bounds, 0 , SDL_Display, useLocalHdwrMem | noNewDevice ); + + if (err != noErr) + DSp_SetHWError (err, SDL_TRUE); + else + return (0); + } +#endif + + return (-1); +} + +static int DSp_AllocHWSurface(_THIS, SDL_Surface *surface) +{ + GWorldPtr temp; + + if ( DSp_NewHWSurface (this, &temp, surface->format->BitsPerPixel, surface->w, surface->h) < 0 ) + return (-1); + + surface->hwdata = (private_hwdata*) SDL_malloc (sizeof (private_hwdata)); + if (surface->hwdata == NULL) { + SDL_OutOfMemory (); + return -1; + } + + SDL_memset (surface->hwdata, 0, sizeof(private_hwdata)); + surface->hwdata->offscreen = temp; + surface->pitch = GetPixRowBytes (GetPortPixMap (temp)) & 0x3FFF; + surface->pixels = GetPixBaseAddr (GetPortPixMap (temp)); + surface->flags |= SDL_HWSURFACE; +#ifdef DSP_TRY_CC_AND_AA + surface->flags |= SDL_HWACCEL; +#endif + return 0; +} + +static void DSp_FreeHWSurface(_THIS, SDL_Surface *surface) +{ + if (surface->hwdata->offscreen != NULL) + DisposeGWorld (surface->hwdata->offscreen); + SDL_free(surface->hwdata); + + surface->pixels = NULL; +} + +static int DSp_CheckHWBlit(_THIS, SDL_Surface *src, SDL_Surface *dest) +{ + int accelerated; + + /* Set initial acceleration on */ + src->flags |= SDL_HWACCEL; + + /* Set the surface attributes */ + if ( (src->flags & SDL_SRCALPHA) == SDL_SRCALPHA ) { + if ( ! this->info.blit_hw_A ) { + src->flags &= ~SDL_HWACCEL; + } + } + if ( (src->flags & SDL_SRCCOLORKEY) == SDL_SRCCOLORKEY ) { + if ( ! this->info.blit_hw_CC ) { + src->flags &= ~SDL_HWACCEL; + } + } + + /* Check to see if final surface blit is accelerated */ + accelerated = !!(src->flags & SDL_HWACCEL); + if ( accelerated ) { + src->map->hw_blit = DSp_HWAccelBlit; + } + return(accelerated); +} + +static int DSp_HWAccelBlit(SDL_Surface *src, SDL_Rect *srcrect, + SDL_Surface *dst, SDL_Rect *dstrect) +{ + CGrafPtr save_port; + GDHandle save_device; + Rect src_rect, dst_rect; + RGBColor black = { 0, 0, 0 }; + RGBColor white = { 0xFFFF, 0xFFFF, 0xFFFF }; + +#ifdef DSP_TRY_CC_AND_AA + UInt32 mode; +#endif + + SetRect (&src_rect, srcrect->x, srcrect->y, srcrect->x + srcrect->w, srcrect->y + srcrect->h); + SetRect (&dst_rect, dstrect->x, dstrect->y, dstrect->x + dstrect->w, dstrect->y + dstrect->h); + + GetGWorld (&save_port, &save_device); + SetGWorld (dst->hwdata->offscreen, NULL); + + RGBForeColor (&black); + RGBBackColor (&white); + +#ifdef DSP_TRY_CC_AND_AA + + if ( (src->flags & SDL_SRCCOLORKEY) && + (src->flags & SDL_SRCALPHA) ) { + + OpColor (&(src->hwdata->alpha)); + + CopyDeepMask ( GetPortBitMapForCopyBits(src->hwdata->offscreen), + GetPortBitMapForCopyBits(src->hwdata->mask), + GetPortBitMapForCopyBits(dst->hwdata->offscreen), + &src_rect, &src_rect, &dst_rect, + blend, + NULL ); + } + else { + + if ( src->flags & SDL_SRCCOLORKEY) { + RGBBackColor (&(src->hwdata->trans) ); + mode = transparent; + } + else if (src->flags & SDL_SRCALPHA) { + + OpColor (&(src->hwdata->alpha)); + mode = blend; + } + else { + + mode = srcCopy; + } + + CopyBits ( GetPortBitMapForCopyBits(src->hwdata->offscreen), + GetPortBitMapForCopyBits(dst->hwdata->offscreen), + &src_rect, &dst_rect, mode, NULL ); + } +#else + + CopyBits ( &(((GrafPtr)(src->hwdata->offscreen))->portBits), + &(((GrafPtr)(dst->hwdata->offscreen))->portBits), + &src_rect, &dst_rect, srcCopy, NULL ); + +#endif /* DSP_TRY_CC_AND_AA */ + + SetGWorld (save_port, save_device); + + return(0); +} + +static int DSp_FillHWRect(_THIS, SDL_Surface *dst, SDL_Rect *rect, Uint32 color) +{ + CGrafPtr save_port; + GDHandle save_device; + Rect fill_rect; + RGBColor rgb; + + SetRect (&fill_rect, rect->x, rect->y, rect->x + rect->w, rect->y + rect->h); + + GetGWorld (&save_port, &save_device); + SetGWorld (dst->hwdata->offscreen, NULL); + + Index2Color (color, &rgb); + + RGBForeColor (&rgb); + PaintRect (&fill_rect); + + SetGWorld (save_port, save_device); + + return(0); +} + +static int DSp_FlipHWSurface(_THIS, SDL_Surface *surface) +{ + if ( (surface->flags & SDL_HWSURFACE) ) { + CGrafPtr dsp_front_buffer, save_port; + Rect rect; + + #if ! TARGET_API_MAC_OSX + unsigned int old_count; + #endif + + /* pseudo page flipping for VRAM back buffer*/ + DSpContext_GetFrontBuffer (dsp_context, &dsp_front_buffer); + SetRect (&rect, 0, 0, surface->w-1, surface->h-1); + + GetPort ((GrafPtr *)&save_port); + SetPort ((GrafPtr)dsp_front_buffer); + + /* wait for retrace */ + /* I have tried doing the swap in interrupt routine (VBL Proc) to do */ + /* it asynchronously, but apparently CopyBits isn't interrupt safe */ + + #if ! TARGET_API_MAC_OSX + #ifndef DSP_NO_SYNC_VBL + old_count = retrace_count; + while (old_count == retrace_count) + ; + #endif + #endif + + CopyBits ( GetPortBitMapForCopyBits(dsp_back_buffer), + GetPortBitMapForCopyBits(dsp_front_buffer), + &rect, &rect, srcCopy, NULL ); + + SetPort ((GrafPtr)save_port); + + } else { + /* not really page flipping at all: DSp just blits the dirty rectangles from DSp_UpdateRects */ + Boolean busy_flag; + DSpContext_SwapBuffers (dsp_context, NULL, &busy_flag); /* this waits for VBL */ + DSpContext_GetBackBuffer (dsp_context, kDSpBufferKind_Normal, &dsp_back_buffer); + surface->pixels = GetPixBaseAddr( GetPortPixMap(dsp_back_buffer) ); + } + return(0); +} + +static int DSp_LockHWSurface(_THIS, SDL_Surface *surface) +{ + if ( LockPixels (GetGWorldPixMap (surface->hwdata->offscreen)) ) + return 0; + else + return -1; +} + +static void DSp_UnlockHWSurface(_THIS, SDL_Surface *surface) +{ + UnlockPixels (GetGWorldPixMap (surface->hwdata->offscreen)); +} + +static void DSp_DirectUpdate(_THIS, int numrects, SDL_Rect *sdl_rects) +{ + return; +} + +static void DSp_DSpUpdate(_THIS, int numrects, SDL_Rect *sdl_rects) +{ +#if ! TARGET_API_MAC_OSX /* Unsupported DSp in here */ + int i; + Rect rect; + + for (i = 0; i < numrects; i++) { + + rect.top = sdl_rects[i].y; + rect.left = sdl_rects[i].x; + rect.bottom = sdl_rects[i].h + sdl_rects[i].y; + rect.right = sdl_rects[i].w + sdl_rects[i].x; + + DSpContext_InvalBackBufferRect (dsp_context, &rect); + } +#endif +} + +static int DSp_CreatePalette(_THIS) { + + + /* Create our palette */ + SDL_CTab = (CTabHandle)NewHandle(sizeof(ColorSpec)*256 + 8); + if ( SDL_CTab == nil ) { + SDL_OutOfMemory(); + return(-1); + } + (**SDL_CTab).ctSeed = GetCTSeed(); + (**SDL_CTab).ctFlags = 0; + (**SDL_CTab).ctSize = 255; + CTabChanged(SDL_CTab); + SDL_CPal = NewPalette(256, SDL_CTab, pmExplicit+pmTolerant, 0); + + return 0; +} + +static int DSp_DestroyPalette(_THIS) { + + /* Free palette and restore original one */ + if ( SDL_CTab != nil ) { + DisposeHandle((Handle)SDL_CTab); + SDL_CTab = nil; + } + if ( SDL_CPal != nil ) { + DisposePalette(SDL_CPal); + SDL_CPal = nil; + } + RestoreDeviceClut(SDL_Display); + + return (0); +} + +static int DSp_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors) +{ + CTabHandle cTab; + + int i; + + cTab = SDL_CTab; + + /* Verify the range of colors */ + if ( (firstcolor+ncolors) > ((**cTab).ctSize+1) ) { + return(0); + } + + /* Set the screen palette and update the display */ + for(i = 0; i < ncolors; i++) { + int j = firstcolor + i; + (**cTab).ctTable[j].value = j; + (**cTab).ctTable[j].rgb.red = colors[i].r << 8 | colors[i].r; + (**cTab).ctTable[j].rgb.green = colors[i].g << 8 | colors[i].g; + (**cTab).ctTable[j].rgb.blue = colors[i].b << 8 | colors[i].b; + } + + SetGDevice(SDL_Display); + SetEntries(0, (**cTab).ctSize, (ColorSpec *)&(**cTab).ctTable); + + return(1); +} + +void DSp_VideoQuit(_THIS) +{ + int i; + + /* Free current video mode */ + DSp_UnsetVideoMode(this, this->screen); + + /* Free Palette and restore original */ + DSp_DestroyPalette (this); + +#if SDL_MACCLASSIC_GAMMA_SUPPORT + Mac_QuitGamma(this); +#endif + + /* Free list of video modes */ + if ( SDL_modelist != NULL ) { + for ( i=0; SDL_modelist[i]; i++ ) { + SDL_free(SDL_modelist[i]); + } + SDL_free(SDL_modelist); + SDL_modelist = NULL; + } + + /* Unload DrawSprocket */ + DSpShutdown (); +} + +#if SDL_VIDEO_OPENGL + +/* swap buffers with v-sync */ +static void DSp_GL_SwapBuffers (_THIS) { + + #ifndef DSP_NO_SYNC_OPENGL + + unsigned int old_count; + + old_count = retrace_count; + while (old_count == retrace_count) + ; + #endif + + aglSwapBuffers (glContext); +} + +#endif diff --git a/3rdparty/SDL/src/video/macdsp/SDL_dspvideo.h b/3rdparty/SDL/src/video/macdsp/SDL_dspvideo.h new file mode 100644 index 0000000..7fc0896 --- /dev/null +++ b/3rdparty/SDL/src/video/macdsp/SDL_dspvideo.h @@ -0,0 +1,54 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#ifndef _SDL_dspvideo_h +#define _SDL_dspvideo_h + +#if TARGET_API_MAC_OSX +# include <DrawSprocket/DrawSprocket.h> /* Drawsprocket.framework */ +#else +#include <DrawSprocket.h> +#endif + +#include "../maccommon/SDL_lowvideo.h" + +/* DrawSprocket specific information */ +struct DSpInfo { + DSpContextReference dsp_context; + CGrafPtr dsp_back_buffer; + int dsp_old_depth; + + /* Flags for hw acceleration */ + int dsp_vram_available; + int dsp_agp_available; + + +}; +/* Old variable names */ +#define dsp_context (this->hidden->dspinfo->dsp_context) +#define dsp_back_buffer (this->hidden->dspinfo->dsp_back_buffer) +#define dsp_old_depth (this->hidden->dspinfo->dsp_old_depth) +#define dsp_vram_available (this->hidden->dspinfo->dsp_vram_available) +#define dsp_agp_available (this->hidden->dspinfo->dsp_agp_available) + +#endif /* _SDL_dspvideo_h */ diff --git a/3rdparty/SDL/src/video/macrom/SDL_romvideo.c b/3rdparty/SDL/src/video/macrom/SDL_romvideo.c new file mode 100644 index 0000000..4c48881 --- /dev/null +++ b/3rdparty/SDL/src/video/macrom/SDL_romvideo.c @@ -0,0 +1,745 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#if defined(__APPLE__) && defined(__MACH__) +#include <Carbon/Carbon.h> +#if USE_QUICKTIME +#include <QuickTime/Movies.h> +#endif +#elif TARGET_API_MAC_CARBON && (UNIVERSAL_INTERFACES_VERSION > 0x0335) +#include <Carbon.h> +/* The fullscreen code requires the QuickTime framework, and the window + is still at the back on Mac OS X, which is where this code is needed. + */ +#if USE_QUICKTIME +#include <Movies.h> +#endif +#else +#include <Quickdraw.h> +#include <LowMem.h> +#include <Gestalt.h> +#include <Devices.h> +#include <DiskInit.h> +#include <QDOffscreen.h> +#endif + +#include "SDL_video.h" +#include "SDL_syswm.h" +#include "../SDL_sysvideo.h" +#include "SDL_romvideo.h" +#include "../maccommon/SDL_macgl_c.h" +#include "../maccommon/SDL_macwm_c.h" +#include "../maccommon/SDL_macmouse_c.h" +#include "../maccommon/SDL_macevents_c.h" + +/* Initialization/Query functions */ +static int ROM_VideoInit(_THIS, SDL_PixelFormat *vformat); +static SDL_Rect **ROM_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags); +static SDL_Surface *ROM_SetVideoMode(_THIS, SDL_Surface *current, int width, int height, int bpp, Uint32 flags); +static int ROM_SetColors(_THIS, int firstcolor, int ncolors, + SDL_Color *colors); +static void ROM_VideoQuit(_THIS); + +/* Hardware surface functions */ +static int ROM_AllocHWSurface(_THIS, SDL_Surface *surface); +static int ROM_LockHWSurface(_THIS, SDL_Surface *surface); +static void ROM_UnlockHWSurface(_THIS, SDL_Surface *surface); +static void ROM_FreeHWSurface(_THIS, SDL_Surface *surface); + +#if !TARGET_API_MAC_CARBON /* This seems not to be available? -sts Aug 2000 */ +/* Saved state for the menu bar */ +static RgnHandle gSaveGrayRgn = nil; +static short gSaveMenuBar = 0; +static Boolean gSaveCSVis = true; + +#if powerc +/* Mixed mode glue to activate the 68K emulator and twiddle a register */ +#define ONEWORDSTUB(p1) \ + { 0x41FA, 0x0010, 0x209F, (p1), 0x41FA, \ + 0x0008, 0x2F10, 0x4E75, 0x0000, 0x0000, 0x0000 } + +#define TWOWORDSTUB(p1,p2) \ + { 0x41FA, 0x0012, 0x209F, (p1), (p2), 0x41FA, \ + 0x0008, 0x2F10, 0x4E75, 0x0000, 0x0000, 0x0000 } + +#define THREEWORDSTUB(p1,p2,p3) \ + { 0x41FA, 0x0014, 0x209F, (p1), (p2), (p3), 0x41FA, \ + 0x0008, 0x2F10, 0x4E75, 0x0000, 0x0000, 0x0000 } + +/* ControlStrip inline glue for PowerPC */ +static pascal Boolean SBIsControlStripVisible(void) +{ + static short procData[] = TWOWORDSTUB(0x7000, 0xAAF2); + ProcInfoType procInfo = kD0DispatchedPascalStackBased + | RESULT_SIZE(SIZE_CODE(sizeof(Boolean))) + | DISPATCHED_STACK_ROUTINE_SELECTOR_SIZE(kFourByteCode); + + return((Boolean) CallUniversalProc((UniversalProcPtr) procData, procInfo, 0x00)); +} + +static pascal void SBShowHideControlStrip(Boolean showIt) +{ + static short procData[] = THREEWORDSTUB(0x303C, 0x0101, 0xAAF2); + ProcInfoType procInfo = kD0DispatchedPascalStackBased + | DISPATCHED_STACK_ROUTINE_SELECTOR_SIZE(kFourByteCode) + | DISPATCHED_STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(Boolean))); + + CallUniversalProc((UniversalProcPtr) procData, procInfo, 0x01, showIt); +} +#endif /* powerc */ +#endif /* !TARGET_API_MAC_CARBON */ + +/* Macintosh toolbox driver bootstrap functions */ + +static int ROM_Available(void) +{ + return(1); +} + +static void ROM_DeleteDevice(SDL_VideoDevice *device) +{ + SDL_free(device->hidden); + SDL_free(device); +} + +static SDL_VideoDevice *ROM_CreateDevice(int devindex) +{ + SDL_VideoDevice *device; + + /* Initialize all variables that we clean on shutdown */ + device = (SDL_VideoDevice *)SDL_malloc(sizeof(SDL_VideoDevice)); + if ( device ) { + SDL_memset(device, 0, (sizeof *device)); + device->hidden = (struct SDL_PrivateVideoData *) + SDL_malloc((sizeof *device->hidden)); + } + if ( (device == NULL) || (device->hidden == NULL) ) { + SDL_OutOfMemory(); + if ( device ) { + SDL_free(device); + } + return(0); + } + SDL_memset(device->hidden, 0, (sizeof *device->hidden)); + + /* Set the function pointers */ + device->VideoInit = ROM_VideoInit; + device->ListModes = ROM_ListModes; + device->SetVideoMode = ROM_SetVideoMode; + device->SetColors = ROM_SetColors; + device->UpdateRects = NULL; + device->VideoQuit = ROM_VideoQuit; + device->AllocHWSurface = ROM_AllocHWSurface; + device->CheckHWBlit = NULL; + device->FillHWRect = NULL; + device->SetHWColorKey = NULL; + device->SetHWAlpha = NULL; + device->LockHWSurface = ROM_LockHWSurface; + device->UnlockHWSurface = ROM_UnlockHWSurface; + device->FlipHWSurface = NULL; + device->FreeHWSurface = ROM_FreeHWSurface; +#if SDL_MACCLASSIC_GAMMA_SUPPORT + device->SetGammaRamp = Mac_SetGammaRamp; + device->GetGammaRamp = Mac_GetGammaRamp; +#endif +#if SDL_VIDEO_OPENGL + device->GL_MakeCurrent = Mac_GL_MakeCurrent; + device->GL_SwapBuffers = Mac_GL_SwapBuffers; + device->GL_LoadLibrary = Mac_GL_LoadLibrary; + device->GL_GetProcAddress = Mac_GL_GetProcAddress; +#endif /* Have OpenGL */ + device->SetCaption = Mac_SetCaption; + device->SetIcon = NULL; + device->IconifyWindow = NULL; + device->GrabInput = NULL; + device->GetWMInfo = NULL; + device->FreeWMCursor = Mac_FreeWMCursor; + device->CreateWMCursor = Mac_CreateWMCursor; + device->ShowWMCursor = Mac_ShowWMCursor; + device->WarpWMCursor = Mac_WarpWMCursor; + device->InitOSKeymap = Mac_InitOSKeymap; + device->PumpEvents = Mac_PumpEvents; + + device->free = ROM_DeleteDevice; + + return device; +} + +VideoBootStrap TOOLBOX_bootstrap = { + "toolbox", "MacOS ROM Toolbox", + ROM_Available, ROM_CreateDevice +}; + + +static int ROM_VideoInit(_THIS, SDL_PixelFormat *vformat) +{ + long info; + + /* Check out some things about the system */ + Gestalt(gestaltQuickdrawVersion, &info); + if ( info == gestaltOriginalQD ) { + SDL_SetError("Color Quickdraw not available"); + return(-1); + } + + /* Start ROMintosh events */ + Mac_InitEvents(this); + + /* Get a handle to the main monitor */ + SDL_Display = GetMainDevice(); + + /* Determine the current screen size */ + this->info.current_w = (**SDL_Display).gdRect.right; + this->info.current_h = (**SDL_Display).gdRect.bottom; + + /* Determine pixel format */ + vformat->BitsPerPixel = (**(**SDL_Display).gdPMap).pixelSize; + switch (vformat->BitsPerPixel) { + case 16: /* 5-5-5 RGB */ + vformat->Rmask = 0x00007c00; + vformat->Gmask = 0x000003e0; + vformat->Bmask = 0x0000001f; + break; + default: + break; + } + + /* Create our palette */ + SDL_CTab = (CTabHandle)NewHandle(sizeof(ColorSpec)*256 + 8); + if ( SDL_CTab == nil ) { + SDL_OutOfMemory(); + return(-1); + } + (**SDL_CTab).ctSeed = GetCTSeed(); + (**SDL_CTab).ctFlags = 0; + (**SDL_CTab).ctSize = 255; + CTabChanged(SDL_CTab); + SDL_CPal = NewPalette(256, SDL_CTab, pmExplicit+pmTolerant, 0); + + /* Get a list of available fullscreen modes */ + SDL_modelist = (SDL_Rect **)SDL_malloc((1+1)*sizeof(SDL_Rect *)); + if ( SDL_modelist ) { + SDL_modelist[0] = (SDL_Rect *)SDL_malloc(sizeof(SDL_Rect)); + if ( SDL_modelist[0] ) { + SDL_modelist[0]->x = 0; + SDL_modelist[0]->y = 0; + SDL_modelist[0]->w = (**SDL_Display).gdRect.right; + SDL_modelist[0]->h = (**SDL_Display).gdRect.bottom; + } + SDL_modelist[1] = NULL; + } + + /* Fill in some window manager capabilities */ + this->info.wm_available = 1; + + /* We're done! */ + return(0); +} + +static SDL_Rect **ROM_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags) +{ + if ( this->screen->format->BitsPerPixel == format->BitsPerPixel ) { + if ( (flags & SDL_FULLSCREEN) == SDL_FULLSCREEN ) { + return(SDL_modelist); + } else { + return((SDL_Rect **)-1); + } + } else { + return((SDL_Rect **)0); + } +} + +static void ROM_HideMenuBar(_THIS) +{ +#if !TARGET_API_MAC_CARBON /* This seems not to be available? -sts Aug 2000 */ + RgnHandle drawRgn = nil; + RgnHandle tempRgn = nil; + RgnHandle grayRgn = nil; + WindowPtr window = nil; + GDHandle gd = nil; + GrafPtr savePort; + long response; + short height; + EventRecord theEvent; + + height = GetMBarHeight(); + + if ( height > 0 ) { + tempRgn = NewRgn(); + drawRgn = NewRgn(); + gSaveGrayRgn = NewRgn(); + if ( ! tempRgn || ! drawRgn || ! gSaveGrayRgn ) { + goto CLEANUP; + } + grayRgn = GetGrayRgn(); /* No need to check for this */ + + GetPort(&savePort); + + /* Hide the control strip if it's present, and record its + previous position into the dirty region for redrawing. + This isn't necessary, but may help catch stray bits. */ + CopyRgn(grayRgn, tempRgn); + if (!Gestalt(gestaltControlStripAttr, &response) && + (response & (1L << gestaltControlStripExists))) { + gSaveCSVis = SBIsControlStripVisible(); + if (gSaveCSVis) + SBShowHideControlStrip(false); + } + DiffRgn(grayRgn, tempRgn, drawRgn); + + /* Save the gray region once the control strip is hidden*/ + CopyRgn(grayRgn, gSaveGrayRgn); + + /* Change the menu height in lowmem */ + gSaveMenuBar = height; + LMSetMBarHeight(0); + + /* Walk the monitor rectangles, and combine any pieces that + aren't in GrayRgn: menubar, round corners, fake floaters. */ + for(gd = GetDeviceList(); gd; gd = GetNextDevice(gd)) + { + if (!TestDeviceAttribute(gd, screenDevice)) continue; + if (!TestDeviceAttribute(gd, screenActive)) continue; + + RectRgn(tempRgn, &(*gd)->gdRect); /* Get the whole screen */ + DiffRgn(tempRgn, grayRgn, tempRgn); /* Subtract out GrayRgn */ + UnionRgn(tempRgn, drawRgn, drawRgn);/* Combine all the bits */ + } + + /* Add the bits into the GrayRgn */ + UnionRgn(drawRgn, grayRgn, grayRgn); + + /* Modify the vis regions of exposed windows */ + window = (FrontWindow()) ? FrontWindow() : (WindowPtr) -1L; + PaintBehind(window, drawRgn); + CalcVisBehind(window, drawRgn); + + SetPort(savePort); + + /* Yield time so that floaters can catch up */ + EventAvail(0, &theEvent); + EventAvail(0, &theEvent); + EventAvail(0, &theEvent); + EventAvail(0, &theEvent); + } + +CLEANUP: + + if (tempRgn) DisposeRgn(tempRgn); + if (drawRgn) DisposeRgn(drawRgn); +#endif /* !TARGET_API_MAC_CARBON */ +} + +static void ROM_ShowMenuBar(_THIS) +{ +#if !TARGET_API_MAC_CARBON /* This seems not to be available? -sts Aug 2000 */ + RgnHandle drawRgn = nil; + RgnHandle menuRgn = nil; + RgnHandle tempRgn = nil; + RgnHandle grayRgn = nil; + WindowPtr window = nil; + GrafPtr wMgrPort; + GrafPtr savePort; + Rect menuRect; + long response; + short height; + EventRecord theEvent; + RGBColor saveRGB; + RGBColor blackRGB = { 0, 0, 0 }; + + height = GetMBarHeight(); + + if ((height <= 0) && (gSaveMenuBar > 0)) { + drawRgn = NewRgn(); + menuRgn = NewRgn(); + tempRgn = NewRgn(); + if ( ! tempRgn || ! drawRgn || ! gSaveGrayRgn ) { + goto CLEANUP; + } + grayRgn = GetGrayRgn(); /* No need to check for this */ + + GetPort(&savePort); + GetWMgrPort(&wMgrPort); + + /* Set the height properly */ + LMSetMBarHeight(gSaveMenuBar); + + /* Restore the old GrayRgn: rounded corners, etc, but not + the menubar -- subtract that out first! */ + if (gSaveGrayRgn) + { + menuRect = (*GetMainDevice())->gdRect; + menuRect.bottom = menuRect.top + gSaveMenuBar; + RectRgn(menuRgn, &menuRect); + + DiffRgn(grayRgn, gSaveGrayRgn, drawRgn); /* What do we inval? */ + DiffRgn(drawRgn, menuRgn, drawRgn); /* Clip out the menu */ + + /* Now redraw the corners and other bits black */ + SetPort(wMgrPort); + GetClip(tempRgn); + SetClip(drawRgn); + GetForeColor(&saveRGB); + RGBForeColor(&blackRGB); + PaintRgn(drawRgn); + RGBForeColor(&saveRGB); + SetClip(tempRgn); + SetPort(savePort); + + UnionRgn(drawRgn, menuRgn, drawRgn); /* Put back the menu */ + + /* Now actually restore the GrayRgn */ + CopyRgn(gSaveGrayRgn, grayRgn); + DisposeRgn(gSaveGrayRgn); + gSaveGrayRgn = nil; + } + + /* Modify the vis regions of exposed windows and draw menubar */ + window = (FrontWindow()) ? FrontWindow() : (WindowPtr) -1L; + PaintBehind(window, drawRgn); + CalcVisBehind(window, drawRgn); + DrawMenuBar(); + + SetPort(savePort); + gSaveMenuBar = 0; + + /* Now show the control strip if it's present */ + if (!Gestalt(gestaltControlStripAttr, &response) && + (response & (1L << gestaltControlStripExists))) + { + if (gSaveCSVis && !SBIsControlStripVisible()) + SBShowHideControlStrip(true); + gSaveCSVis = true; + } + + /* Yield time so that floaters can catch up */ + EventAvail(0, &theEvent); + EventAvail(0, &theEvent); + EventAvail(0, &theEvent); + EventAvail(0, &theEvent); + } + +CLEANUP: + + if (drawRgn) DisposeRgn(drawRgn); + if (menuRgn) DisposeRgn(menuRgn); + if (tempRgn) DisposeRgn(tempRgn); +#endif /* !TARGET_API_MAC_CARBON */ +} + +/* Various screen update functions available */ +static void ROM_DirectUpdate(_THIS, int numrects, SDL_Rect *rects); +static void ROM_WindowUpdate(_THIS, int numrects, SDL_Rect *rects); + +static void ROM_UnsetVideoMode(_THIS, SDL_Surface *current) +{ + /* Free the current window, if any */ + if ( SDL_Window != nil ) { + GWorldPtr memworld; + + /* Handle OpenGL support */ + Mac_GL_Quit(this); + + memworld = (GWorldPtr)GetWRefCon(SDL_Window); + if ( memworld != nil ) { + UnlockPixels(GetGWorldPixMap(memworld)); + DisposeGWorld(memworld); + } + if ( (current->flags & SDL_FULLSCREEN) == SDL_FULLSCREEN ) { +#if USE_QUICKTIME + EndFullScreen(fullscreen_ctx, nil); + SDL_Window = nil; +#else + ROM_ShowMenuBar(this); +#endif + } + } + current->pixels = NULL; + current->flags &= ~(SDL_HWSURFACE|SDL_FULLSCREEN); +} + +static SDL_Surface *ROM_SetVideoMode(_THIS, SDL_Surface *current, + int width, int height, int bpp, Uint32 flags) +{ + Rect wrect, orect; +#if TARGET_API_MAC_CARBON + Rect tmprect; +#endif + + /* Free any previous video mode */ + ROM_UnsetVideoMode(this, current); + + /* Create the ROM window and SDL video surface */ + current->flags = 0; /* Clear flags */ + current->w = width; + current->h = height; + SetRect(&wrect, 0, 0, width, height); + if ( SDL_Window ) { + /* If we recreate the window, don't move it around */ +#if TARGET_API_MAC_CARBON + orect = *GetWindowPortBounds(SDL_Window, &tmprect); +#else + orect = SDL_Window->portRect; +#endif + OffsetRect(&wrect, orect.left, orect.top); + } else { + /* Center the window the first time we show it */ + OffsetRect(&wrect, + (SDL_modelist[0]->w-width)/2, (SDL_modelist[0]->h-height)/2); + } + +#if defined(__MACOSX__) && !USE_QUICKTIME + /* Hum.. fullscreen mode is broken */ + flags &= ~SDL_FULLSCREEN; +#endif + if ( (flags & SDL_FULLSCREEN) == SDL_FULLSCREEN ) { + /* Create the fullscreen window and use screen bits */ + current->flags |= SDL_HWSURFACE|SDL_FULLSCREEN; + if ( SDL_Window ) { + DisposeWindow(SDL_Window); + } +#if USE_QUICKTIME + BeginFullScreen(&fullscreen_ctx, nil, 0,0, &SDL_Window, nil, 0); +#else + SDL_Window = NewCWindow(nil, &wrect, "\p", true, plainDBox, + (WindowPtr)-1, false, 0); + ROM_HideMenuBar(this); +#endif + current->pitch = (**(**SDL_Display).gdPMap).rowBytes & 0x3FFF; + current->pixels = (**(**SDL_Display).gdPMap).baseAddr; + this->UpdateRects = ROM_DirectUpdate; + } else { + GWorldPtr memworld; + PixMapHandle pixmap; + int style; + + style = noGrowDocProc; + if ( flags & SDL_NOFRAME ) { + style = plainDBox; + current->flags |= SDL_NOFRAME; + } else + if ( flags & SDL_RESIZABLE ) { + style = zoomDocProc; + current->flags |= SDL_RESIZABLE; + } + if ( SDL_Window && (style == current_style) ) { + /* Resize existing window, if necessary */ + if ( ((orect.right-orect.left) != width) || + ((orect.bottom-orect.top) != height) ) { + SizeWindow(SDL_Window, width, height, false); + } + } else { + /* Recreate the window in the new style */ + if ( SDL_Window ) { + DisposeWindow(SDL_Window); + } + SDL_Window = NewCWindow(nil, &wrect, "\p", true, + style, (WindowPtr)-1, true, 0); + + /* Set the window title, if any */ + { char *title; + SDL_WM_GetCaption(&title, NULL); + if ( title ) { + Mac_SetCaption(this, title, NULL); + } + } + } + current_style = style; + SetPalette(SDL_Window, SDL_CPal, false); + ActivatePalette(SDL_Window); + if ( NewGWorld(&memworld, 0, +#if TARGET_API_MAC_CARBON + GetWindowPortBounds(SDL_Window, &tmprect), +#else + &SDL_Window->portRect, +#endif + SDL_CTab, nil, 0) != noErr ) { + SDL_SetError("NewGWorld() failed"); + return(NULL); + } + SetWRefCon(SDL_Window, (long)memworld); + pixmap = GetGWorldPixMap(memworld); + LockPixels(pixmap); + current->pitch = (**pixmap).rowBytes & 0x3FFF; + current->pixels = GetPixBaseAddr(pixmap); + this->UpdateRects = ROM_WindowUpdate; + } + SetPortWindowPort(SDL_Window); + SelectWindow(SDL_Window); + + /* Handle OpenGL support */ + if ( flags & SDL_OPENGL ) { + if ( Mac_GL_Init(this) == 0 ) { + current->flags |= SDL_OPENGL; + } else { + current = NULL; + } + } + + if ( (flags & SDL_HWPALETTE) && (flags & SDL_FULLSCREEN) ) + current->flags |= SDL_HWPALETTE; + + /* We're live! */ + return(current); +} + +/* We don't actually allow hardware surfaces other than the main one */ +static int ROM_AllocHWSurface(_THIS, SDL_Surface *surface) +{ + return(-1); +} +static void ROM_FreeHWSurface(_THIS, SDL_Surface *surface) +{ + return; +} +static int ROM_LockHWSurface(_THIS, SDL_Surface *surface) +{ + return(0); +} +static void ROM_UnlockHWSurface(_THIS, SDL_Surface *surface) +{ + return; +} + +static void ROM_DirectUpdate(_THIS, int numrects, SDL_Rect *rects) +{ + /* The application is already updating the visible video memory */ + return; +} + +static void ROM_WindowUpdate(_THIS, int numrects, SDL_Rect *rects) +{ + GWorldPtr memworld; + GrafPtr saveport; + CGrafPtr thePort; + const BitMap *memBits; + const BitMap *winBits; + int i; + Rect update; + + /* Copy from the offscreen GWorld to the window port */ + GetPort(&saveport); + SetPortWindowPort(SDL_Window); + thePort = GetWindowPort(SDL_Window); + memworld = (GWorldPtr)GetWRefCon(SDL_Window); +#if TARGET_API_MAC_CARBON && ACCESSOR_CALLS_ARE_FUNCTIONS + memBits = GetPortBitMapForCopyBits((CGrafPtr) memworld); +#else + memBits = &((GrafPtr)memworld)->portBits; +#endif +#if TARGET_API_MAC_CARBON && ACCESSOR_CALLS_ARE_FUNCTIONS + winBits = GetPortBitMapForCopyBits(thePort); +#else + winBits = &SDL_Window->portBits; +#endif + for ( i=0; i<numrects; ++i ) { + update.left = rects[i].x; + update.right = rects[i].x+rects[i].w; + update.top = rects[i].y; + update.bottom = rects[i].y+rects[i].h; + CopyBits(memBits, winBits, + &update, &update, srcCopy, nil); + } +#if TARGET_API_MAC_CARBON + if ( QDIsPortBuffered(thePort) ) { + QDFlushPortBuffer(thePort, NULL); + } +#endif + SetPort(saveport); +} + +static int ROM_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors) +{ + CTabHandle cTab; + int i; + + /* Get the colortable from the either the display or window */ + if ( (this->screen->flags & SDL_FULLSCREEN) == SDL_FULLSCREEN ) { + cTab = (**(**SDL_Display).gdPMap).pmTable; + } else { + cTab = SDL_CTab; + } + + /* Verify the range of colors */ + if ( (firstcolor+ncolors) > ((**cTab).ctSize+1) ) { + return(0); + } + + /* Set the screen palette and update the display */ + for ( i=0; i< ncolors; ++i ) { + int j = firstcolor + i; + (**cTab).ctTable[j].value = j; + (**cTab).ctTable[j].rgb.red = colors[i].r << 8 | colors[i].r; + (**cTab).ctTable[j].rgb.green = colors[i].g << 8 | colors[i].g; + (**cTab).ctTable[j].rgb.blue = colors[i].b << 8 | colors[i].b; + } + +#if 0 + if ( (this->screen->flags & SDL_FULLSCREEN) == SDL_FULLSCREEN ) +#endif + { + GDevice **odisplay; + odisplay = GetGDevice(); + SetGDevice(SDL_Display); + SetEntries(0, (**cTab).ctSize, (ColorSpec *)&(**cTab).ctTable); + SetGDevice(odisplay); + } + return(1); +} + +void ROM_VideoQuit(_THIS) +{ + int i; + + /* Free current video mode */ + ROM_UnsetVideoMode(this, this->screen); + if ( SDL_Window ) { + DisposeWindow(SDL_Window); + SDL_Window = nil; + } + + /* Free palette and restore original one */ + if ( SDL_CTab != nil ) { + DisposeHandle((Handle)SDL_CTab); + SDL_CTab = nil; + } + if ( SDL_CPal != nil ) { + DisposePalette(SDL_CPal); + SDL_CPal = nil; + } + RestoreDeviceClut(GetMainDevice()); + +#if SDL_MACCLASSIC_GAMMA_SUPPORT + Mac_QuitGamma(this); +#endif + + /* Free list of video modes */ + if ( SDL_modelist != NULL ) { + for ( i=0; SDL_modelist[i]; ++i ) { + SDL_free(SDL_modelist[i]); + } + SDL_free(SDL_modelist); + SDL_modelist = NULL; + } +} + diff --git a/3rdparty/SDL/src/video/macrom/SDL_romvideo.h b/3rdparty/SDL/src/video/macrom/SDL_romvideo.h new file mode 100644 index 0000000..0380f91 --- /dev/null +++ b/3rdparty/SDL/src/video/macrom/SDL_romvideo.h @@ -0,0 +1,29 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#ifndef _SDL_romvideo_h +#define _SDL_romvideo_h + +#include "../maccommon/SDL_lowvideo.h" + +#endif /* _SDL_romvideo_h */ diff --git a/3rdparty/SDL/src/video/math_private.h b/3rdparty/SDL/src/video/math_private.h new file mode 100644 index 0000000..1087d7d --- /dev/null +++ b/3rdparty/SDL/src/video/math_private.h @@ -0,0 +1,173 @@ +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunPro, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ + +/* + * from: @(#)fdlibm.h 5.1 93/09/24 + * $Id$ + */ + +#ifndef _MATH_PRIVATE_H_ +#define _MATH_PRIVATE_H_ + +#include "SDL_name.h" +#include "SDL_endian.h" + +#define huge really_big /* huge is a reserved keyword in VC++ 6.0 */ +#define u_int32_t uint32_t + +/* The original fdlibm code used statements like: + n0 = ((*(int*)&one)>>29)^1; * index of high word * + ix0 = *(n0+(int*)&x); * high word of x * + ix1 = *((1-n0)+(int*)&x); * low word of x * + to dig two 32 bit words out of the 64 bit IEEE floating point + value. That is non-ANSI, and, moreover, the gcc instruction + scheduler gets it wrong. We instead use the following macros. + Unlike the original code, we determine the endianness at compile + time, not at run time; I don't see much benefit to selecting + endianness at run time. */ + +/* A union which permits us to convert between a double and two 32 bit + ints. */ + +/* + * Math on arm is special: + * For FPA, float words are always big-endian. + * For VFP, floats words follow the memory system mode. + */ + +#if (SDL_BYTEORDER == SDL_BIG_ENDIAN) || \ + (!defined(__VFP_FP__) && (defined(__arm__) || defined(__thumb__))) + +typedef union +{ + double value; + struct + { + u_int32_t msw; + u_int32_t lsw; + } parts; +} ieee_double_shape_type; + +#else + +typedef union +{ + double value; + struct + { + u_int32_t lsw; + u_int32_t msw; + } parts; +} ieee_double_shape_type; + +#endif + +/* Get two 32 bit ints from a double. */ + +#define EXTRACT_WORDS(ix0,ix1,d) \ +do { \ + ieee_double_shape_type ew_u; \ + ew_u.value = (d); \ + (ix0) = ew_u.parts.msw; \ + (ix1) = ew_u.parts.lsw; \ +} while (0) + +/* Get the more significant 32 bit int from a double. */ + +#define GET_HIGH_WORD(i,d) \ +do { \ + ieee_double_shape_type gh_u; \ + gh_u.value = (d); \ + (i) = gh_u.parts.msw; \ +} while (0) + +/* Get the less significant 32 bit int from a double. */ + +#define GET_LOW_WORD(i,d) \ +do { \ + ieee_double_shape_type gl_u; \ + gl_u.value = (d); \ + (i) = gl_u.parts.lsw; \ +} while (0) + +/* Set a double from two 32 bit ints. */ + +#define INSERT_WORDS(d,ix0,ix1) \ +do { \ + ieee_double_shape_type iw_u; \ + iw_u.parts.msw = (ix0); \ + iw_u.parts.lsw = (ix1); \ + (d) = iw_u.value; \ +} while (0) + +/* Set the more significant 32 bits of a double from an int. */ + +#define SET_HIGH_WORD(d,v) \ +do { \ + ieee_double_shape_type sh_u; \ + sh_u.value = (d); \ + sh_u.parts.msw = (v); \ + (d) = sh_u.value; \ +} while (0) + +/* Set the less significant 32 bits of a double from an int. */ + +#define SET_LOW_WORD(d,v) \ +do { \ + ieee_double_shape_type sl_u; \ + sl_u.value = (d); \ + sl_u.parts.lsw = (v); \ + (d) = sl_u.value; \ +} while (0) + +/* A union which permits us to convert between a float and a 32 bit + int. */ + +typedef union +{ + float value; + u_int32_t word; +} ieee_float_shape_type; + +/* Get a 32 bit int from a float. */ + +#define GET_FLOAT_WORD(i,d) \ +do { \ + ieee_float_shape_type gf_u; \ + gf_u.value = (d); \ + (i) = gf_u.word; \ +} while (0) + +/* Set a float from a 32 bit int. */ + +#define SET_FLOAT_WORD(d,i) \ +do { \ + ieee_float_shape_type sf_u; \ + sf_u.word = (i); \ + (d) = sf_u.value; \ +} while (0) + + +#ifdef __STDC__ +static const double +#else +static double +#endif +zero = 0.0, +one = 1.0, +two = 2.0, +two53 = 9007199254740992.0, /* 0x43400000, 0x00000000 */ +two54 = 1.80143985094819840000e+16, /* 0x43500000, 0x00000000 */ +twom54 = 5.55111512312578270212e-17, /* 0x3C900000, 0x00000000 */ +huge = 1.0e+300, +tiny = 1.0e-300; + +#endif /* _MATH_PRIVATE_H_ */ diff --git a/3rdparty/SDL/src/video/mmx.h b/3rdparty/SDL/src/video/mmx.h new file mode 100644 index 0000000..dcee7b0 --- /dev/null +++ b/3rdparty/SDL/src/video/mmx.h @@ -0,0 +1,704 @@ +/* mmx.h + + MultiMedia eXtensions GCC interface library for IA32. + + To use this library, simply include this header file + and compile with GCC. You MUST have inlining enabled + in order for mmx_ok() to work; this can be done by + simply using -O on the GCC command line. + + Compiling with -DMMX_TRACE will cause detailed trace + output to be sent to stderr for each mmx operation. + This adds lots of code, and obviously slows execution to + a crawl, but can be very useful for debugging. + + THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY + EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT + LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTABILITY + AND FITNESS FOR ANY PARTICULAR PURPOSE. + + 1997-99 by H. Dietz and R. Fisher + + Notes: + It appears that the latest gas has the pand problem fixed, therefore + I'll undefine BROKEN_PAND by default. +*/ + +#ifndef _MMX_H +#define _MMX_H + + +/* Warning: at this writing, the version of GAS packaged + with most Linux distributions does not handle the + parallel AND operation mnemonic correctly. If the + symbol BROKEN_PAND is defined, a slower alternative + coding will be used. If execution of mmxtest results + in an illegal instruction fault, define this symbol. +*/ +#undef BROKEN_PAND + + +/* The type of an value that fits in an MMX register + (note that long long constant values MUST be suffixed + by LL and unsigned long long values by ULL, lest + they be truncated by the compiler) +*/ +typedef union { + long long q; /* Quadword (64-bit) value */ + unsigned long long uq; /* Unsigned Quadword */ + int d[2]; /* 2 Doubleword (32-bit) values */ + unsigned int ud[2]; /* 2 Unsigned Doubleword */ + short w[4]; /* 4 Word (16-bit) values */ + unsigned short uw[4]; /* 4 Unsigned Word */ + char b[8]; /* 8 Byte (8-bit) values */ + unsigned char ub[8]; /* 8 Unsigned Byte */ + float s[2]; /* Single-precision (32-bit) value */ +} __attribute__ ((aligned (8))) mmx_t; /* On an 8-byte (64-bit) boundary */ + + +#if 0 +/* Function to test if multimedia instructions are supported... +*/ +inline extern int +mm_support(void) +{ + /* Returns 1 if MMX instructions are supported, + 3 if Cyrix MMX and Extended MMX instructions are supported + 5 if AMD MMX and 3DNow! instructions are supported + 0 if hardware does not support any of these + */ + register int rval = 0; + + __asm__ __volatile__ ( + /* See if CPUID instruction is supported ... */ + /* ... Get copies of EFLAGS into eax and ecx */ + "pushf\n\t" + "popl %%eax\n\t" + "movl %%eax, %%ecx\n\t" + + /* ... Toggle the ID bit in one copy and store */ + /* to the EFLAGS reg */ + "xorl $0x200000, %%eax\n\t" + "push %%eax\n\t" + "popf\n\t" + + /* ... Get the (hopefully modified) EFLAGS */ + "pushf\n\t" + "popl %%eax\n\t" + + /* ... Compare and test result */ + "xorl %%eax, %%ecx\n\t" + "testl $0x200000, %%ecx\n\t" + "jz NotSupported1\n\t" /* CPUID not supported */ + + + /* Get standard CPUID information, and + go to a specific vendor section */ + "movl $0, %%eax\n\t" + "cpuid\n\t" + + /* Check for Intel */ + "cmpl $0x756e6547, %%ebx\n\t" + "jne TryAMD\n\t" + "cmpl $0x49656e69, %%edx\n\t" + "jne TryAMD\n\t" + "cmpl $0x6c65746e, %%ecx\n" + "jne TryAMD\n\t" + "jmp Intel\n\t" + + /* Check for AMD */ + "\nTryAMD:\n\t" + "cmpl $0x68747541, %%ebx\n\t" + "jne TryCyrix\n\t" + "cmpl $0x69746e65, %%edx\n\t" + "jne TryCyrix\n\t" + "cmpl $0x444d4163, %%ecx\n" + "jne TryCyrix\n\t" + "jmp AMD\n\t" + + /* Check for Cyrix */ + "\nTryCyrix:\n\t" + "cmpl $0x69727943, %%ebx\n\t" + "jne NotSupported2\n\t" + "cmpl $0x736e4978, %%edx\n\t" + "jne NotSupported3\n\t" + "cmpl $0x64616574, %%ecx\n\t" + "jne NotSupported4\n\t" + /* Drop through to Cyrix... */ + + + /* Cyrix Section */ + /* See if extended CPUID level 80000001 is supported */ + /* The value of CPUID/80000001 for the 6x86MX is undefined + according to the Cyrix CPU Detection Guide (Preliminary + Rev. 1.01 table 1), so we'll check the value of eax for + CPUID/0 to see if standard CPUID level 2 is supported. + According to the table, the only CPU which supports level + 2 is also the only one which supports extended CPUID levels. + */ + "cmpl $0x2, %%eax\n\t" + "jne MMXtest\n\t" /* Use standard CPUID instead */ + + /* Extended CPUID supported (in theory), so get extended + features */ + "movl $0x80000001, %%eax\n\t" + "cpuid\n\t" + "testl $0x00800000, %%eax\n\t" /* Test for MMX */ + "jz NotSupported5\n\t" /* MMX not supported */ + "testl $0x01000000, %%eax\n\t" /* Test for Ext'd MMX */ + "jnz EMMXSupported\n\t" + "movl $1, %0:\n\n\t" /* MMX Supported */ + "jmp Return\n\n" + "EMMXSupported:\n\t" + "movl $3, %0:\n\n\t" /* EMMX and MMX Supported */ + "jmp Return\n\t" + + + /* AMD Section */ + "AMD:\n\t" + + /* See if extended CPUID is supported */ + "movl $0x80000000, %%eax\n\t" + "cpuid\n\t" + "cmpl $0x80000000, %%eax\n\t" + "jl MMXtest\n\t" /* Use standard CPUID instead */ + + /* Extended CPUID supported, so get extended features */ + "movl $0x80000001, %%eax\n\t" + "cpuid\n\t" + "testl $0x00800000, %%edx\n\t" /* Test for MMX */ + "jz NotSupported6\n\t" /* MMX not supported */ + "testl $0x80000000, %%edx\n\t" /* Test for 3DNow! */ + "jnz ThreeDNowSupported\n\t" + "movl $1, %0:\n\n\t" /* MMX Supported */ + "jmp Return\n\n" + "ThreeDNowSupported:\n\t" + "movl $5, %0:\n\n\t" /* 3DNow! and MMX Supported */ + "jmp Return\n\t" + + + /* Intel Section */ + "Intel:\n\t" + + /* Check for MMX */ + "MMXtest:\n\t" + "movl $1, %%eax\n\t" + "cpuid\n\t" + "testl $0x00800000, %%edx\n\t" /* Test for MMX */ + "jz NotSupported7\n\t" /* MMX Not supported */ + "movl $1, %0:\n\n\t" /* MMX Supported */ + "jmp Return\n\t" + + /* Nothing supported */ + "\nNotSupported1:\n\t" + "#movl $101, %0:\n\n\t" + "\nNotSupported2:\n\t" + "#movl $102, %0:\n\n\t" + "\nNotSupported3:\n\t" + "#movl $103, %0:\n\n\t" + "\nNotSupported4:\n\t" + "#movl $104, %0:\n\n\t" + "\nNotSupported5:\n\t" + "#movl $105, %0:\n\n\t" + "\nNotSupported6:\n\t" + "#movl $106, %0:\n\n\t" + "\nNotSupported7:\n\t" + "#movl $107, %0:\n\n\t" + "movl $0, %0:\n\n\t" + + "Return:\n\t" + : "=a" (rval) + : /* no input */ + : "eax", "ebx", "ecx", "edx" + ); + + /* Return */ + return(rval); +} + +/* Function to test if mmx instructions are supported... +*/ +inline extern int +mmx_ok(void) +{ + /* Returns 1 if MMX instructions are supported, 0 otherwise */ + return ( mm_support() & 0x1 ); +} +#endif + +/* Helper functions for the instruction macros that follow... + (note that memory-to-register, m2r, instructions are nearly + as efficient as register-to-register, r2r, instructions; + however, memory-to-memory instructions are really simulated + as a convenience, and are only 1/3 as efficient) +*/ +#ifdef MMX_TRACE + +/* Include the stuff for printing a trace to stderr... +*/ + +#define mmx_i2r(op, imm, reg) \ + { \ + mmx_t mmx_trace; \ + mmx_trace.uq = (imm); \ + printf(#op "_i2r(" #imm "=0x%08x%08x, ", \ + mmx_trace.d[1], mmx_trace.d[0]); \ + __asm__ __volatile__ ("movq %%" #reg ", %0" \ + : "=y" (mmx_trace) \ + : /* nothing */ ); \ + printf(#reg "=0x%08x%08x) => ", \ + mmx_trace.d[1], mmx_trace.d[0]); \ + __asm__ __volatile__ (#op " %0, %%" #reg \ + : /* nothing */ \ + : "y" (imm)); \ + __asm__ __volatile__ ("movq %%" #reg ", %0" \ + : "=y" (mmx_trace) \ + : /* nothing */ ); \ + printf(#reg "=0x%08x%08x\n", \ + mmx_trace.d[1], mmx_trace.d[0]); \ + } + +#define mmx_m2r(op, mem, reg) \ + { \ + mmx_t mmx_trace; \ + mmx_trace = (mem); \ + printf(#op "_m2r(" #mem "=0x%08x%08x, ", \ + mmx_trace.d[1], mmx_trace.d[0]); \ + __asm__ __volatile__ ("movq %%" #reg ", %0" \ + : "=y" (mmx_trace) \ + : /* nothing */ ); \ + printf(#reg "=0x%08x%08x) => ", \ + mmx_trace.d[1], mmx_trace.d[0]); \ + __asm__ __volatile__ (#op " %0, %%" #reg \ + : /* nothing */ \ + : "y" (mem)); \ + __asm__ __volatile__ ("movq %%" #reg ", %0" \ + : "=y" (mmx_trace) \ + : /* nothing */ ); \ + printf(#reg "=0x%08x%08x\n", \ + mmx_trace.d[1], mmx_trace.d[0]); \ + } + +#define mmx_r2m(op, reg, mem) \ + { \ + mmx_t mmx_trace; \ + __asm__ __volatile__ ("movq %%" #reg ", %0" \ + : "=y" (mmx_trace) \ + : /* nothing */ ); \ + printf(#op "_r2m(" #reg "=0x%08x%08x, ", \ + mmx_trace.d[1], mmx_trace.d[0]); \ + mmx_trace = (mem); \ + printf(#mem "=0x%08x%08x) => ", \ + mmx_trace.d[1], mmx_trace.d[0]); \ + __asm__ __volatile__ (#op " %%" #reg ", %0" \ + : "=y" (mem) \ + : /* nothing */ ); \ + mmx_trace = (mem); \ + printf(#mem "=0x%08x%08x\n", \ + mmx_trace.d[1], mmx_trace.d[0]); \ + } + +#define mmx_r2r(op, regs, regd) \ + { \ + mmx_t mmx_trace; \ + __asm__ __volatile__ ("movq %%" #regs ", %0" \ + : "=y" (mmx_trace) \ + : /* nothing */ ); \ + printf(#op "_r2r(" #regs "=0x%08x%08x, ", \ + mmx_trace.d[1], mmx_trace.d[0]); \ + __asm__ __volatile__ ("movq %%" #regd ", %0" \ + : "=y" (mmx_trace) \ + : /* nothing */ ); \ + printf(#regd "=0x%08x%08x) => ", \ + mmx_trace.d[1], mmx_trace.d[0]); \ + __asm__ __volatile__ (#op " %" #regs ", %" #regd); \ + __asm__ __volatile__ ("movq %%" #regd ", %0" \ + : "=y" (mmx_trace) \ + : /* nothing */ ); \ + printf(#regd "=0x%08x%08x\n", \ + mmx_trace.d[1], mmx_trace.d[0]); \ + } + +#define mmx_m2m(op, mems, memd) \ + { \ + mmx_t mmx_trace; \ + mmx_trace = (mems); \ + printf(#op "_m2m(" #mems "=0x%08x%08x, ", \ + mmx_trace.d[1], mmx_trace.d[0]); \ + mmx_trace = (memd); \ + printf(#memd "=0x%08x%08x) => ", \ + mmx_trace.d[1], mmx_trace.d[0]); \ + __asm__ __volatile__ ("movq %0, %%mm0\n\t" \ + #op " %1, %%mm0\n\t" \ + "movq %%mm0, %0" \ + : "=y" (memd) \ + : "y" (mems)); \ + mmx_trace = (memd); \ + printf(#memd "=0x%08x%08x\n", \ + mmx_trace.d[1], mmx_trace.d[0]); \ + } + +#else + +/* These macros are a lot simpler without the tracing... +*/ + +#define mmx_i2r(op, imm, reg) \ + __asm__ __volatile__ (#op " %0, %%" #reg \ + : /* nothing */ \ + : "y" (imm) ) + +#define mmx_m2r(op, mem, reg) \ + __asm__ __volatile__ (#op " %0, %%" #reg \ + : /* nothing */ \ + : "m" (mem)) + +#define mmx_r2m(op, reg, mem) \ + __asm__ __volatile__ (#op " %%" #reg ", %0" \ + : "=m" (mem) \ + : /* nothing */ ) + +#define mmx_r2r(op, regs, regd) \ + __asm__ __volatile__ (#op " %" #regs ", %" #regd) + +#define mmx_m2m(op, mems, memd) \ + __asm__ __volatile__ ("movq %0, %%mm0\n\t" \ + #op " %1, %%mm0\n\t" \ + "movq %%mm0, %0" \ + : "=y" (memd) \ + : "y" (mems)) + +#endif + + +/* 1x64 MOVe Quadword + (this is both a load and a store... + in fact, it is the only way to store) +*/ +#define movq_m2r(var, reg) mmx_m2r(movq, var, reg) +#define movq_r2m(reg, var) mmx_r2m(movq, reg, var) +#define movq_r2r(regs, regd) mmx_r2r(movq, regs, regd) +#define movq(vars, vard) \ + __asm__ __volatile__ ("movq %1, %%mm0\n\t" \ + "movq %%mm0, %0" \ + : "=y" (vard) \ + : "y" (vars)) + + +/* 1x32 MOVe Doubleword + (like movq, this is both load and store... + but is most useful for moving things between + mmx registers and ordinary registers) +*/ +#define movd_m2r(var, reg) mmx_m2r(movd, var, reg) +#define movd_r2m(reg, var) mmx_r2m(movd, reg, var) +#define movd_r2r(regs, regd) mmx_r2r(movd, regs, regd) +#define movd(vars, vard) \ + __asm__ __volatile__ ("movd %1, %%mm0\n\t" \ + "movd %%mm0, %0" \ + : "=y" (vard) \ + : "y" (vars)) + + +/* 2x32, 4x16, and 8x8 Parallel ADDs +*/ +#define paddd_m2r(var, reg) mmx_m2r(paddd, var, reg) +#define paddd_r2r(regs, regd) mmx_r2r(paddd, regs, regd) +#define paddd(vars, vard) mmx_m2m(paddd, vars, vard) + +#define paddw_m2r(var, reg) mmx_m2r(paddw, var, reg) +#define paddw_r2r(regs, regd) mmx_r2r(paddw, regs, regd) +#define paddw(vars, vard) mmx_m2m(paddw, vars, vard) + +#define paddb_m2r(var, reg) mmx_m2r(paddb, var, reg) +#define paddb_r2r(regs, regd) mmx_r2r(paddb, regs, regd) +#define paddb(vars, vard) mmx_m2m(paddb, vars, vard) + + +/* 4x16 and 8x8 Parallel ADDs using Saturation arithmetic +*/ +#define paddsw_m2r(var, reg) mmx_m2r(paddsw, var, reg) +#define paddsw_r2r(regs, regd) mmx_r2r(paddsw, regs, regd) +#define paddsw(vars, vard) mmx_m2m(paddsw, vars, vard) + +#define paddsb_m2r(var, reg) mmx_m2r(paddsb, var, reg) +#define paddsb_r2r(regs, regd) mmx_r2r(paddsb, regs, regd) +#define paddsb(vars, vard) mmx_m2m(paddsb, vars, vard) + + +/* 4x16 and 8x8 Parallel ADDs using Unsigned Saturation arithmetic +*/ +#define paddusw_m2r(var, reg) mmx_m2r(paddusw, var, reg) +#define paddusw_r2r(regs, regd) mmx_r2r(paddusw, regs, regd) +#define paddusw(vars, vard) mmx_m2m(paddusw, vars, vard) + +#define paddusb_m2r(var, reg) mmx_m2r(paddusb, var, reg) +#define paddusb_r2r(regs, regd) mmx_r2r(paddusb, regs, regd) +#define paddusb(vars, vard) mmx_m2m(paddusb, vars, vard) + + +/* 2x32, 4x16, and 8x8 Parallel SUBs +*/ +#define psubd_m2r(var, reg) mmx_m2r(psubd, var, reg) +#define psubd_r2r(regs, regd) mmx_r2r(psubd, regs, regd) +#define psubd(vars, vard) mmx_m2m(psubd, vars, vard) + +#define psubw_m2r(var, reg) mmx_m2r(psubw, var, reg) +#define psubw_r2r(regs, regd) mmx_r2r(psubw, regs, regd) +#define psubw(vars, vard) mmx_m2m(psubw, vars, vard) + +#define psubb_m2r(var, reg) mmx_m2r(psubb, var, reg) +#define psubb_r2r(regs, regd) mmx_r2r(psubb, regs, regd) +#define psubb(vars, vard) mmx_m2m(psubb, vars, vard) + + +/* 4x16 and 8x8 Parallel SUBs using Saturation arithmetic +*/ +#define psubsw_m2r(var, reg) mmx_m2r(psubsw, var, reg) +#define psubsw_r2r(regs, regd) mmx_r2r(psubsw, regs, regd) +#define psubsw(vars, vard) mmx_m2m(psubsw, vars, vard) + +#define psubsb_m2r(var, reg) mmx_m2r(psubsb, var, reg) +#define psubsb_r2r(regs, regd) mmx_r2r(psubsb, regs, regd) +#define psubsb(vars, vard) mmx_m2m(psubsb, vars, vard) + + +/* 4x16 and 8x8 Parallel SUBs using Unsigned Saturation arithmetic +*/ +#define psubusw_m2r(var, reg) mmx_m2r(psubusw, var, reg) +#define psubusw_r2r(regs, regd) mmx_r2r(psubusw, regs, regd) +#define psubusw(vars, vard) mmx_m2m(psubusw, vars, vard) + +#define psubusb_m2r(var, reg) mmx_m2r(psubusb, var, reg) +#define psubusb_r2r(regs, regd) mmx_r2r(psubusb, regs, regd) +#define psubusb(vars, vard) mmx_m2m(psubusb, vars, vard) + + +/* 4x16 Parallel MULs giving Low 4x16 portions of results +*/ +#define pmullw_m2r(var, reg) mmx_m2r(pmullw, var, reg) +#define pmullw_r2r(regs, regd) mmx_r2r(pmullw, regs, regd) +#define pmullw(vars, vard) mmx_m2m(pmullw, vars, vard) + + +/* 4x16 Parallel MULs giving High 4x16 portions of results +*/ +#define pmulhw_m2r(var, reg) mmx_m2r(pmulhw, var, reg) +#define pmulhw_r2r(regs, regd) mmx_r2r(pmulhw, regs, regd) +#define pmulhw(vars, vard) mmx_m2m(pmulhw, vars, vard) + + +/* 4x16->2x32 Parallel Mul-ADD + (muls like pmullw, then adds adjacent 16-bit fields + in the multiply result to make the final 2x32 result) +*/ +#define pmaddwd_m2r(var, reg) mmx_m2r(pmaddwd, var, reg) +#define pmaddwd_r2r(regs, regd) mmx_r2r(pmaddwd, regs, regd) +#define pmaddwd(vars, vard) mmx_m2m(pmaddwd, vars, vard) + + +/* 1x64 bitwise AND +*/ +#ifdef BROKEN_PAND +#define pand_m2r(var, reg) \ + { \ + mmx_m2r(pandn, (mmx_t) -1LL, reg); \ + mmx_m2r(pandn, var, reg); \ + } +#define pand_r2r(regs, regd) \ + { \ + mmx_m2r(pandn, (mmx_t) -1LL, regd); \ + mmx_r2r(pandn, regs, regd) \ + } +#define pand(vars, vard) \ + { \ + movq_m2r(vard, mm0); \ + mmx_m2r(pandn, (mmx_t) -1LL, mm0); \ + mmx_m2r(pandn, vars, mm0); \ + movq_r2m(mm0, vard); \ + } +#else +#define pand_m2r(var, reg) mmx_m2r(pand, var, reg) +#define pand_r2r(regs, regd) mmx_r2r(pand, regs, regd) +#define pand(vars, vard) mmx_m2m(pand, vars, vard) +#endif + + +/* 1x64 bitwise AND with Not the destination +*/ +#define pandn_m2r(var, reg) mmx_m2r(pandn, var, reg) +#define pandn_r2r(regs, regd) mmx_r2r(pandn, regs, regd) +#define pandn(vars, vard) mmx_m2m(pandn, vars, vard) + + +/* 1x64 bitwise OR +*/ +#define por_m2r(var, reg) mmx_m2r(por, var, reg) +#define por_r2r(regs, regd) mmx_r2r(por, regs, regd) +#define por(vars, vard) mmx_m2m(por, vars, vard) + + +/* 1x64 bitwise eXclusive OR +*/ +#define pxor_m2r(var, reg) mmx_m2r(pxor, var, reg) +#define pxor_r2r(regs, regd) mmx_r2r(pxor, regs, regd) +#define pxor(vars, vard) mmx_m2m(pxor, vars, vard) + + +/* 2x32, 4x16, and 8x8 Parallel CoMPare for EQuality + (resulting fields are either 0 or -1) +*/ +#define pcmpeqd_m2r(var, reg) mmx_m2r(pcmpeqd, var, reg) +#define pcmpeqd_r2r(regs, regd) mmx_r2r(pcmpeqd, regs, regd) +#define pcmpeqd(vars, vard) mmx_m2m(pcmpeqd, vars, vard) + +#define pcmpeqw_m2r(var, reg) mmx_m2r(pcmpeqw, var, reg) +#define pcmpeqw_r2r(regs, regd) mmx_r2r(pcmpeqw, regs, regd) +#define pcmpeqw(vars, vard) mmx_m2m(pcmpeqw, vars, vard) + +#define pcmpeqb_m2r(var, reg) mmx_m2r(pcmpeqb, var, reg) +#define pcmpeqb_r2r(regs, regd) mmx_r2r(pcmpeqb, regs, regd) +#define pcmpeqb(vars, vard) mmx_m2m(pcmpeqb, vars, vard) + + +/* 2x32, 4x16, and 8x8 Parallel CoMPare for Greater Than + (resulting fields are either 0 or -1) +*/ +#define pcmpgtd_m2r(var, reg) mmx_m2r(pcmpgtd, var, reg) +#define pcmpgtd_r2r(regs, regd) mmx_r2r(pcmpgtd, regs, regd) +#define pcmpgtd(vars, vard) mmx_m2m(pcmpgtd, vars, vard) + +#define pcmpgtw_m2r(var, reg) mmx_m2r(pcmpgtw, var, reg) +#define pcmpgtw_r2r(regs, regd) mmx_r2r(pcmpgtw, regs, regd) +#define pcmpgtw(vars, vard) mmx_m2m(pcmpgtw, vars, vard) + +#define pcmpgtb_m2r(var, reg) mmx_m2r(pcmpgtb, var, reg) +#define pcmpgtb_r2r(regs, regd) mmx_r2r(pcmpgtb, regs, regd) +#define pcmpgtb(vars, vard) mmx_m2m(pcmpgtb, vars, vard) + + +/* 1x64, 2x32, and 4x16 Parallel Shift Left Logical +*/ +#define psllq_i2r(imm, reg) mmx_i2r(psllq, imm, reg) +#define psllq_m2r(var, reg) mmx_m2r(psllq, var, reg) +#define psllq_r2r(regs, regd) mmx_r2r(psllq, regs, regd) +#define psllq(vars, vard) mmx_m2m(psllq, vars, vard) + +#define pslld_i2r(imm, reg) mmx_i2r(pslld, imm, reg) +#define pslld_m2r(var, reg) mmx_m2r(pslld, var, reg) +#define pslld_r2r(regs, regd) mmx_r2r(pslld, regs, regd) +#define pslld(vars, vard) mmx_m2m(pslld, vars, vard) + +#define psllw_i2r(imm, reg) mmx_i2r(psllw, imm, reg) +#define psllw_m2r(var, reg) mmx_m2r(psllw, var, reg) +#define psllw_r2r(regs, regd) mmx_r2r(psllw, regs, regd) +#define psllw(vars, vard) mmx_m2m(psllw, vars, vard) + + +/* 1x64, 2x32, and 4x16 Parallel Shift Right Logical +*/ +#define psrlq_i2r(imm, reg) mmx_i2r(psrlq, imm, reg) +#define psrlq_m2r(var, reg) mmx_m2r(psrlq, var, reg) +#define psrlq_r2r(regs, regd) mmx_r2r(psrlq, regs, regd) +#define psrlq(vars, vard) mmx_m2m(psrlq, vars, vard) + +#define psrld_i2r(imm, reg) mmx_i2r(psrld, imm, reg) +#define psrld_m2r(var, reg) mmx_m2r(psrld, var, reg) +#define psrld_r2r(regs, regd) mmx_r2r(psrld, regs, regd) +#define psrld(vars, vard) mmx_m2m(psrld, vars, vard) + +#define psrlw_i2r(imm, reg) mmx_i2r(psrlw, imm, reg) +#define psrlw_m2r(var, reg) mmx_m2r(psrlw, var, reg) +#define psrlw_r2r(regs, regd) mmx_r2r(psrlw, regs, regd) +#define psrlw(vars, vard) mmx_m2m(psrlw, vars, vard) + + +/* 2x32 and 4x16 Parallel Shift Right Arithmetic +*/ +#define psrad_i2r(imm, reg) mmx_i2r(psrad, imm, reg) +#define psrad_m2r(var, reg) mmx_m2r(psrad, var, reg) +#define psrad_r2r(regs, regd) mmx_r2r(psrad, regs, regd) +#define psrad(vars, vard) mmx_m2m(psrad, vars, vard) + +#define psraw_i2r(imm, reg) mmx_i2r(psraw, imm, reg) +#define psraw_m2r(var, reg) mmx_m2r(psraw, var, reg) +#define psraw_r2r(regs, regd) mmx_r2r(psraw, regs, regd) +#define psraw(vars, vard) mmx_m2m(psraw, vars, vard) + + +/* 2x32->4x16 and 4x16->8x8 PACK and Signed Saturate + (packs source and dest fields into dest in that order) +*/ +#define packssdw_m2r(var, reg) mmx_m2r(packssdw, var, reg) +#define packssdw_r2r(regs, regd) mmx_r2r(packssdw, regs, regd) +#define packssdw(vars, vard) mmx_m2m(packssdw, vars, vard) + +#define packsswb_m2r(var, reg) mmx_m2r(packsswb, var, reg) +#define packsswb_r2r(regs, regd) mmx_r2r(packsswb, regs, regd) +#define packsswb(vars, vard) mmx_m2m(packsswb, vars, vard) + + +/* 4x16->8x8 PACK and Unsigned Saturate + (packs source and dest fields into dest in that order) +*/ +#define packuswb_m2r(var, reg) mmx_m2r(packuswb, var, reg) +#define packuswb_r2r(regs, regd) mmx_r2r(packuswb, regs, regd) +#define packuswb(vars, vard) mmx_m2m(packuswb, vars, vard) + + +/* 2x32->1x64, 4x16->2x32, and 8x8->4x16 UNPaCK Low + (interleaves low half of dest with low half of source + as padding in each result field) +*/ +#define punpckldq_m2r(var, reg) mmx_m2r(punpckldq, var, reg) +#define punpckldq_r2r(regs, regd) mmx_r2r(punpckldq, regs, regd) +#define punpckldq(vars, vard) mmx_m2m(punpckldq, vars, vard) + +#define punpcklwd_m2r(var, reg) mmx_m2r(punpcklwd, var, reg) +#define punpcklwd_r2r(regs, regd) mmx_r2r(punpcklwd, regs, regd) +#define punpcklwd(vars, vard) mmx_m2m(punpcklwd, vars, vard) + +#define punpcklbw_m2r(var, reg) mmx_m2r(punpcklbw, var, reg) +#define punpcklbw_r2r(regs, regd) mmx_r2r(punpcklbw, regs, regd) +#define punpcklbw(vars, vard) mmx_m2m(punpcklbw, vars, vard) + + +/* 2x32->1x64, 4x16->2x32, and 8x8->4x16 UNPaCK High + (interleaves high half of dest with high half of source + as padding in each result field) +*/ +#define punpckhdq_m2r(var, reg) mmx_m2r(punpckhdq, var, reg) +#define punpckhdq_r2r(regs, regd) mmx_r2r(punpckhdq, regs, regd) +#define punpckhdq(vars, vard) mmx_m2m(punpckhdq, vars, vard) + +#define punpckhwd_m2r(var, reg) mmx_m2r(punpckhwd, var, reg) +#define punpckhwd_r2r(regs, regd) mmx_r2r(punpckhwd, regs, regd) +#define punpckhwd(vars, vard) mmx_m2m(punpckhwd, vars, vard) + +#define punpckhbw_m2r(var, reg) mmx_m2r(punpckhbw, var, reg) +#define punpckhbw_r2r(regs, regd) mmx_r2r(punpckhbw, regs, regd) +#define punpckhbw(vars, vard) mmx_m2m(punpckhbw, vars, vard) + + +/* Empty MMx State + (used to clean-up when going from mmx to float use + of the registers that are shared by both; note that + there is no float-to-mmx operation needed, because + only the float tag word info is corruptible) +*/ +#ifdef MMX_TRACE + +#define emms() \ + { \ + printf("emms()\n"); \ + __asm__ __volatile__ ("emms"); \ + } + +#else + +#define emms() __asm__ __volatile__ ("emms") + +#endif + +#endif + diff --git a/3rdparty/SDL/src/video/nanox/SDL_nxevents.c b/3rdparty/SDL/src/video/nanox/SDL_nxevents.c new file mode 100644 index 0000000..788c794 --- /dev/null +++ b/3rdparty/SDL/src/video/nanox/SDL_nxevents.c @@ -0,0 +1,382 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + Copyright (C) 2001 Hsieh-Fu Tsai + Copyright (C) 2002 Greg Haerr <greg@censoft.com> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Sam Lantinga + slouken@libsdl.org + + Hsieh-Fu Tsai + clare@setabox.com +*/ +#include "SDL_config.h" + +#include "SDL_keysym.h" +#include "../../events/SDL_events_c.h" + +#include "SDL_nxevents_c.h" +#include "SDL_nximage_c.h" + +// The translation tables from a nanox keysym to a SDL keysym +static SDLKey NX_NONASCII_keymap [MWKEY_LAST + 1] ; + +void NX_InitOSKeymap (_THIS) +{ + int i ; + + Dprintf ("enter NX_InitOSKeymap\n") ; + + // Map the nanox scancodes to SDL keysyms + for (i = 0; i < SDL_arraysize (NX_NONASCII_keymap); ++ i) + NX_NONASCII_keymap [i] = SDLK_UNKNOWN ; + + NX_NONASCII_keymap [MWKEY_LEFT & 0xFF] = SDLK_LEFT ; + NX_NONASCII_keymap [MWKEY_RIGHT & 0xFF] = SDLK_RIGHT ; + NX_NONASCII_keymap [MWKEY_UP & 0xFF] = SDLK_UP ; + NX_NONASCII_keymap [MWKEY_DOWN & 0xFF] = SDLK_DOWN ; + NX_NONASCII_keymap [MWKEY_INSERT & 0xFF] = SDLK_INSERT ; + NX_NONASCII_keymap [MWKEY_DELETE & 0xFF] = SDLK_DELETE ; + NX_NONASCII_keymap [MWKEY_HOME & 0xFF] = SDLK_HOME ; + NX_NONASCII_keymap [MWKEY_END & 0xFF] = SDLK_END ; + NX_NONASCII_keymap [MWKEY_PAGEUP & 0xFF] = SDLK_PAGEUP ; + NX_NONASCII_keymap [MWKEY_PAGEDOWN & 0xFF] = SDLK_PAGEDOWN ; + + NX_NONASCII_keymap [MWKEY_KP0 & 0xFF] = SDLK_KP0 ; + NX_NONASCII_keymap [MWKEY_KP1 & 0xFF] = SDLK_KP1 ; + NX_NONASCII_keymap [MWKEY_KP2 & 0xFF] = SDLK_KP2 ; + NX_NONASCII_keymap [MWKEY_KP3 & 0xFF] = SDLK_KP3 ; + NX_NONASCII_keymap [MWKEY_KP4 & 0xFF] = SDLK_KP4 ; + NX_NONASCII_keymap [MWKEY_KP5 & 0xFF] = SDLK_KP5 ; + NX_NONASCII_keymap [MWKEY_KP6 & 0xFF] = SDLK_KP6 ; + NX_NONASCII_keymap [MWKEY_KP7 & 0xFF] = SDLK_KP7 ; + NX_NONASCII_keymap [MWKEY_KP8 & 0xFF] = SDLK_KP8 ; + NX_NONASCII_keymap [MWKEY_KP9 & 0xFF] = SDLK_KP9 ; + NX_NONASCII_keymap [MWKEY_KP_PERIOD & 0xFF] = SDLK_KP_PERIOD ; + NX_NONASCII_keymap [MWKEY_KP_DIVIDE & 0xFF] = SDLK_KP_DIVIDE ; + NX_NONASCII_keymap [MWKEY_KP_MULTIPLY & 0xFF] = SDLK_KP_MULTIPLY ; + NX_NONASCII_keymap [MWKEY_KP_MINUS & 0xFF] = SDLK_KP_MINUS ; + NX_NONASCII_keymap [MWKEY_KP_PLUS & 0xFF] = SDLK_KP_PLUS ; + NX_NONASCII_keymap [MWKEY_KP_ENTER & 0xFF] = SDLK_KP_ENTER ; + NX_NONASCII_keymap [MWKEY_KP_EQUALS & 0xFF] = SDLK_KP_EQUALS ; + + NX_NONASCII_keymap [MWKEY_F1 & 0xFF] = SDLK_F1 ; + NX_NONASCII_keymap [MWKEY_F2 & 0xFF] = SDLK_F2 ; + NX_NONASCII_keymap [MWKEY_F3 & 0xFF] = SDLK_F3 ; + NX_NONASCII_keymap [MWKEY_F4 & 0xFF] = SDLK_F4 ; + NX_NONASCII_keymap [MWKEY_F5 & 0xFF] = SDLK_F5 ; + NX_NONASCII_keymap [MWKEY_F6 & 0xFF] = SDLK_F6 ; + NX_NONASCII_keymap [MWKEY_F7 & 0xFF] = SDLK_F7 ; + NX_NONASCII_keymap [MWKEY_F8 & 0xFF] = SDLK_F8 ; + NX_NONASCII_keymap [MWKEY_F9 & 0xFF] = SDLK_F9 ; + NX_NONASCII_keymap [MWKEY_F10 & 0xFF] = SDLK_F10 ; + NX_NONASCII_keymap [MWKEY_F11 & 0xFF] = SDLK_F11 ; + NX_NONASCII_keymap [MWKEY_F12 & 0xFF] = SDLK_F12 ; + + NX_NONASCII_keymap [MWKEY_NUMLOCK & 0xFF] = SDLK_NUMLOCK ; + NX_NONASCII_keymap [MWKEY_CAPSLOCK & 0xFF] = SDLK_CAPSLOCK ; + NX_NONASCII_keymap [MWKEY_SCROLLOCK & 0xFF] = SDLK_SCROLLOCK ; + NX_NONASCII_keymap [MWKEY_LSHIFT & 0xFF] = SDLK_LSHIFT ; + NX_NONASCII_keymap [MWKEY_RSHIFT & 0xFF] = SDLK_RSHIFT ; + NX_NONASCII_keymap [MWKEY_LCTRL & 0xFF] = SDLK_LCTRL ; + NX_NONASCII_keymap [MWKEY_RCTRL & 0xFF] = SDLK_RCTRL ; + NX_NONASCII_keymap [MWKEY_LALT & 0xFF] = SDLK_LALT ; + NX_NONASCII_keymap [MWKEY_RALT & 0xFF] = SDLK_RALT ; + NX_NONASCII_keymap [MWKEY_LMETA & 0xFF] = SDLK_LMETA ; + NX_NONASCII_keymap [MWKEY_RMETA & 0xFF] = SDLK_RMETA ; + NX_NONASCII_keymap [MWKEY_ALTGR & 0xFF] = SDLK_MODE ; + + NX_NONASCII_keymap [MWKEY_PRINT & 0xFF] = SDLK_PRINT ; + NX_NONASCII_keymap [MWKEY_SYSREQ & 0xFF] = SDLK_SYSREQ ; + NX_NONASCII_keymap [MWKEY_PAUSE & 0xFF] = SDLK_PAUSE ; + NX_NONASCII_keymap [MWKEY_BREAK & 0xFF] = SDLK_BREAK ; + NX_NONASCII_keymap [MWKEY_MENU & 0xFF] = SDLK_MENU ; + + Dprintf ("leave NX_InitOSKeymap\n") ; +} + +SDL_keysym * NX_TranslateKey (GR_EVENT_KEYSTROKE * keystroke, SDL_keysym * keysym) +{ + GR_KEY ch = keystroke -> ch ; + + Dprintf ("enter NX_TranslateKey\n") ; + + keysym -> scancode = keystroke -> scancode ; + keysym -> sym = SDLK_UNKNOWN ; + + if (ch & MWKEY_NONASCII_MASK) { + keysym -> sym = NX_NONASCII_keymap [ch & 0xFF] ; + } else { + keysym -> sym = ch & 0x7F ; + } + + keysym -> mod = KMOD_NONE ; + +#if 1 // Retrieve more mode information + { + GR_KEYMOD mod = keystroke -> modifiers ; + + if (mod & MWKMOD_LSHIFT) + keysym -> mod |= KMOD_LSHIFT ; + if (mod & MWKMOD_RSHIFT) + keysym -> mod |= KMOD_RSHIFT ; + if (mod & MWKMOD_LCTRL) + keysym -> mod |= KMOD_LCTRL ; + if (mod & MWKMOD_RCTRL) + keysym -> mod |= KMOD_RCTRL ; + if (mod & MWKMOD_LALT) + keysym -> mod |= KMOD_LALT ; + if (mod & MWKMOD_RALT) + keysym -> mod |= KMOD_RALT ; + if (mod & MWKMOD_LMETA) + keysym -> mod |= KMOD_LMETA ; + if (mod & MWKMOD_RMETA) + keysym -> mod |= KMOD_RMETA ; + if (mod & MWKMOD_NUM) + keysym -> mod |= KMOD_NUM ; + if (mod & MWKMOD_CAPS) + keysym -> mod |= KMOD_CAPS ; + if (mod & MWKMOD_ALTGR) + keysym -> mod |= KMOD_MODE ; + } +#endif + + keysym -> unicode = ch ; + + Dprintf ("leave NX_TranslateKey\n") ; + return keysym ; +} + +static int check_boundary (_THIS, int x, int y) +{ + if (x < OffsetX || y < OffsetY || x > OffsetX + this -> screen -> w || + y > OffsetY + this -> screen -> h) + return 0 ; + + return 1 ; +} + +void NX_PumpEvents (_THIS) +{ + GR_EVENT event ; + static GR_BUTTON last_button_down = 0 ; + + GrCheckNextEvent (& event) ; + while (event.type != GR_EVENT_TYPE_NONE) { + + // dispatch event + switch (event.type) { + case GR_EVENT_TYPE_MOUSE_ENTER : + { + Dprintf ("mouse enter\n") ; + SDL_PrivateAppActive (1, SDL_APPMOUSEFOCUS) ; + break ; + } + + case GR_EVENT_TYPE_MOUSE_EXIT : + { + Dprintf ("mouse exit\n") ; + SDL_PrivateAppActive (0, SDL_APPMOUSEFOCUS) ; + break ; + } + + case GR_EVENT_TYPE_FOCUS_IN : + { + Dprintf ("focus in\n") ; + SDL_PrivateAppActive (1, SDL_APPINPUTFOCUS) ; + break ; + } + + case GR_EVENT_TYPE_FOCUS_OUT : + { + Dprintf ("focus out\n") ; + SDL_PrivateAppActive (0, SDL_APPINPUTFOCUS) ; + break ; + } + + case GR_EVENT_TYPE_MOUSE_MOTION : + { + Dprintf ("mouse motion\n") ; + + if (SDL_VideoSurface) { + if (currently_fullscreen) { + if (check_boundary (this, event.button.x, event.button.y)) { + SDL_PrivateMouseMotion (0, 0, event.button.x - OffsetX, + event.button.y - OffsetY) ; + } + } else { + SDL_PrivateMouseMotion (0, 0, event.button.x, event.button.y) ; + } + } + break ; + } + + case GR_EVENT_TYPE_BUTTON_DOWN : + { + int button = event.button.buttons ; + + Dprintf ("button down\n") ; + + switch (button) { + case MWBUTTON_L : + button = 1 ; + break ; + case MWBUTTON_M : + button = 2 ; + break ; + case MWBUTTON_R : + button = 3 ; + break ; + default : + button = 0 ; + } + last_button_down = button ; + + if (currently_fullscreen) { + if (check_boundary (this, event.button.x, event.button.y)) { + SDL_PrivateMouseButton (SDL_PRESSED, button, + event.button.x - OffsetX, event.button.y - OffsetY) ; + } + } else { + SDL_PrivateMouseButton (SDL_PRESSED, button, + event.button.x, event.button.y) ; + } + break ; + } + + // do not konw which button is released + case GR_EVENT_TYPE_BUTTON_UP : + { + Dprintf ("button up\n") ; + + if (currently_fullscreen) { + if (check_boundary (this, event.button.x, event.button.y)) { + SDL_PrivateMouseButton (SDL_RELEASED, last_button_down, + event.button.x - OffsetX, event.button.y - OffsetY) ; + } + } else { + SDL_PrivateMouseButton (SDL_RELEASED, last_button_down, + event.button.x, event.button.y) ; + } + last_button_down = 0 ; + break ; + } + + case GR_EVENT_TYPE_KEY_DOWN : + { + SDL_keysym keysym ; + + Dprintf ("key down\n") ; + SDL_PrivateKeyboard (SDL_PRESSED, + NX_TranslateKey (& event.keystroke, & keysym)) ; + break ; + } + + case GR_EVENT_TYPE_KEY_UP : + { + SDL_keysym keysym ; + + Dprintf ("key up\n") ; + SDL_PrivateKeyboard (SDL_RELEASED, + NX_TranslateKey (& event.keystroke, & keysym)) ; + break ; + } + + case GR_EVENT_TYPE_CLOSE_REQ : + { + Dprintf ("close require\n") ; + SDL_PrivateQuit () ; + break ; + } + + case GR_EVENT_TYPE_EXPOSURE : + { + Dprintf ("event_type_exposure\n") ; + if (SDL_VideoSurface) { + NX_RefreshDisplay (this) ;//, & event.exposure) ; + } + break ; + } + + case GR_EVENT_TYPE_UPDATE : + { + switch (event.update.utype) { + case GR_UPDATE_MAP : + { + Dprintf ("GR_UPDATE_MAP\n") ; + // If we're not active, make ourselves active + if (!(SDL_GetAppState () & SDL_APPACTIVE)) { + // Send an internal activate event + SDL_PrivateAppActive (1, SDL_APPACTIVE) ; + } + if (SDL_VideoSurface) { + NX_RefreshDisplay (this) ; + } + break ; + } + + case GR_UPDATE_UNMAP : + case GR_UPDATE_UNMAPTEMP : + { + Dprintf ("GR_UPDATE_UNMAP or GR_UPDATE_UNMAPTEMP\n") ; + // If we're active, make ourselves inactive + if (SDL_GetAppState () & SDL_APPACTIVE) { + // Send an internal deactivate event + SDL_PrivateAppActive (0, SDL_APPACTIVE | SDL_APPINPUTFOCUS) ; + } + break ; + } + + case GR_UPDATE_SIZE : + { + Dprintf ("GR_UPDATE_SIZE\n") ; + SDL_PrivateResize (event.update.width, event.update.height) ; + break ; + } + + case GR_UPDATE_MOVE : + case GR_UPDATE_REPARENT : + { + Dprintf ("GR_UPDATE_MOVE or GR_UPDATE_REPARENT\n") ; +#ifdef ENABLE_NANOX_DIRECT_FB + if (Clientfb) { + /* Get current window position and fb pointer*/ + if (currently_fullscreen) + GrGetWindowFBInfo(FSwindow, &fbinfo); + else + GrGetWindowFBInfo(SDL_Window, &fbinfo); + } +#endif + break ; + } + + default : + Dprintf ("unknown GR_EVENT_TYPE_UPDATE\n") ; + break ; + } + break ; + } + + default : + { + Dprintf ("pump event default\n") ; + } + } + + GrCheckNextEvent (& event) ; + } +} diff --git a/3rdparty/SDL/src/video/nanox/SDL_nxevents_c.h b/3rdparty/SDL/src/video/nanox/SDL_nxevents_c.h new file mode 100644 index 0000000..b3b4f97 --- /dev/null +++ b/3rdparty/SDL/src/video/nanox/SDL_nxevents_c.h @@ -0,0 +1,32 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + Copyright (C) 2001 Hsieh-Fu Tsai + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Sam Lantinga + slouken@libsdl.org + + Hsieh-Fu Tsai + clare@setabox.com +*/ +#include "SDL_config.h" + +#include "SDL_nxvideo.h" + +// Functions to be exported +extern void NX_InitOSKeymap (_THIS) ; +extern void NX_PumpEvents (_THIS) ; diff --git a/3rdparty/SDL/src/video/nanox/SDL_nximage.c b/3rdparty/SDL/src/video/nanox/SDL_nximage.c new file mode 100644 index 0000000..23d3157 --- /dev/null +++ b/3rdparty/SDL/src/video/nanox/SDL_nximage.c @@ -0,0 +1,230 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + Copyright (C) 2001 Hsieh-Fu Tsai + Copyright (C) 2002 Greg Haerr <greg@censoft.com> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Sam Lantinga + slouken@libsdl.org + + Hsieh-Fu Tsai + clare@setabox.com +*/ +#include "SDL_config.h" + +#include "SDL_nximage_c.h" + +void NX_NormalUpdate (_THIS, int numrects, SDL_Rect * rects) +{ + int i, j, xinc, yinc, destinc, rowinc ; + int x, y, w, h ; + unsigned char * src = NULL, * dest = NULL ; + + Dprintf ("enter NX_NormalUpdate\n") ; + + /* These are the values for the incoming image */ + xinc = this -> screen -> format -> BytesPerPixel ; + yinc = this -> screen -> pitch ; + + for (i = 0; i < numrects; ++ i) { + x = rects [i].x, y = rects [i].y ; + w = rects [i].w, h = rects [i].h ; + src = SDL_Image + y * yinc + x * xinc ; +#ifdef ENABLE_NANOX_DIRECT_FB + if (Clientfb) { + if (currently_fullscreen) + dest = fbinfo.winpixels + (((y+OffsetY) * fbinfo.pitch) + + ((x+OffsetX) * fbinfo.bytespp)); + else + dest = fbinfo.winpixels + ((y * fbinfo.pitch) + (x * fbinfo.bytespp)); + destinc = fbinfo.pitch; + } + else +#endif + { + dest = Image_buff ; + destinc = w * xinc ; + } + rowinc = w * xinc; + + // apply GammaRamp table + if ((pixel_type == MWPF_TRUECOLOR0888 || pixel_type == MWPF_TRUECOLOR888) + && GammaRamp_R && GammaRamp_G && GammaRamp_B) { + Uint8 * ptrsrc ; + Uint8 * ptrdst ; + int k ; + + for (j = h; j > 0; -- j, src += yinc, dest += destinc) { + ptrsrc = src ; + ptrdst = dest ; + for (k = w; k > 0; -- k) { + *ptrdst++ = GammaRamp_B [*ptrsrc++] >> 8; + *ptrdst++ = GammaRamp_G [*ptrsrc++] >> 8; + *ptrdst++ = GammaRamp_R [*ptrsrc++] >> 8; + *ptrdst++ = 0; + ++ptrsrc; + } + } + } +#if 1 /* This is needed for microwindows 0.90 or older */ + else if (pixel_type == MWPF_TRUECOLOR0888 || pixel_type == MWPF_TRUECOLOR888) { + Uint8 * ptrsrc ; + Uint8 * ptrdst ; + int k ; + + for (j = h; j > 0; -- j, src += yinc, dest += destinc) { + ptrsrc = src ; + ptrdst = dest ; + for (k = w; k > 0; -- k) { + *ptrdst++ = *ptrsrc++; + *ptrdst++ = *ptrsrc++; + *ptrdst++ = *ptrsrc++; + *ptrdst++ = 0; + ++ptrsrc; + } + } + } +#endif + else + { + for (j = h; j > 0; -- j, src += yinc, dest += destinc) + SDL_memcpy (dest, src, rowinc) ; + } + if (!Clientfb) { + if (currently_fullscreen) { + GrArea (FSwindow, SDL_GC, x + OffsetX, y + OffsetY, w, h, Image_buff, + pixel_type) ; + } else { + GrArea (SDL_Window, SDL_GC, x, y, w, h, Image_buff, pixel_type) ; + } + } + } + GrFlush(); + + Dprintf ("leave NX_NormalUpdate\n") ; +} + +int NX_SetupImage (_THIS, SDL_Surface * screen) +{ + int size = screen -> h * screen -> pitch ; + + Dprintf ("enter NX_SetupImage\n") ; + + screen -> pixels = (void *) SDL_malloc (size) ; + + if (!Clientfb) { + Image_buff = (unsigned char *) SDL_malloc (size) ; + if (screen -> pixels == NULL || Image_buff == NULL) { + SDL_free (screen -> pixels) ; + SDL_free (Image_buff) ; + SDL_OutOfMemory () ; + return -1 ; + } + } + + SDL_Image = (unsigned char *) screen -> pixels ; + + this -> UpdateRects = NX_NormalUpdate ; + + Dprintf ("leave NX_SetupImage\n") ; + return 0 ; +} + +void NX_DestroyImage (_THIS, SDL_Surface * screen) +{ + Dprintf ("enter NX_DestroyImage\n") ; + + if (SDL_Image) SDL_free (SDL_Image) ; + if (Image_buff) SDL_free (Image_buff) ; + if (screen) screen -> pixels = NULL ; + + Dprintf ("leave NX_DestroyImage\n") ; +} + +int NX_ResizeImage (_THIS, SDL_Surface * screen, Uint32 flags) +{ + int retval ; + GR_SCREEN_INFO si ; + + Dprintf ("enter NX_ResizeImage\n") ; + + NX_DestroyImage (this, screen) ; + retval = NX_SetupImage (this, screen) ; + + GrGetScreenInfo (& si) ; + OffsetX = (si.cols - screen -> w) / 2 ; + OffsetY = (si.rows - screen -> h) / 2 ; + +#ifdef ENABLE_NANOX_DIRECT_FB + if (Clientfb) { + /* Get current window position and fb pointer*/ + if (currently_fullscreen) + GrGetWindowFBInfo(FSwindow, &fbinfo); + else + GrGetWindowFBInfo(SDL_Window, &fbinfo); + } +#endif + Dprintf ("leave NX_ResizeImage\n") ; + return retval ; +} + +void NX_RefreshDisplay (_THIS) +{ + Dprintf ("enter NX_RefreshDisplay\n") ; + + // Don't refresh a display that doesn't have an image (like GL) + if (! SDL_Image) { + return; + } + +#ifdef ENABLE_NANOX_DIRECT_FB + if (Clientfb) { + int j; + char *src, *dest = NULL; + int xinc, yinc, rowinc; + + GrGetWindowFBInfo(SDL_Window, &fbinfo); + + xinc = this -> screen -> format -> BytesPerPixel ; + yinc = this -> screen -> pitch ; + + src = SDL_Image; + if (currently_fullscreen) + dest = fbinfo.winpixels + ((OffsetY * fbinfo.pitch) + + (OffsetX * fbinfo.bytespp)); + else + dest = fbinfo.winpixels; + rowinc = xinc * this -> screen -> w; + + for (j = this -> screen -> h; j > 0; -- j, src += yinc, dest += fbinfo.pitch) + SDL_memcpy (dest, src, rowinc) ; + } + else +#endif + { + if (currently_fullscreen) { + GrArea (FSwindow, SDL_GC, OffsetX, OffsetY, this -> screen -> w, + this -> screen -> h, SDL_Image, pixel_type) ; + } else { + GrArea (SDL_Window, SDL_GC, 0, 0, this -> screen -> w, + this -> screen -> h, SDL_Image, pixel_type) ; + } + } + GrFlush(); + + Dprintf ("leave NX_RefreshDisplay\n") ; +} diff --git a/3rdparty/SDL/src/video/nanox/SDL_nximage_c.h b/3rdparty/SDL/src/video/nanox/SDL_nximage_c.h new file mode 100644 index 0000000..0bf29e5 --- /dev/null +++ b/3rdparty/SDL/src/video/nanox/SDL_nximage_c.h @@ -0,0 +1,35 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + Copyright (C) 2001 Hsieh-Fu Tsai + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Sam Lantinga + slouken@libsdl.org + + Hsieh-Fu Tsai + clare@setabox.com +*/ +#include "SDL_config.h" + +#include "SDL_nxvideo.h" + +extern int NX_SetupImage (_THIS, SDL_Surface * screen) ; +extern void NX_DestroyImage (_THIS, SDL_Surface * screen) ; +extern int NX_ResizeImage (_THIS, SDL_Surface * screen, Uint32 flags) ; + +extern void NX_NormalUpdate (_THIS, int numrects, SDL_Rect * rects) ; +extern void NX_RefreshDisplay (_THIS) ; diff --git a/3rdparty/SDL/src/video/nanox/SDL_nxmodes.c b/3rdparty/SDL/src/video/nanox/SDL_nxmodes.c new file mode 100644 index 0000000..bcf74e5 --- /dev/null +++ b/3rdparty/SDL/src/video/nanox/SDL_nxmodes.c @@ -0,0 +1,84 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + Copyright (C) 2001 Hsieh-Fu Tsai + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Sam Lantinga + slouken@libsdl.org + + Hsieh-Fu Tsai + clare@setabox.com +*/ +#include "SDL_config.h" + +#include "SDL_stdinc.h" +#include "SDL_nxmodes_c.h" + +SDL_Rect ** NX_ListModes (_THIS, SDL_PixelFormat * format, Uint32 flags) +{ + if (flags & SDL_FULLSCREEN) + return SDL_modelist ; + + if (SDL_Visual.bpp == format -> BitsPerPixel) { + return ((SDL_Rect **) -1) ; + } else { + return ((SDL_Rect **) 0) ; + } +} + +void NX_FreeVideoModes (_THIS) +{ + int i ; + + if (SDL_modelist) { + for (i = 0; SDL_modelist [i]; ++ i) { + SDL_free (SDL_modelist [i]) ; + } + SDL_free (SDL_modelist) ; + SDL_modelist = NULL; + } +} + +int NX_EnterFullScreen (_THIS) +{ + if (! currently_fullscreen) { + GR_SCREEN_INFO si ; + + GrGetScreenInfo (& si) ; + GrResizeWindow (FSwindow, si.cols, si.rows) ; + GrUnmapWindow (SDL_Window) ; + GrMapWindow (FSwindow) ; + GrRaiseWindow (FSwindow) ; + GrSetFocus (FSwindow) ; + currently_fullscreen = 1 ; + } + + return 1 ; +} + +int NX_LeaveFullScreen (_THIS) +{ + if (currently_fullscreen) { + GrUnmapWindow (FSwindow) ; + GrMapWindow (SDL_Window) ; + GrRaiseWindow (SDL_Window) ; + GrSetFocus (SDL_Window) ; + currently_fullscreen = 0 ; + } + + return 0 ; +} diff --git a/3rdparty/SDL/src/video/nanox/SDL_nxmodes_c.h b/3rdparty/SDL/src/video/nanox/SDL_nxmodes_c.h new file mode 100644 index 0000000..fe2e655 --- /dev/null +++ b/3rdparty/SDL/src/video/nanox/SDL_nxmodes_c.h @@ -0,0 +1,34 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + Copyright (C) 2001 Hsieh-Fu Tsai + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Sam Lantinga + slouken@libsdl.org + + Hsieh-Fu Tsai + clare@setabox.com +*/ +#include "SDL_config.h" + +#include "SDL_nxvideo.h" +#include <SDL.h> + +extern SDL_Rect ** NX_ListModes (_THIS, SDL_PixelFormat * format, Uint32 flags) ; +extern void NX_FreeVideoModes (_THIS) ; +extern int NX_EnterFullScreen (_THIS) ; +extern int NX_LeaveFullScreen (_THIS) ; diff --git a/3rdparty/SDL/src/video/nanox/SDL_nxmouse.c b/3rdparty/SDL/src/video/nanox/SDL_nxmouse.c new file mode 100644 index 0000000..9c8f382 --- /dev/null +++ b/3rdparty/SDL/src/video/nanox/SDL_nxmouse.c @@ -0,0 +1,79 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + Copyright (C) 2001 Hsieh-Fu Tsai + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Sam Lantinga + slouken@libsdl.org + + Hsieh-Fu Tsai + clare@setabox.com +*/ +#include "SDL_config.h" + +#include "../../events/SDL_events_c.h" + +#include "SDL_nxmouse_c.h" + +// The implementation dependent data for the window manager cursor +struct WMcursor { + int unused ; +} ; + +WMcursor * NX_CreateWMCursor (_THIS, + Uint8 * data, Uint8 * mask, int w, int h, int hot_x, int hot_y) +{ + WMcursor * cursor ; + + Dprintf ("enter NX_CreateWMCursor\n") ; + + cursor = (WMcursor *) SDL_malloc (sizeof (WMcursor)) ; + if (cursor == NULL) { + SDL_OutOfMemory () ; + return NULL ; + } + + Dprintf ("leave NX_CreateWMCursor\n") ; + return cursor ; +} + +void NX_FreeWMCursor (_THIS, WMcursor * cursor) +{ + Dprintf ("NX_FreeWMCursor\n") ; + SDL_free (cursor) ; + return ; +} + +void NX_WarpWMCursor(_THIS, Uint16 x, Uint16 y) +{ + GR_WINDOW_INFO info ; + + Dprintf ("enter NX_WarpWMCursor\n") ; + SDL_Lock_EventThread () ; + + GrGetWindowInfo (SDL_Window, & info) ; + GrMoveCursor (info.x + x, info.y + y) ; + + SDL_Unlock_EventThread () ; + Dprintf ("leave NX_WarpWMCursor\n") ; +} + +int NX_ShowWMCursor (_THIS, WMcursor * cursor) +{ + Dprintf ("NX_ShowWMCursor\n") ; + return 1 ; +} diff --git a/3rdparty/SDL/src/video/nanox/SDL_nxmouse_c.h b/3rdparty/SDL/src/video/nanox/SDL_nxmouse_c.h new file mode 100644 index 0000000..d7fedb5 --- /dev/null +++ b/3rdparty/SDL/src/video/nanox/SDL_nxmouse_c.h @@ -0,0 +1,29 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#include "SDL_nxvideo.h" + +extern WMcursor * NX_CreateWMCursor (_THIS, Uint8 * data, Uint8 * mask, int w, int h, int hot_x, int hot_y) ; +void NX_FreeWMCursor (_THIS, WMcursor * cursor) ; +extern void NX_WarpWMCursor (_THIS, Uint16 x, Uint16 y) ; +extern int NX_ShowWMCursor (_THIS, WMcursor * cursor) ; diff --git a/3rdparty/SDL/src/video/nanox/SDL_nxvideo.c b/3rdparty/SDL/src/video/nanox/SDL_nxvideo.c new file mode 100644 index 0000000..b188e09 --- /dev/null +++ b/3rdparty/SDL/src/video/nanox/SDL_nxvideo.c @@ -0,0 +1,544 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + Copyright (C) 2001 Hsieh-Fu Tsai + Copyright (C) 2002 Greg Haerr <greg@censoft.com> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Sam Lantinga + slouken@libsdl.org + + Hsieh-Fu Tsai + clare@setabox.com +*/ +#include "SDL_config.h" + +#include "SDL_thread.h" +#include "SDL_video.h" +#include "../SDL_pixels_c.h" +#include "../../events/SDL_events_c.h" + +#define MWINCLUDECOLORS +#include "SDL_nxvideo.h" +#include "SDL_nxmodes_c.h" +#include "SDL_nxwm_c.h" +#include "SDL_nxmouse_c.h" +#include "SDL_nximage_c.h" +#include "SDL_nxevents_c.h" + +// Initialization/Query functions +static int NX_VideoInit (_THIS, SDL_PixelFormat * vformat) ; +static SDL_Surface * NX_SetVideoMode (_THIS, SDL_Surface * current, int width, int height, int bpp, Uint32 flags) ; +static int NX_SetColors (_THIS, int firstcolor, int ncolors, SDL_Color * colors) ; +static void NX_VideoQuit (_THIS) ; +static void NX_DestroyWindow (_THIS, SDL_Surface * screen) ; +static int NX_ToggleFullScreen (_THIS, int on) ; +static void NX_UpdateMouse (_THIS) ; +static int NX_SetGammaRamp (_THIS, Uint16 * ramp) ; +static int NX_GetGammaRamp (_THIS, Uint16 * ramp) ; + +// Microwin driver bootstrap functions +static int NX_Available () +{ + Dprintf ("enter NX_Available\n") ; + + if (GrOpen () < 0) return 0 ; + GrClose () ; + + Dprintf ("leave NX_Available\n") ; + return 1 ; +} + +static void NX_DeleteDevice (SDL_VideoDevice * device) +{ + Dprintf ("enter NX_DeleteDevice\n") ; + + if (device) { + if (device -> hidden) SDL_free (device -> hidden) ; + if (device -> gl_data) SDL_free (device -> gl_data) ; + SDL_free (device) ; + } + + Dprintf ("leave NX_DeleteDevice\n") ; +} + +static SDL_VideoDevice * NX_CreateDevice (int devindex) +{ + SDL_VideoDevice * device ; + + Dprintf ("enter NX_CreateDevice\n") ; + + // Initialize all variables that we clean on shutdown + device = (SDL_VideoDevice *) SDL_malloc (sizeof (SDL_VideoDevice)) ; + if (device) { + SDL_memset (device, 0, (sizeof * device)) ; + device -> hidden = (struct SDL_PrivateVideoData *) + SDL_malloc ((sizeof * device -> hidden)) ; + device -> gl_data = NULL ; + } + if ((device == NULL) || (device -> hidden == NULL)) { + SDL_OutOfMemory () ; + NX_DeleteDevice (device) ; + return 0 ; + } + SDL_memset (device -> hidden, 0, (sizeof * device -> hidden)) ; + + // Set the function pointers + device -> VideoInit = NX_VideoInit ; + device -> ListModes = NX_ListModes ; + device -> SetVideoMode = NX_SetVideoMode ; + device -> ToggleFullScreen = NX_ToggleFullScreen ; + device -> UpdateMouse = NX_UpdateMouse ; + device -> CreateYUVOverlay = NULL ; + device -> SetColors = NX_SetColors ; + device -> UpdateRects = NULL ; + device -> VideoQuit = NX_VideoQuit; + device -> AllocHWSurface = NULL ; + device -> CheckHWBlit = NULL ; + device -> FillHWRect = NULL ; + device -> SetHWColorKey = NULL ; + device -> SetHWAlpha = NULL ; + device -> LockHWSurface = NULL ; + device -> UnlockHWSurface = NULL ; + device -> FlipHWSurface = NULL ; + device -> FreeHWSurface = NULL ; + device -> SetGamma = NULL ; + device -> GetGamma = NULL ; + device -> SetGammaRamp = NX_SetGammaRamp ; + device -> GetGammaRamp = NX_GetGammaRamp ; + +#if SDL_VIDEO_OPENGL + device -> GL_LoadLibrary = NULL ; + device -> GL_GetProcAddress = NULL ; + device -> GL_GetAttribute = NULL ; + device -> GL_MakeCurrent = NULL ; + device -> GL_SwapBuffers = NULL ; +#endif + + device -> SetIcon = NULL ; + device -> SetCaption = NX_SetCaption; + device -> IconifyWindow = NULL ; + device -> GrabInput = NULL ; + device -> GetWMInfo = NX_GetWMInfo ; + device -> FreeWMCursor = NX_FreeWMCursor ; + device -> CreateWMCursor = NX_CreateWMCursor ; + device -> ShowWMCursor = NX_ShowWMCursor ; + device -> WarpWMCursor = NX_WarpWMCursor ; + device -> CheckMouseMode = NULL ; + device -> InitOSKeymap = NX_InitOSKeymap ; + device -> PumpEvents = NX_PumpEvents ; + + device -> free = NX_DeleteDevice ; + + Dprintf ("leave NX_CreateDevice\n") ; + return device ; +} + +VideoBootStrap NX_bootstrap = { + "nanox", "nanox", NX_Available, NX_CreateDevice +} ; + +static void create_aux_windows (_THIS) +{ + GR_WM_PROPERTIES props ; + + Dprintf ("enter create_aux_windows\n") ; + + // Don't create any extra windows if we are being managed + if (SDL_windowid) { + FSwindow = 0 ; + return ; + } + + if (FSwindow && FSwindow != GR_ROOT_WINDOW_ID) { + GrDestroyWindow (FSwindow) ; + } + + FSwindow = GrNewWindow (GR_ROOT_WINDOW_ID, 0, 0, 1, 1, 0, BLACK, BLACK) ; + props.flags = GR_WM_FLAGS_PROPS ; + props.props = GR_WM_PROPS_NODECORATE ; + GrSetWMProperties (FSwindow, & props) ; + + GrSelectEvents (FSwindow, (GR_EVENT_MASK_EXPOSURE | + GR_EVENT_MASK_BUTTON_DOWN | GR_EVENT_MASK_BUTTON_UP | + GR_EVENT_MASK_FOCUS_IN | GR_EVENT_MASK_FOCUS_OUT | + GR_EVENT_MASK_KEY_DOWN | GR_EVENT_MASK_KEY_UP | + GR_EVENT_MASK_MOUSE_ENTER | GR_EVENT_MASK_MOUSE_EXIT | + GR_EVENT_MASK_MOUSE_MOTION | GR_EVENT_MASK_UPDATE | + GR_EVENT_MASK_CLOSE_REQ)) ; + + Dprintf ("leave create_aux_windows\n") ; +} + +int NX_VideoInit (_THIS, SDL_PixelFormat * vformat) +{ + GR_SCREEN_INFO si ; + + Dprintf ("enter NX_VideoInit\n") ; + + if (GrOpen () < 0) { + SDL_SetError ("GrOpen() fail") ; + return -1 ; + } + + // use share memory to speed up +#ifdef NANOX_SHARE_MEMORY + GrReqShmCmds (0xFFFF); +#endif + + SDL_Window = 0 ; + FSwindow = 0 ; + + GammaRamp_R = NULL ; + GammaRamp_G = NULL ; + GammaRamp_B = NULL ; + + GrGetScreenInfo (& si) ; + SDL_Visual.bpp = si.bpp ; + + /* Determine the current screen size */ + this->info.current_w = si.cols ; + this->info.current_h = si.rows ; + + // GetVideoMode + SDL_modelist = (SDL_Rect **) SDL_malloc (sizeof (SDL_Rect *) * 2) ; + if (SDL_modelist) { + SDL_modelist [0] = (SDL_Rect *) SDL_malloc (sizeof(SDL_Rect)) ; + if (SDL_modelist [0]) { + SDL_modelist [0] -> x = 0 ; + SDL_modelist [0] -> y = 0 ; + SDL_modelist [0] -> w = si.cols ; + SDL_modelist [0] -> h = si.rows ; + } + SDL_modelist [1] = NULL ; + } + + pixel_type = si.pixtype; + SDL_Visual.red_mask = si.rmask; + SDL_Visual.green_mask = si.gmask; + SDL_Visual.blue_mask = si.bmask; + + vformat -> BitsPerPixel = SDL_Visual.bpp ; + if (vformat -> BitsPerPixel > 8) { + vformat -> Rmask = SDL_Visual.red_mask ; + vformat -> Gmask = SDL_Visual.green_mask ; + vformat -> Bmask = SDL_Visual.blue_mask ; + } + + // See if we have been passed a window to use + SDL_windowid = getenv ("SDL_WINDOWID") ; + + // Create the fullscreen (and managed windows : no implement) + create_aux_windows (this) ; + + Dprintf ("leave NX_VideoInit\n") ; + return 0 ; +} + +void NX_VideoQuit (_THIS) +{ + Dprintf ("enter NX_VideoQuit\n") ; + + // Start shutting down the windows + NX_DestroyImage (this, this -> screen) ; + NX_DestroyWindow (this, this -> screen) ; + if (FSwindow && FSwindow != GR_ROOT_WINDOW_ID) { + GrDestroyWindow (FSwindow) ; + } + NX_FreeVideoModes (this) ; + SDL_free (GammaRamp_R) ; + SDL_free (GammaRamp_G) ; + SDL_free (GammaRamp_B) ; + +#ifdef ENABLE_NANOX_DIRECT_FB + if (Clientfb) + GrCloseClientFramebuffer(); +#endif + GrClose () ; + + Dprintf ("leave NX_VideoQuit\n") ; +} + +static void NX_DestroyWindow (_THIS, SDL_Surface * screen) +{ + Dprintf ("enter NX_DestroyWindow\n") ; + + if (! SDL_windowid) { + if (screen && (screen -> flags & SDL_FULLSCREEN)) { + screen -> flags &= ~ SDL_FULLSCREEN ; + NX_LeaveFullScreen (this) ; + } + + // Destroy the output window + if (SDL_Window && SDL_Window != GR_ROOT_WINDOW_ID) { + GrDestroyWindow (SDL_Window) ; + } + } + + // Free the graphics context + if (! SDL_GC) { + GrDestroyGC (SDL_GC) ; + SDL_GC = 0; + } + + Dprintf ("leave NX_DestroyWindow\n") ; +} + +static int NX_CreateWindow (_THIS, SDL_Surface * screen, + int w, int h, int bpp, Uint32 flags) +{ + Dprintf ("enter NX_CreateWindow\n") ; + + // If a window is already present, destroy it and start fresh + if (SDL_Window && SDL_Window != GR_ROOT_WINDOW_ID) { + NX_DestroyWindow (this, screen) ; + } + + // See if we have been given a window id + if (SDL_windowid) { + SDL_Window = SDL_strtol (SDL_windowid, NULL, 0) ; + } else { + SDL_Window = 0 ; + } + + if ( ! SDL_ReallocFormat (screen, bpp, SDL_Visual.red_mask, + SDL_Visual.green_mask, SDL_Visual.blue_mask, 0)) + return -1; + + // Create (or use) the nanox display window + if (! SDL_windowid) { + + SDL_Window = GrNewWindow (GR_ROOT_WINDOW_ID, 0, 0, w, h, 0, BLACK, WHITE) ; + + GrSelectEvents (SDL_Window, (GR_EVENT_MASK_EXPOSURE | + GR_EVENT_MASK_BUTTON_DOWN | GR_EVENT_MASK_BUTTON_UP | + GR_EVENT_MASK_FOCUS_IN | GR_EVENT_MASK_FOCUS_OUT | + GR_EVENT_MASK_KEY_DOWN | GR_EVENT_MASK_KEY_UP | + GR_EVENT_MASK_MOUSE_ENTER | GR_EVENT_MASK_MOUSE_EXIT | + GR_EVENT_MASK_MOUSE_MOTION | GR_EVENT_MASK_UPDATE | + GR_EVENT_MASK_CLOSE_REQ)) ; + } + + /* Create the graphics context here, once we have a window */ + SDL_GC = GrNewGC () ; + if (SDL_GC == 0) { + SDL_SetError("Couldn't create graphics context"); + return(-1); + } + + // Map them both and go fullscreen, if requested + if (! SDL_windowid) { + GrMapWindow (SDL_Window) ; + if (flags & SDL_FULLSCREEN) { + screen -> flags |= SDL_FULLSCREEN ; + NX_EnterFullScreen (this) ; + } else { + screen -> flags &= ~ SDL_FULLSCREEN ; + } + } + +#ifdef ENABLE_NANOX_DIRECT_FB + /* attempt allocating the client side framebuffer */ + Clientfb = GrOpenClientFramebuffer(); + /* NULL return will default to using GrArea()*/ +#endif + + Dprintf ("leave NX_CreateWindow\n") ; + return 0 ; +} + +SDL_Surface * NX_SetVideoMode (_THIS, SDL_Surface * current, + int width, int height, int bpp, Uint32 flags) +{ + Dprintf ("enter NX_SetVideoMode\n") ; + + // Lock the event thread, in multi-threading environments + SDL_Lock_EventThread () ; + + bpp = SDL_Visual.bpp ; + if (NX_CreateWindow (this, current, width, height, bpp, flags) < 0) { + current = NULL; + goto done; + } + + if (current -> w != width || current -> h != height) { + current -> w = width ; + current -> h = height ; + current -> pitch = SDL_CalculatePitch (current) ; + NX_ResizeImage (this, current, flags) ; + } + + /* Clear these flags and set them only if they are in the new set. */ + current -> flags &= ~(SDL_RESIZABLE|SDL_NOFRAME); + current -> flags |= (flags & (SDL_RESIZABLE | SDL_NOFRAME)) ; + + done: + SDL_Unlock_EventThread () ; + + Dprintf ("leave NX_SetVideoMode\n") ; + + // We're done! + return current ; +} + +// ncolors <= 256 +int NX_SetColors (_THIS, int firstcolor, int ncolors, SDL_Color * colors) +{ + int i ; + GR_PALETTE pal ; + + Dprintf ("enter NX_SetColors\n") ; + + if (ncolors > 256) return 0 ; + + pal.count = ncolors ; + for (i = 0; i < ncolors; ++ i) { + pal.palette [i].r = colors [i].r ; + pal.palette [i].g = colors [i].g ; + pal.palette [i].b = colors [i].b ; + } + GrSetSystemPalette (firstcolor, & pal) ; + + Dprintf ("leave NX_SetColors\n") ; + return 1 ; +} + +static int NX_ToggleFullScreen (_THIS, int on) +{ + SDL_Rect rect ; + Uint32 event_thread ; + + Dprintf ("enter NX_ToggleFullScreen\n") ; + + // Don't switch if we don't own the window + if (SDL_windowid) return 0 ; + + // Don't lock if we are the event thread + event_thread = SDL_EventThreadID () ; + if (event_thread && (SDL_ThreadID () == event_thread)) { + event_thread = 0 ; + } + if (event_thread) { + SDL_Lock_EventThread() ; + } + + if (on) { + NX_EnterFullScreen (this) ; + } else { + this -> screen -> flags &= ~ SDL_FULLSCREEN ; + NX_LeaveFullScreen (this) ; + } + + rect.x = rect.y = 0 ; + rect.w = this -> screen -> w, rect.h = this -> screen -> h ; + NX_NormalUpdate (this, 1, & rect) ; + + if (event_thread) { + SDL_Unlock_EventThread () ; + } + + Dprintf ("leave NX_ToggleFullScreen\n") ; + return 1 ; +} + +// Update the current mouse state and position +static void NX_UpdateMouse (_THIS) +{ + int x, y ; + GR_WINDOW_INFO info ; + GR_SCREEN_INFO si ; + + + Dprintf ("enter NX_UpdateMouse\n") ; + + // Lock the event thread, in multi-threading environments + SDL_Lock_EventThread () ; + + GrGetScreenInfo (& si) ; + GrGetWindowInfo (SDL_Window, & info) ; + x = si.xpos - info.x ; + y = si.ypos - info.y ; + if (x >= 0 && x <= info.width && y >= 0 && y <= info.height) { + SDL_PrivateAppActive (1, SDL_APPMOUSEFOCUS) ; + SDL_PrivateMouseMotion (0, 0, x, y); + } else { + SDL_PrivateAppActive (0, SDL_APPMOUSEFOCUS) ; + } + + SDL_Unlock_EventThread () ; + Dprintf ("leave NX_UpdateMouse\n") ; +} + +static int NX_SetGammaRamp (_THIS, Uint16 * ramp) +{ + int i ; + Uint16 * red, * green, * blue ; + + Dprintf ("enter NX_SetGammaRamp\n") ; + + if (SDL_Visual.bpp != 32 && SDL_Visual.bpp != 24) return -1 ; + + if (! GammaRamp_R) GammaRamp_R = (Uint16 *) SDL_malloc (sizeof (Uint16) * CI_SIZE) ; + if (! GammaRamp_G) GammaRamp_G = (Uint16 *) SDL_malloc (sizeof (Uint16) * CI_SIZE) ; + if (! GammaRamp_B) GammaRamp_B = (Uint16 *) SDL_malloc (sizeof (Uint16) * CI_SIZE) ; + if ((! GammaRamp_R) || (! GammaRamp_G) || (! GammaRamp_B)) { + SDL_OutOfMemory () ; + return -1 ; + } + + for (i = 0; i < CI_SIZE; ++ i) + GammaRamp_R [i] = GammaRamp_G [i] = GammaRamp_B [i] = i ; + + red = ramp ; + green = ramp + CI_SIZE ; + blue = green + CI_SIZE ; + + for (i = 0; i < CI_SIZE; ++ i) { + GammaRamp_R [i] = red [i] ; + GammaRamp_G [i] = green [i] ; + GammaRamp_B [i] = blue [i] ; + } + SDL_UpdateRect(this->screen, 0, 0, 0, 0); + + Dprintf ("leave NX_SetGammaRamp\n") ; + return 0 ; +} + +static int NX_GetGammaRamp (_THIS, Uint16 * ramp) +{ + int i ; + Uint16 * red, * green, * blue ; + + Dprintf ("enter NX_GetGammaRamp\n") ; + + if (SDL_Visual.bpp != 32 && SDL_Visual.bpp != 24) return -1 ; + red = ramp ; + green = ramp + CI_SIZE ; + blue = green + CI_SIZE ; + if (GammaRamp_R && GammaRamp_G && GammaRamp_B) { + for (i = 0; i < CI_SIZE; ++ i) { + red [i] = GammaRamp_R [i] ; + green [i] = GammaRamp_G [i] ; + blue [i] = GammaRamp_B [i] ; + } + } else { + for (i = 0; i < CI_SIZE; ++ i) + red [i] = green [i] = blue [i] = i ; + } + + Dprintf ("leave NX_GetGammaRamp\n") ; + return 0 ; +} diff --git a/3rdparty/SDL/src/video/nanox/SDL_nxvideo.h b/3rdparty/SDL/src/video/nanox/SDL_nxvideo.h new file mode 100644 index 0000000..1d858d9 --- /dev/null +++ b/3rdparty/SDL/src/video/nanox/SDL_nxvideo.h @@ -0,0 +1,96 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + Copyright (C) 2001 Hsieh-Fu Tsai + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Sam Lantinga + slouken@libsdl.org + + Hsieh-Fu Tsai + clare@setabox.com +*/ +#include "SDL_config.h" + +#ifndef _SDL_nxvideo_h +#define _SDL_nxvideo_h + +#include <microwin/nano-X.h> + +#include "../SDL_sysvideo.h" + +#ifdef ENABLE_NANOX_DEBUG +#define Dprintf printf +#else +#define Dprintf(ignore...) +#endif + +// Hidden "this" pointer for the video functions +#define _THIS SDL_VideoDevice * this + +// Private display data +typedef struct NX_SDL_VISUAL { + int bpp ; + Uint32 red_mask ; + Uint32 green_mask ; + Uint32 blue_mask ; +} nx_sdl_visual_t ; + +struct SDL_PrivateVideoData { + GR_WINDOW_ID SDL_Window ; + GR_WINDOW_ID FSwindow ; + // Flag: true if we have been passed a window + char * SDL_windowid ; + GR_GC_ID GC ; + unsigned char * Image ; + unsigned char * Image_buff ; /* for GrArea*/ + unsigned char * Clientfb; /* for DirectFB*/ + nx_sdl_visual_t SDL_Visual ; + // The current list of available video modes + SDL_Rect ** modelist ; + int currently_fullscreen ; + // for fullscreen + int OffsetX, OffsetY ; + // for GammaRamp + Uint16 * GammaRamp_R, * GammaRamp_G, * GammaRamp_B ; + // for GrArea, r_mask, g_mask, b_mask + int pixel_type ; +#ifdef ENABLE_NANOX_DIRECT_FB + GR_WINDOW_FB_INFO fbinfo; +#endif +} ; + +#define SDL_Window (this -> hidden -> SDL_Window) +#define FSwindow (this -> hidden -> FSwindow) +#define SDL_windowid (this -> hidden -> SDL_windowid) +#define SDL_GC (this -> hidden -> GC) +#define SDL_Image (this -> hidden -> Image) +#define Image_buff (this -> hidden -> Image_buff) +#define Clientfb (this -> hidden -> Clientfb) +#define SDL_Visual (this -> hidden -> SDL_Visual) +#define SDL_modelist (this -> hidden -> modelist) +#define currently_fullscreen (this -> hidden -> currently_fullscreen) +#define OffsetX (this -> hidden -> OffsetX) +#define OffsetY (this -> hidden -> OffsetY) +#define GammaRamp_R (this -> hidden -> GammaRamp_R) +#define GammaRamp_G (this -> hidden -> GammaRamp_G) +#define GammaRamp_B (this -> hidden -> GammaRamp_B) +#define pixel_type (this -> hidden -> pixel_type) +#define fbinfo (this -> hidden -> fbinfo) + +#define CI_SIZE 256 // color index size + +#endif // _SDL_nxvideo_h diff --git a/3rdparty/SDL/src/video/nanox/SDL_nxwm.c b/3rdparty/SDL/src/video/nanox/SDL_nxwm.c new file mode 100644 index 0000000..c60ebb0 --- /dev/null +++ b/3rdparty/SDL/src/video/nanox/SDL_nxwm.c @@ -0,0 +1,61 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + Copyright (C) 2001 Hsieh-Fu Tsai + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Sam Lantinga + slouken@libsdl.org + + Hsieh-Fu Tsai + clare@setabox.com +*/ +#include "SDL_config.h" + +#include "SDL_syswm.h" +#include "../../events/SDL_events_c.h" + +#include "SDL_nxwm_c.h" + +void NX_SetCaption (_THIS, const char * title, const char * icon) +{ + Dprintf ("enter NX_SetCaption\n") ; + + // Lock the event thread, in multi-threading environments + SDL_Lock_EventThread () ; + + if (SDL_Window) + GrSetWindowTitle (SDL_Window, title) ; + + SDL_Unlock_EventThread () ; + Dprintf ("leave NX_SetCaption\n") ; +} + +int NX_GetWMInfo (_THIS, SDL_SysWMinfo * info) +{ + Dprintf ("enter NX_GetWMInfo\n") ; + + if (info -> version.major <= SDL_MAJOR_VERSION) { + info -> window = SDL_Window ; + return 1 ; + } else { + SDL_SetError("Application not compiled with SDL %d.%d\n", + SDL_MAJOR_VERSION, SDL_MINOR_VERSION) ; + return -1 ; + } + + Dprintf ("leave NX_GetWMInfo\n") ; +} diff --git a/3rdparty/SDL/src/video/nanox/SDL_nxwm_c.h b/3rdparty/SDL/src/video/nanox/SDL_nxwm_c.h new file mode 100644 index 0000000..77be794 --- /dev/null +++ b/3rdparty/SDL/src/video/nanox/SDL_nxwm_c.h @@ -0,0 +1,32 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + Copyright (C) 2001 Hsieh-Fu Tsai + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Sam Lantinga + slouken@libsdl.org + + Hsieh-Fu Tsai + clare@setabox.com +*/ +#include "SDL_config.h" + +#include "SDL_nxvideo.h" + +// Functions to be exported +extern void NX_SetCaption (_THIS, const char * title, const char * icon) ; +extern int NX_GetWMInfo (_THIS, SDL_SysWMinfo * info) ; diff --git a/3rdparty/SDL/src/video/nds/SDL_ndsevents.c b/3rdparty/SDL/src/video/nds/SDL_ndsevents.c new file mode 100644 index 0000000..a4f0fbe --- /dev/null +++ b/3rdparty/SDL/src/video/nds/SDL_ndsevents.c @@ -0,0 +1,83 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* Being a nds driver, there's no event stream. We just define stubs for + most of the API. */ +#include <nds.h> +#include "SDL.h" +#include "../../events/SDL_sysevents.h" +#include "../../events/SDL_events_c.h" +#include "SDL_ndsvideo.h" +#include "SDL_ndsevents_c.h" + +static SDLKey keymap[NDS_NUMKEYS]; +char keymem[NDS_NUMKEYS]; /* memorize states of buttons */ + +void NDS_PumpEvents(_THIS) +{ + scanKeys(); + int i; + SDL_keysym keysym; + keysym.mod=KMOD_NONE; + for(i=0;i<NDS_NUMKEYS;i++) + { + keysym.scancode=i; + keysym.sym=keymap[i]; + if(keysHeld()&(1<<i) && !keymem[i]) + { + keymem[i]=1; + //printf("key released %d\n",i); + SDL_PrivateKeyboard(SDL_RELEASED, &keysym); + } + if(!(keysHeld()&(1<<i)) && keymem[i]) + { + keymem[i]=0; + //printf("key pressed %d\n",i); + SDL_PrivateKeyboard(SDL_PRESSED, &keysym); + } + } + //touchPosition touch; + //touch=touchReadXY(); + //if (touch.px!=0 || touch.py!=0) + // SDL_PrivateMouseMotion(SDL_PRESSED, 0, touch.px, touch.py); +} + +void NDS_InitOSKeymap(_THIS) +{ + SDL_memset(keymem,1,NDS_NUMKEYS); + keymap[KEY_A]=SDLK_a; + keymap[KEY_B]=SDLK_s; + keymap[KEY_X]=SDLK_w; + keymap[KEY_Y]=SDLK_d; + keymap[KEY_L]=SDLK_q; + keymap[KEY_R]=SDLK_e; + keymap[KEY_UP]=SDLK_UP; + keymap[KEY_DOWN]=SDLK_DOWN; + keymap[KEY_LEFT]=SDLK_LEFT; + keymap[KEY_RIGHT]=SDLK_RIGHT; + keymap[KEY_SELECT]=SDLK_SPACE; + keymap[KEY_START]=SDLK_RETURN; +} + +/* end of SDL_gbaevents.c ... */ + diff --git a/3rdparty/SDL/src/video/nds/SDL_ndsevents_c.h b/3rdparty/SDL/src/video/nds/SDL_ndsevents_c.h new file mode 100644 index 0000000..fcd0ef2 --- /dev/null +++ b/3rdparty/SDL/src/video/nds/SDL_ndsevents_c.h @@ -0,0 +1,51 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#include "SDL_ndsvideo.h" + +/* Variables and functions exported by SDL_sysevents.c to other parts + of the native video subsystem (SDL_sysvideo.c) +*/ +extern void NDS_InitOSKeymap(_THIS); +extern void NDS_PumpEvents(_THIS); + +#define NDS_NUMKEYS 12 + +/* +#define NDS_JOYPADREG 0x4000130 +#define NDS_JOYPAD (*(volatile Uint16*)NDS_JOYPADREG) + +#define NDS_NUMKEYS 10 +#define NDS_KEYA (0) +#define NDS_KEYB (1) +#define NDS_KEYSEL (2) +#define NDS_KEYSTART (3) +#define NDS_KEYRIGHT (4) +#define NDS_KEYLEFT (5) +#define NDS_KEYUP (6) +#define NDS_KEYDOWN (7) +#define NDS_KEYR (8) +#define NDS_KEYL (9) +*/ +/* end of SDL_NDSevents_c.h ... */ + diff --git a/3rdparty/SDL/src/video/nds/SDL_ndsmouse.c b/3rdparty/SDL/src/video/nds/SDL_ndsmouse.c new file mode 100644 index 0000000..bba1417 --- /dev/null +++ b/3rdparty/SDL/src/video/nds/SDL_ndsmouse.c @@ -0,0 +1,34 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#include "SDL_error.h" +#include "SDL_mouse.h" +#include "../../events/SDL_events_c.h" + +#include "SDL_ndsmouse_c.h" + + +/* The implementation dependent data for the window manager cursor */ +struct WMcursor { + int unused; +}; diff --git a/3rdparty/SDL/src/video/nds/SDL_ndsmouse_c.h b/3rdparty/SDL/src/video/nds/SDL_ndsmouse_c.h new file mode 100644 index 0000000..76adf02 --- /dev/null +++ b/3rdparty/SDL/src/video/nds/SDL_ndsmouse_c.h @@ -0,0 +1,26 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#include "SDL_ndsvideo.h" + +/* Functions to be exported */ diff --git a/3rdparty/SDL/src/video/nds/SDL_ndsvideo.c b/3rdparty/SDL/src/video/nds/SDL_ndsvideo.c new file mode 100644 index 0000000..d0ee8bf --- /dev/null +++ b/3rdparty/SDL/src/video/nds/SDL_ndsvideo.c @@ -0,0 +1,500 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#include <nds.h> +#include <nds/registers_alt.h> +#include "SDL.h" +#include "SDL_error.h" +#include "SDL_video.h" +#include "SDL_mouse.h" +#include "../SDL_sysvideo.h" +#include "../SDL_pixels_c.h" +#include "../../events/SDL_events_c.h" + +#include "SDL_ndsvideo.h" +#include "SDL_ndsevents_c.h" +#include "SDL_ndsmouse_c.h" + +#define NDSVID_DRIVER_NAME "nds" + +/* Initialization/Query functions */ +static int NDS_VideoInit(_THIS, SDL_PixelFormat *vformat); +static SDL_Rect **NDS_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags); +static SDL_Surface *NDS_SetVideoMode(_THIS, SDL_Surface *current, int width, int height, int bpp, Uint32 flags); +static int NDS_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors); +static void NDS_VideoQuit(_THIS); + +/* Hardware surface functions */ +static int NDS_AllocHWSurface(_THIS, SDL_Surface *surface); +static int NDS_LockHWSurface(_THIS, SDL_Surface *surface); +static int NDS_FlipHWSurface(_THIS, SDL_Surface *surface); +static void NDS_UnlockHWSurface(_THIS, SDL_Surface *surface); +static void NDS_FreeHWSurface(_THIS, SDL_Surface *surface); + +/* etc. */ +static void NDS_UpdateRects(_THIS, int numrects, SDL_Rect *rects); + +/* NDS driver bootstrap functions */ + +static int NDS_Available(void) +{ + return(1); +} + +static void NDS_DeleteDevice(SDL_VideoDevice *device) +{ + SDL_free(device->hidden); + SDL_free(device); +} + +void on_irq_vblank() +{ + // Disable interrupts + //REG_IME = 0; + scanKeys(); + + // VBLANK_INTR_WAIT_FLAGS |= IRQ_VBLANK; + // REG_IF |= IRQ_VBLANK; + //REG_IF = REG_IF; + + // Enable interrupts + //REG_IME = 1; +} + +static int HWAccelBlit(SDL_Surface *src, SDL_Rect *srcrect, + SDL_Surface *dst, SDL_Rect *dstrect) + { + return 0; + } + +static int CheckHWBlit(_THIS, SDL_Surface *src, SDL_Surface *dst) +{ + if (src->flags & SDL_SRCALPHA) return false; + if (src->flags & SDL_SRCCOLORKEY) return false; + if (src->flags & SDL_HWPALETTE ) return false; + if (dst->flags & SDL_SRCALPHA) return false; + if (dst->flags & SDL_SRCCOLORKEY) return false; + if (dst->flags & SDL_HWPALETTE ) return false; + + if (src->format->BitsPerPixel != dst->format->BitsPerPixel) return false; + if (src->format->BytesPerPixel != dst->format->BytesPerPixel) return false; + + src->map->hw_blit = HWAccelBlit; + return true; +} + +static SDL_VideoDevice *NDS_CreateDevice(int devindex) +{ + SDL_VideoDevice *device=0; + + + /* Initialize all variables that we clean on shutdown */ + device = (SDL_VideoDevice *)SDL_malloc(sizeof(SDL_VideoDevice)); + if ( device ) { + SDL_memset(device, 0, (sizeof *device)); + device->hidden = (struct SDL_PrivateVideoData *) + SDL_malloc((sizeof *device->hidden)); + } + if ( (device == NULL) || (device->hidden == NULL) ) { + SDL_OutOfMemory(); + if ( device ) { + SDL_free(device); + } + return(0); + } + SDL_memset(device->hidden, 0, (sizeof *device->hidden)); + + /* Set the function pointers */ + device->VideoInit = NDS_VideoInit; + device->ListModes = NDS_ListModes; + device->SetVideoMode = NDS_SetVideoMode; + device->CreateYUVOverlay = NULL; + device->SetColors = NDS_SetColors; + device->UpdateRects = NDS_UpdateRects; + device->VideoQuit = NDS_VideoQuit; + device->AllocHWSurface = NDS_AllocHWSurface; + device->CheckHWBlit = CheckHWBlit; + device->FillHWRect = NULL; + device->SetHWColorKey = NULL; + device->SetHWAlpha = NULL; + device->LockHWSurface = NDS_LockHWSurface; + device->UnlockHWSurface = NDS_UnlockHWSurface; + device->FlipHWSurface = NDS_FlipHWSurface; + device->FreeHWSurface = NDS_FreeHWSurface; + device->SetCaption = NULL; + device->SetIcon = NULL; + device->IconifyWindow = NULL; + device->GrabInput = NULL; + device->GetWMInfo = NULL; + device->InitOSKeymap = NDS_InitOSKeymap; + device->PumpEvents = NDS_PumpEvents; + device->info.blit_hw=1; + + device->free = NDS_DeleteDevice; + return device; +} + +VideoBootStrap NDS_bootstrap = { + NDSVID_DRIVER_NAME, "SDL NDS video driver", + NDS_Available, NDS_CreateDevice +}; + + u16* frontBuffer;// = (u16*)(0x06000000); + u16* backBuffer;// = (u16*)(0x06000000 + 256 * 256 * 2); +int NDS_VideoInit(_THIS, SDL_PixelFormat *vformat) +{ + //printf("WARNING: You are using the SDL NDS video driver!\n"); + + /* Determine the screen depth (use default 8-bit depth) */ + /* we change this during the SDL_SetVideoMode implementation... */ + vformat->BitsPerPixel = 16; // mode 3 + vformat->BytesPerPixel = 2; + vformat->Rmask = 0x0000f800; + vformat->Gmask = 0x000007e0; + vformat->Bmask = 0x0000001f; + powerON(POWER_ALL); + irqInit(); + irqSet(IRQ_VBLANK, on_irq_vblank); + irqEnable(IRQ_VBLANK); + + //set the mode for 2 text layers and two extended background layers + //videoSetMode(MODE_5_2D | DISPLAY_BG3_ACTIVE); + videoSetMode(MODE_6_2D| DISPLAY_BG2_ACTIVE); + + //set the sub background up for text display (we could just print to one + //of the main display text backgrounds just as easily + videoSetModeSub(MODE_0_2D | DISPLAY_BG0_ACTIVE); //sub bg 0 will be used to print text + + //set the first two banks as background memory and the third as sub background memory + //D is not used..if you need a bigger background then you will need to map + //more vram banks consecutivly (VRAM A-D are all 0x20000 bytes in size) + //vramSetMainBanks(VRAM_A_MAIN_BG_0x6000000, VRAM_B_MAIN_BG_0x6020000,VRAM_C_SUB_BG , VRAM_D_LCD); + vramSetMainBanks(VRAM_A_MAIN_BG,VRAM_B_MAIN_BG,VRAM_C_MAIN_BG,VRAM_D_MAIN_BG); + //vramSetBankA(VRAM_A_MAIN_BG); + //vramSetBankB(VRAM_B_MAIN_BG); + //vramSetBankC(VRAM_C_MAIN_BG); + //vramSetBankD(VRAM_D_MAIN_BG); + //vramSetBankE(VRAM_E_MAIN_BG); + //vramSetBankF(VRAM_F_MAIN_BG); + //vramSetBankG(VRAM_G_MAIN_BG); + vramSetBankH(VRAM_H_SUB_BG); + vramSetBankI(VRAM_I_LCD); + + ////////////////set up text background for text///////////////////// + SUB_BG0_CR = BG_MAP_BASE(8); + + BG_PALETTE_SUB[255] = RGB15(31,31,31);//by default font will be rendered with color 255 + ///////////////set up our bitmap background/////////////////////// + + //BG3_CR = BG_BMP16_512x512; + + //these are rotation backgrounds so you must set the rotation attributes: + //these are fixed point numbers with the low 8 bits the fractional part + //this basicaly gives it a 1:1 translation in x and y so you get a nice flat bitmap + /* BG3_XDX = 1<<8; + BG3_XDY = 0; + BG3_YDX = 0; + BG3_YDY = 1<<8; + //our bitmap looks a bit better if we center it so scroll down (256 - 192) / 2 + BG3_CX = 0; + BG3_CY = 0; + */ + //consoleInit() is a lot more flexible but this gets you up and running quick + consoleInitDefault((u16*)SCREEN_BASE_BLOCK_SUB(8), (u16*)CHAR_BASE_BLOCK_SUB(0), 16); + + + frontBuffer =(u16*)(0x06000000); + //backBuffer =(u16*)(0x06000000 + 1024 * 512*2); + + //lcdSwap(); + /* We're done! */ + return(0); +} + +SDL_Rect **NDS_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags) +{ + return (SDL_Rect **) -1; +} + +SDL_Surface *NDS_SetVideoMode(_THIS, SDL_Surface *current, + int width, int height, int bpp, Uint32 flags) +{ + Uint32 Rmask, Gmask, Bmask, Amask; + + //if(width > 1024 || height > 512 || bpp > 16) + // return(NULL); + + if(bpp >8) { + bpp=16; + Rmask = 0x0000001F; + Gmask = 0x000003E0; + Bmask = 0x00007C00; + Amask = 0x00008000; + + videoSetMode(MODE_5_2D| DISPLAY_BG2_ACTIVE); + + vramSetMainBanks(VRAM_A_MAIN_BG,VRAM_B_MAIN_BG,VRAM_C_MAIN_BG,VRAM_D_MAIN_BG); + + BG2_CR = BG_BMP16_512x512; + BG2_XDX = ((width / 256) << 8) | (width % 256) ; + BG2_XDY = 0; + BG2_YDX = 0; + BG2_YDY = ((height / 192) << 8) | ((height % 192) + (height % 192) / 3) ; + BG2_CX = 0; + BG2_CY = 0; +// for (i=0;i<256*192;i++) +// frontBuffer[i] = RGB15(31,0,0)|BIT(15); + } + else + if(bpp <= 8) { + bpp=8; + Rmask = 0x00000000; + Gmask = 0x00000000; + Bmask = 0x00000000; + BG2_CR = BG_BMP8_1024x512; + BG2_XDX = ((width / 256) << 8) | (width % 256) ; + BG2_XDY = 0; + BG2_YDX = 0; + BG2_YDY = ((height / 192) << 8) | ((height % 192) + (height % 192) / 3) ; + + } + else + if(bpp < 15) bpp=15; + if(width<=256) width=256; + else + if(width<256) width=256; + if(height<=192) height=192; + else + if(height<192) height=192; + + if(bpp==8) + { + if(width<256) width=256; + if(height<192) height=192; + this->hidden->ndsmode=4; + } + + if(bpp==15) + { + if(width<256) this->hidden->ndsmode=5; + else this->hidden->ndsmode=3; + } + + this->hidden->buffer= frontBuffer;//NDS_VRAM_BASE; + + //NDS_DISPCNT = NDS_DISP_MODE(this->hidden->ndsmode)|NDS_DISP_BG2; + + //fprintf(stderr,"Setting mode %dx%d (ndsmode %d)\n", width, height,this->hidden->ndsmode); + + // FIXME: How do I tell that 15 bits mode is 555? + + SDL_memset(this->hidden->buffer, 0, 1024 * 512* ((this->hidden->ndsmode==4 || this->hidden->ndsmode==5) ? 2 : 1 ) * ((bpp+7) / 8)); + + /* Allocate the new pixel format for the screen */ + if ( ! SDL_ReallocFormat(current, bpp, Rmask, Gmask, Bmask, Amask) ) { + this->hidden->buffer = NULL; + SDL_SetError("Couldn't allocate new pixel format for requested mode"); + return(NULL); + } + + /* Set up the new mode framebuffer */ + current->flags = flags | SDL_FULLSCREEN | SDL_HWSURFACE | (this->hidden->ndsmode > 0 ? SDL_DOUBLEBUF : 0); + this->hidden->w = current->w = width; + this->hidden->h = current->h = height; + current->pixels = frontBuffer; + + if (flags & SDL_DOUBLEBUF) { + this->hidden->secondbufferallocd=1; + backBuffer=(u16*)SDL_malloc(1024*512*2); + current->pixels = backBuffer; + } + if(bpp==8) + current->pitch =1024; + else + current->pitch =512*2; + + /* We're done */ + return(current); +} + +static int NDS_AllocHWSurface(_THIS, SDL_Surface *surface) +{ + if(this->hidden->secondbufferallocd) { + //printf("double double buffer alloc\n"); + return -1; + } + //if(this->hidden->ndsmode==3) + //{ + // printf("no 2nd buffer in mode3\n"); + // return -1; + //} + //printf("second buffer\n"); + //this->hidden->secondbufferallocd=1; + //backBuffer=(u16*)malloc(1024*512*2); + //surface->pixels = backBuffer; + + return(0); +} +static void NDS_FreeHWSurface(_THIS, SDL_Surface *surface) +{ + //free(backBuffer); + this->hidden->secondbufferallocd=0; +} +int z=0; +/* We need to wait for vertical retrace on page flipped displays */ +static int NDS_LockHWSurface(_THIS, SDL_Surface *surface) +{ +/* + uint8* a = surface->pixels; + int i,j; + a += 5 * SCREEN_WIDTH + 5; + for( i = 0; i < 195; ++i) { + uint16* line = a + (SCREEN_WIDTH * i); + for( j = 0; j < 158; ++j) { + *line++ = RGB15(155,155,25); + } + } +*/ + //if (z <256) + // BG_PALETTE[z++]=RGB15(255-z,z,255-z); + + + return(0); +} + +static void NDS_UnlockHWSurface(_THIS, SDL_Surface *surface) +{ + return; +} + +static int NDS_FlipHWSurface(_THIS, SDL_Surface *surface) +{ + if(this->hidden->secondbufferallocd){ + while(DISP_Y!=192); + while(DISP_Y==192); + //printf("flip"); + + dmaCopyAsynch(backBuffer,frontBuffer,1024*512); + } + //printf("flip\n"); + //u16* temp = surface->pixels; + //surface->pixels = frontBuffer; + //frontBuffer = temp; + /* u8* vram=BG_GFX; + int x,y; + for(y = 0; y < 512; y++) + dmaCopy(&frontBuffer[y*rects->w], &vram[y*512],512); + //unsigned char buf; + + //printf("NDS_FlipHWSurface\n"); + //printf("ptr now: 0x%x\n",surface->pixels); + + while(DISP_Y!=192); + while(DISP_Y==192); + //swap + u16* temp = frontBuffer; + frontBuffer = backBuffer; + backBuffer = temp; + + //flip + //base is 16KB and screen size is 256x256x2 (128KB) + BG2_CR ^= BG_BMP_BASE( 512 / 16 ); */ +/* + if(surface->pixels == frontBuffer)//NDS_VRAM_BASE) + { + while(DISP_Y!=192); + while(DISP_Y==192); + //swap + u16* temp = backBuffer; + backBuffer = frontBuffer; + frontBuffer = temp; + + //flip + //base is 16KB and screen size is 256x256x2 (128KB) + BG3_CR ^= BG_BMP_BASE( 128 / 16 ); + } + else + { + + while(DISP_Y!=192); + while(DISP_Y==192); + //swap + u16* temp = frontBuffer; + frontBuffer = backBuffer; + backBuffer = temp; + + //flip + //base is 16KB and screen size is 256x256x2 (128KB) + BG3_CR ^= BG_BMP_BASE( 128 / 16 ); + + } + */ + //printf("ptr then: 0x%x\n",surface->pixels); + + //printf("setting dispcnt to 0x%x\n",NDS_DISPCNT = NDS_DISP_MODE(this->hidden->ndsmode)|NDS_DISP_BG2| buf); + return(0); +} + +static void NDS_UpdateRects(_THIS, int numrects, SDL_Rect *rects) +{ + //fprintf(stderr,"update\n"); + /* do nothing. */ + //dmaCopy(frontBuffer,BG_GFX,512*512); + /* + u8* vram=(u8*)BG_GFX; + int x,y; + for(y = 0; y < 512; y++) + dmaCopy(&frontBuffer[y*rects->w], &vram[y*512],512); + */ + +} + +int NDS_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors) +{ + //printf("SetColors\n"); + short r,g,b; + + if(this->hidden->ndsmode != 4) + { + printf("This is not a palettized mode\n"); + return -1; + } + + int i,j=firstcolor+ncolors; + for(i=firstcolor;i<j;i++) + { + r=colors[i].r>>3; + g=colors[i].g>>3; + b=colors[i].b>>3; + BG_PALETTE[i]=RGB15(r, g, b); + } + + return(0); +} + +/* Note: If we are terminated, this could be called in the middle of + another SDL video routine -- notably UpdateRects. +*/ +void NDS_VideoQuit(_THIS) +{ +} diff --git a/3rdparty/SDL/src/video/nds/SDL_ndsvideo.h b/3rdparty/SDL/src/video/nds/SDL_ndsvideo.h new file mode 100644 index 0000000..015f655 --- /dev/null +++ b/3rdparty/SDL/src/video/nds/SDL_ndsvideo.h @@ -0,0 +1,61 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#ifndef _SDL_ndsvideo_h +#define _SDL_ndsvideo_h + +#include "SDL_mouse.h" +#include "../SDL_sysvideo.h" + +/* Hidden "this" pointer for the video functions */ +#define _THIS SDL_VideoDevice *this + + +/* Private display data */ + +struct SDL_PrivateVideoData { + int w, h; + void *buffer; + short ndsmode; + short secondbufferallocd; +}; + +/* +#define NDS_VIDC_BASE 0x4000000 +#define NDS_DISPCNT (*(volatile Uint32*)(NDS_VIDC_BASE)) +#define NDS_VIDC_SCANLINE (NDS_VIDC_BASE+6) +#define NDS_SCANLINE (*(volatile Uint8*)(NDS_VIDC_SCANLINE)) + +#define NDS_DISP_MODE(n) (n&7) +#define NDS_DISP_BG2 0x400 +#define NDS_DISP_FB 0x10 + +#define NDS_PAL_BASE 0x5000000 +#define NDS_BGPAL ((volatile Uint16*)(NDS_PAL_BASE)) +#define NDS_OBJPAL ((volatile Uint16*)(NDS_PAL_BASE+0x200)) + +#define NDS_VRAM_BASE 0x6000000 +#define NDS_VRAM_2NDBUF 0x600a000 +#define NDS_VRAM = ((volatile Uint16* )NDS_VRAM_BASE) +*/ +#endif /* _SDL_ndsvideo_h */ diff --git a/3rdparty/SDL/src/video/os2fslib/SDL_os2fslib.c b/3rdparty/SDL/src/video/os2fslib/SDL_os2fslib.c new file mode 100644 index 0000000..a902d1f --- /dev/null +++ b/3rdparty/SDL/src/video/os2fslib/SDL_os2fslib.c @@ -0,0 +1,3018 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#define _ULS_CALLCONV_ +#define CALLCONV _System +#include <unidef.h> // Unicode API +#include <uconv.h> // Unicode API (codepage conversion) + +#include <process.h> +#include <time.h> + +#include "SDL_video.h" +#include "SDL_mouse.h" +#include "../SDL_sysvideo.h" +#include "../SDL_pixels_c.h" +#include "../../events/SDL_events_c.h" + +#include "SDL_os2fslib.h" + +static ULONG ulFCFToUse = + FCF_TITLEBAR | + FCF_SYSMENU | + FCF_MINBUTTON | + FCF_MAXBUTTON | + FCF_NOBYTEALIGN | + FCF_SIZEBORDER | + FCF_TASKLIST; + +static int bMouseCaptured = 0; +static int bMouseCapturable = 0; +static HPOINTER hptrGlobalPointer = NULL; +static HPOINTER hptrCurrentIcon = NULL; +static int iWindowSizeX = 320; +static int iWindowSizeY = 200; +static int bWindowResized = 0; + +#pragma pack(1) +typedef struct BMPINFO +{ + BITMAPINFO; + RGB clr; +} BMPINFO, *PBMPINFO; +#pragma pack() + + +// Backdoors: +DECLSPEC void SDLCALL SDL_OS2FSLIB_SetFCFToUse(ULONG ulFCF) +{ + ulFCFToUse = ulFCF; +} + +// Configuration defines: + +// We have to report empty alpha mask, otherwise SDL will select +// alpha blitters, and this will have unwanted results, as we don't +// support alpha channel in FSLib yet. +#define REPORT_EMPTY_ALPHA_MASK + +// Experimental: Move every FSLib_BitBlt() call into window message +// processing function. +// This may fix dirt left on desktop. Or not. +//#define BITBLT_IN_WINMESSAGEPROC + +// Experimental-2: Use WinLockWindowUpdate() in around bitblts! +// This is not enabled, because it seems to cause more problems +// than good. +//#define USE_WINLOCKWINDOWUPDATE_AROUND_BITBLTS + +// Use the following to show resized image instead of black stuff +// even if the surface is resizable. +//#define RESIZE_EVEN_IF_RESIZABLE + +/* The translation table from a VK keysym to a SDL keysym */ +static SDLKey HWScanKeyMap[256]; +static SDL_keysym *TranslateKey(int vkey, int chcode, int scancode, SDL_keysym *keysym, int iPressed); +static int iShiftIsPressed; + +#ifdef BITBLT_IN_WINMESSAGEPROC +#define WM_UPDATERECTSREQUEST WM_USER+50 +#endif + +#ifdef USE_WINLOCKWINDOWUPDATE_AROUND_BITBLTS +#define FSLIB_BITBLT(hwnd, buffer, top, left, width, height) \ + { \ + WinLockWindowUpdate(HWND_DESKTOP, HWND_DESKTOP); \ + FSLib_BitBlt(hwnd, buffer, top, left, width, height); \ + WinLockWindowUpdate(HWND_DESKTOP, NULL); \ + } +#else +#define FSLIB_BITBLT(hwnd, buffer, top, left, width, height) \ + FSLib_BitBlt(hwnd, buffer, top, left, width, height); +#endif + +///////////////////////////////////////////////////////////////////// +// +// SetAccessableWindowPos +// +// Same as WinSetWindowPos(), but takes care for the window to be +// always on the screen, the titlebar will be accessable everytime. +// +///////////////////////////////////////////////////////////////////// +static BOOL SetAccessableWindowPos(HWND hwnd, HWND hwndInsertBehind, + LONG x, LONG y, + LONG cx, LONG cy, + ULONG fl) +{ + SWP swpDesktop, swp; + // Get desktop area + WinQueryWindowPos(HWND_DESKTOP, &swpDesktop); + + if ((fl & SWP_MOVE) && (fl & SWP_SIZE)) + { + // If both moving and sizing, then change size and pos now!! + if (x+cx>swpDesktop.cx) + x = swpDesktop.cx - cx; + if (x<0) + x = 0; + if (y<0) + y = 0; + if (y+cy>swpDesktop.cy) + y = swpDesktop.cy - cy; + return WinSetWindowPos(hwnd, hwndInsertBehind, x, y, cx, cy, fl); + } else + if (fl & SWP_MOVE) + { + // Just moving + WinQueryWindowPos(hwnd, &swp); + if (x+swp.cx>swpDesktop.cx) + x = swpDesktop.cx - swp.cx; + if (x<0) + x = 0; + if (y<0) + y = 0; + if (y+swp.cy>swpDesktop.cy) + y = swpDesktop.cy - swp.cy; + return WinSetWindowPos(hwnd, hwndInsertBehind, x, y, cx, cy, fl); + } else + if (fl & SWP_SIZE) + { + // Just sizing + WinQueryWindowPos(hwnd, &swp); + x = swp.x; + y = swp.y; + if (x+cx>swpDesktop.cx) + x = swpDesktop.cx - cx; + if (x<0) + x = 0; + if (y<0) + y = 0; + if (y+cy>swpDesktop.cy) + y = swpDesktop.cy - cy; + return WinSetWindowPos(hwnd, hwndInsertBehind, x, y, cx, cy, fl | SWP_MOVE); + } else + return WinSetWindowPos(hwnd, hwndInsertBehind, x, y, cx, cy, fl); +} + +static UniChar NativeCharToUniChar(int chcode) +{ + UniChar ucResult = (UniChar) chcode; + int rc; + UconvObject ucoTemp; + char achFrom[2]; + char *pchFrom; + size_t iFromCount; + UniChar aucTo[10]; + UniChar *pucTo; + size_t iToCount; + size_t iNonIdentical; + + // Create unicode convert object + rc = UniCreateUconvObject(L"", &ucoTemp); + if (rc!=ULS_SUCCESS) + { + // Could not create convert object! + return ucResult; + } + + // Convert language code string to unicode string + achFrom[0] = (char) chcode; + achFrom[1] = 0; + iFromCount = sizeof(char) * 2; + iToCount = sizeof(UniChar) * 2; + pucTo = &(aucTo[0]); + pchFrom = &(achFrom[0]); + + rc = UniUconvToUcs(ucoTemp, + &pchFrom, + &iFromCount, + &pucTo, + &iToCount, + &iNonIdentical); + + if (rc!=ULS_SUCCESS) + { + // Could not convert language code to UCS string! + UniFreeUconvObject(ucoTemp); + return ucResult; + } + + UniFreeUconvObject(ucoTemp); + +#ifdef DEBUG_BUILD + printf("%02x converted to %02x\n", (int) chcode, (int) (aucTo[0])); +#endif + + return aucTo[0]; +} + +///////////////////////////////////////////////////////////////////// +// +// TranslateKey +// +// This creates SDL Keycodes from VK_ and hardware scan codes +// +///////////////////////////////////////////////////////////////////// +static SDL_keysym *TranslateKey(int vkey, int chcode, int scancode, SDL_keysym *keysym, int iPressed) +{ + keysym->scancode = (unsigned char) scancode; + keysym->mod = KMOD_NONE; + keysym->unicode = 0; + + if (iPressed && SDL_TranslateUNICODE) + { + if (chcode) + keysym->unicode = NativeCharToUniChar(chcode); + else + keysym->unicode = vkey; + } + + keysym->sym = HWScanKeyMap[scancode]; + + // Now stuffs based on state of shift key(s)! + if (vkey == VK_SHIFT) + { + iShiftIsPressed = iPressed; + } + + if ((iShiftIsPressed) && (SDL_TranslateUNICODE)) + { + // Change syms, if Unicode stuff is required + // I think it's silly, but it's SDL... + switch (keysym->sym) + { + case SDLK_BACKQUOTE: + keysym->sym = '~'; + break; + case SDLK_1: + keysym->sym = SDLK_EXCLAIM; + break; + case SDLK_2: + keysym->sym = SDLK_AT; + break; + case SDLK_3: + keysym->sym = SDLK_HASH; + break; + case SDLK_4: + keysym->sym = SDLK_DOLLAR; + break; + case SDLK_5: + keysym->sym = '%'; + break; + case SDLK_6: + keysym->sym = SDLK_CARET; + break; + case SDLK_7: + keysym->sym = SDLK_AMPERSAND; + break; + case SDLK_8: + keysym->sym = SDLK_ASTERISK; + break; + case SDLK_9: + keysym->sym = SDLK_LEFTPAREN; + break; + case SDLK_0: + keysym->sym = SDLK_RIGHTPAREN; + break; + case SDLK_MINUS: + keysym->sym = SDLK_UNDERSCORE; + break; + case SDLK_PLUS: + keysym->sym = SDLK_EQUALS; + break; + + case SDLK_LEFTBRACKET: + keysym->sym = '{'; + break; + case SDLK_RIGHTBRACKET: + keysym->sym = '}'; + break; + + case SDLK_SEMICOLON: + keysym->sym = SDLK_COLON; + break; + case SDLK_QUOTE: + keysym->sym = SDLK_QUOTEDBL; + break; + case SDLK_BACKSLASH: + keysym->sym = '|'; + break; + + case SDLK_COMMA: + keysym->sym = SDLK_LESS; + break; + case SDLK_PERIOD: + keysym->sym = SDLK_GREATER; + break; + case SDLK_SLASH: + keysym->sym = SDLK_QUESTION; + break; + + default: + break; + } + } + return keysym; +} + +#define CONVERTMOUSEPOSITION() \ + /* We have to inverse the mouse position, because every non-os/2 system */ \ + /* has a coordinate system where the (0;0) is the top-left corner, */ \ + /* while on os/2 it's the bottom left corner! */ \ + if (FSLib_QueryFSMode(hwnd)) \ + { \ + /* We're in FS mode! */ \ + /* In FS mode our window is as big as fullscreen mode, but not necessary as */ \ + /* big as the source buffer (can be bigger) */ \ + /* So, limit mouse pos to source buffer size! */ \ + if (ppts->x<0) ppts->x = 0; \ + if (ppts->y<0) ppts->y = 0; \ + if (ppts->x>=pVideo->hidden->SrcBufferDesc.uiXResolution) ppts->x = pVideo->hidden->SrcBufferDesc.uiXResolution-1; \ + if (ppts->y>=pVideo->hidden->SrcBufferDesc.uiYResolution) ppts->y = pVideo->hidden->SrcBufferDesc.uiYResolution-1; \ + pVideo->hidden->iSkipWMMOUSEMOVE++; /* Don't take next WM_MOUSEMOVE into account! */ \ + ptl.x = ppts->x; ptl.y = ppts->y; \ + WinMapWindowPoints(pVideo->hidden->hwndClient, HWND_DESKTOP, &ptl, 1); \ + WinSetPointerPos(HWND_DESKTOP, ptl.x, ptl.y); \ + /* Then convert OS/2 position to SDL position */ \ + ppts->y = pVideo->hidden->SrcBufferDesc.uiYResolution - ppts->y - 1; \ + } else \ + { \ + SWP swpClient; \ + /* We're in windowed mode! */ \ + WinQueryWindowPos(pVideo->hidden->hwndClient, &swpClient); \ + /* Convert OS/2 mouse position to SDL position, and also scale it! */ \ + (ppts->x) = (ppts->x) * pVideo->hidden->SrcBufferDesc.uiXResolution / swpClient.cx; \ + (ppts->y) = (ppts->y) * pVideo->hidden->SrcBufferDesc.uiYResolution / swpClient.cy; \ + (ppts->y) = pVideo->hidden->SrcBufferDesc.uiYResolution - (ppts->y) - 1; \ + } + + + +///////////////////////////////////////////////////////////////////// +// +// WndProc +// +// This is the message processing window procedure for the +// SDLWindowClass, which is the client window in our application. +// It handles switching back and away from the app (taking care of +// going out and back to and from fullscreen mode), sending keystrokes +// and mouse events to where it has to be sent, etc... +// +///////////////////////////////////////////////////////////////////// +static MRESULT EXPENTRY WndProc( HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2) +{ + HPS ps; + RECTL rcl; + SDL_VideoDevice *pVideo = NULL; + + switch (msg) + { + case WM_CHAR: // Keypress notification +#ifdef DEBUG_BUILD +// printf("WM_CHAR\n"); fflush(stdout); +#endif + pVideo = WinQueryWindowPtr(hwnd, 0); + if (pVideo) + { + /* + // We skip repeated keys: + if (CHARMSG(&msg)->cRepeat>1) + { +#ifdef DEBUG_BUILD +// printf("Repeated key (%d), skipping...\n", CHARMSG(&msg)->cRepeat); fflush(stdout); +#endif + return (MRESULT) TRUE; + } + */ + + // If it's not repeated, then let's see if its pressed or released! + if (SHORT1FROMMP(mp1) & KC_KEYUP) + { + // A key has been released + SDL_keysym keysym; + +#ifdef DEBUG_BUILD +// printf("WM_CHAR, keyup, code is [0x%0x]\n", CHAR4FROMMP(mp1)); // HW scan code +#endif + + // One problem is with F1, which gets only the keyup message because + // it is a system key. + // So, when we get keyup message, we simulate keydown too! + // UPDATE: + // This problem should be solved now, that the accelerator keys are + // disabled for this window! + /* + if (SHORT2FROMMP(mp2)==VK_F1) + { + SDL_PrivateKeyboard(SDL_PRESSED, TranslateKey(SHORT2FROMMP(mp2), // VK_ code + SHORT1FROMMP(mp2), // Character code + CHAR4FROMMP(mp1), // HW Scan code + &keysym,0)); + }*/ + + SDL_PrivateKeyboard(SDL_RELEASED, TranslateKey(SHORT2FROMMP(mp2), // VK_ code + SHORT1FROMMP(mp2), // Character code + CHAR4FROMMP(mp1), // HW Scan code + &keysym,0)); + + } else + { + // A key has been pressed + SDL_keysym keysym; + +#ifdef DEBUG_BUILD +// printf("WM_CHAR, keydown, code is [0x%0x]\n", CHAR4FROMMP(mp1)); // HW scan code +#endif + // Check for fastkeys: ALT+HOME to toggle FS mode + // ALT+END to close app + if ((SHORT1FROMMP(mp1) & KC_ALT) && + (SHORT2FROMMP(mp2) == VK_HOME)) + { +#ifdef DEBUG_BUILD + printf(" Pressed ALT+HOME!\n"); fflush(stdout); +#endif + // Only switch between fullscreen and back if it's not + // a resizable mode! + if ( + (!pVideo->hidden->pSDLSurface) || + ((pVideo->hidden->pSDLSurface) + && ((pVideo->hidden->pSDLSurface->flags & SDL_RESIZABLE)==0) + ) + ) + FSLib_ToggleFSMode(hwnd, !FSLib_QueryFSMode(hwnd)); +#ifdef DEBUG_BUILD + else + printf(" Resizable mode, so discarding ALT+HOME!\n"); fflush(stdout); +#endif + } else + if ((SHORT1FROMMP(mp1) & KC_ALT) && + (SHORT2FROMMP(mp2) == VK_END)) + { +#ifdef DEBUG_BUILD + printf(" Pressed ALT+END!\n"); fflush(stdout); +#endif + // Close window, and get out of loop! + // Also send event to SDL application, but we won't + // wait for it to be processed! + SDL_PrivateQuit(); + WinPostMsg(hwnd, WM_QUIT, 0, 0); + } else + { + + SDL_PrivateKeyboard(SDL_PRESSED, TranslateKey(SHORT2FROMMP(mp2), // VK_ code + SHORT1FROMMP(mp2), // Character code + CHAR4FROMMP(mp1), // HW Scan code + &keysym,1)); + + } + } + } + return (MRESULT) TRUE; + + case WM_TRANSLATEACCEL: + { + PQMSG pqmsg; + pqmsg = (PQMSG) mp1; + if (mp1) + { + if (pqmsg->msg == WM_CHAR) + { + // WM_CHAR message! + // Let's filter the ALT keypress and all other acceleration keys! + return (MRESULT) FALSE; + } + } + break; // Default processing (pass to parent until frame control) + } + + case WM_PAINT: // Window redraw! +#ifdef DEBUG_BUILD + printf("WM_PAINT (0x%x)\n", hwnd); fflush(stdout); +#endif + ps = WinBeginPaint(hwnd,0,&rcl); + pVideo = FSLib_GetUserParm(hwnd); + if (pVideo) + { + if (!pVideo->hidden->pSDLSurface) + { + RECTL rclRect; + // So, don't blit now! +#ifdef DEBUG_BUILD + printf("WM_PAINT : Skipping blit while resizing (Pre!)!\n"); fflush(stdout); +#endif + WinQueryWindowRect(hwnd, &rclRect); + // Fill with black + WinFillRect(ps, &rclRect, CLR_BLACK); + } else + { + if (DosRequestMutexSem(pVideo->hidden->hmtxUseSrcBuffer, 1000)==NO_ERROR) + { + int iTop, iLeft, iWidth, iHeight; + int iXScaleError, iYScaleError; + int iXScaleError2, iYScaleError2; + SWP swp; + + // Re-blit the modified area! + // For this, we have to calculate the points, scaled! + WinQueryWindowPos(hwnd, &swp); +#ifdef DEBUG_BUILD + printf("WM_PAINT : WinSize: %d %d, BufSize: %d %d\n", + swp.cx, + swp.cy, + pVideo->hidden->SrcBufferDesc.uiXResolution, + pVideo->hidden->SrcBufferDesc.uiYResolution + ); + fflush(stdout); +#endif + +#ifndef RESIZE_EVEN_IF_RESIZABLE + // But only blit if the window is not resizable, or if + // the window is resizable and the source buffer size is the + // same as the destination buffer size! + if ((!pVideo->hidden->pSDLSurface) || + ((pVideo->hidden->pSDLSurface) && + (pVideo->hidden->pSDLSurface->flags & SDL_RESIZABLE) && + ((swp.cx != pVideo->hidden->SrcBufferDesc.uiXResolution) || + (swp.cy != pVideo->hidden->SrcBufferDesc.uiYResolution) + ) && + (!FSLib_QueryFSMode(hwnd)) + ) + ) + { + RECTL rclRect; + // Resizable surface and in resizing! + // So, don't blit now! +#ifdef DEBUG_BUILD + printf("WM_PAINT : Skipping blit while resizing!\n"); fflush(stdout); +#endif + WinQueryWindowRect(hwnd, &rclRect); + // Fill with black + WinFillRect(ps, &rclRect, CLR_BLACK); + } else +#endif + { + + iXScaleError = (pVideo->hidden->SrcBufferDesc.uiXResolution-1) / swp.cx; + iYScaleError = (pVideo->hidden->SrcBufferDesc.uiYResolution-1) / swp.cy; + if (iXScaleError<0) iXScaleError = 0; + if (iYScaleError<0) iYScaleError = 0; + iXScaleError2 = (swp.cx-1)/(pVideo->hidden->SrcBufferDesc.uiXResolution); + iYScaleError2 = (swp.cy-1)/(pVideo->hidden->SrcBufferDesc.uiYResolution); + if (iXScaleError2<0) iXScaleError2 = 0; + if (iYScaleError2<0) iYScaleError2 = 0; + + iTop = (swp.cy - rcl.yTop) * pVideo->hidden->SrcBufferDesc.uiYResolution / swp.cy - iYScaleError; + iLeft = rcl.xLeft * pVideo->hidden->SrcBufferDesc.uiXResolution / swp.cx - iXScaleError; + iWidth = ((rcl.xRight-rcl.xLeft) * pVideo->hidden->SrcBufferDesc.uiXResolution + swp.cx-1) + / swp.cx + 2*iXScaleError; + iHeight = ((rcl.yTop-rcl.yBottom) * pVideo->hidden->SrcBufferDesc.uiYResolution + swp.cy-1) + / swp.cy + 2*iYScaleError; + + iWidth+=iXScaleError2; + iHeight+=iYScaleError2; + + if (iTop<0) iTop = 0; + if (iLeft<0) iLeft = 0; + if (iTop+iHeight>pVideo->hidden->SrcBufferDesc.uiYResolution) iHeight = pVideo->hidden->SrcBufferDesc.uiYResolution-iTop; + if (iLeft+iWidth>pVideo->hidden->SrcBufferDesc.uiXResolution) iWidth = pVideo->hidden->SrcBufferDesc.uiXResolution-iLeft; + +#ifdef DEBUG_BUILD + printf("WM_PAINT : BitBlt: %d %d -> %d %d (Buf %d x %d)\n", + iTop, iLeft, iWidth, iHeight, + pVideo->hidden->SrcBufferDesc.uiXResolution, + pVideo->hidden->SrcBufferDesc.uiYResolution + ); + fflush(stdout); +#endif + + FSLIB_BITBLT(hwnd, pVideo->hidden->pchSrcBuffer, iTop, iLeft, iWidth, iHeight); + } + + DosReleaseMutexSem(pVideo->hidden->hmtxUseSrcBuffer); + } + } + } +#ifdef DEBUG_BUILD + else + { + printf("WM_PAINT : No pVideo!\n"); fflush(stdout); + } +#endif + WinEndPaint(ps); +#ifdef DEBUG_BUILD + printf("WM_PAINT : Done.\n"); + fflush(stdout); +#endif + return 0; + + case WM_SIZE: + { +#ifdef DEBUG_BUILD + printf("WM_SIZE : (%d %d)\n", + SHORT1FROMMP(mp2), SHORT2FROMMP(mp2)); fflush(stdout); +#endif + iWindowSizeX = SHORT1FROMMP(mp2); + iWindowSizeY = SHORT2FROMMP(mp2); + bWindowResized = 1; + + // Make sure the window will be redrawn + WinInvalidateRegion(hwnd, NULL, TRUE); + } + break; + + case WM_FSLIBNOTIFICATION: +#ifdef DEBUG_BUILD + printf("WM_FSLIBNOTIFICATION\n"); fflush(stdout); +#endif + if ((int)mp1 == FSLN_TOGGLEFSMODE) + { + // FS mode changed, reblit image! + pVideo = FSLib_GetUserParm(hwnd); + if (pVideo) + { + if (!pVideo->hidden->pSDLSurface) + { + // Resizable surface and in resizing! + // So, don't blit now! +#ifdef DEBUG_BUILD + printf("WM_FSLIBNOTIFICATION : Can not blit if there is no surface, doing nothing.\n"); fflush(stdout); +#endif + } else + { + if (DosRequestMutexSem(pVideo->hidden->hmtxUseSrcBuffer, 1000)==NO_ERROR) + { + if (pVideo->hidden->pSDLSurface) + { +#ifndef RESIZE_EVEN_IF_RESIZABLE + SWP swp; + + // But only blit if the window is not resizable, or if + // the window is resizable and the source buffer size is the + // same as the destination buffer size! + WinQueryWindowPos(hwnd, &swp); + if ((!pVideo->hidden->pSDLSurface) || + ( + (pVideo->hidden->pSDLSurface) && + (pVideo->hidden->pSDLSurface->flags & SDL_RESIZABLE) && + ((swp.cx != pVideo->hidden->SrcBufferDesc.uiXResolution) || + (swp.cy != pVideo->hidden->SrcBufferDesc.uiYResolution) + ) && + (!FSLib_QueryFSMode(hwnd)) + ) + ) + { + // Resizable surface and in resizing! + // So, don't blit now! +#ifdef DEBUG_BUILD + printf("WM_FSLIBNOTIFICATION : Cannot blit while resizing, doing nothing.\n"); fflush(stdout); +#endif + } else +#endif + { +#ifdef DEBUG_BUILD + printf("WM_FSLIBNOTIFICATION : Blitting!\n"); fflush(stdout); +#endif + FSLIB_BITBLT(hwnd, pVideo->hidden->pchSrcBuffer, + 0, 0, + pVideo->hidden->SrcBufferDesc.uiXResolution, + pVideo->hidden->SrcBufferDesc.uiYResolution); + } + } +#ifdef DEBUG_BUILD + else + printf("WM_FSLIBNOTIFICATION : No public surface!\n"); fflush(stdout); +#endif + + DosReleaseMutexSem(pVideo->hidden->hmtxUseSrcBuffer); + } + } + } + } + return (MPARAM) 1; + + case WM_ACTIVATE: +#ifdef DEBUG_BUILD + printf("WM_ACTIVATE\n"); fflush(stdout); +#endif + + pVideo = FSLib_GetUserParm(hwnd); + if (pVideo) + { + pVideo->hidden->fInFocus = (int) mp1; + if (pVideo->hidden->fInFocus) + { + // Went into focus + if ((pVideo->hidden->iMouseVisible) && (!bMouseCaptured)) + WinSetPointer(HWND_DESKTOP, WinQuerySysPointer(HWND_DESKTOP, SPTR_ARROW, FALSE)); + else + WinSetPointer(HWND_DESKTOP, NULL); + + if (bMouseCapturable) + { + // Re-capture the mouse, if we captured it before! + WinSetCapture(HWND_DESKTOP, hwnd); + bMouseCaptured = 1; + { + SWP swpClient; + POINTL ptl; + // Center the mouse to the middle of the window! + WinQueryWindowPos(pVideo->hidden->hwndClient, &swpClient); + ptl.x = 0; ptl.y = 0; + WinMapWindowPoints(pVideo->hidden->hwndClient, HWND_DESKTOP, &ptl, 1); + pVideo->hidden->iSkipWMMOUSEMOVE++; /* Don't take next WM_MOUSEMOVE into account! */ + WinSetPointerPos(HWND_DESKTOP, + ptl.x + swpClient.cx/2, + ptl.y + swpClient.cy/2); + } + } + } else + { + // Went out of focus + WinSetPointer(HWND_DESKTOP, WinQuerySysPointer(HWND_DESKTOP, SPTR_ARROW, FALSE)); + + if (bMouseCaptured) + { + // Release the mouse + WinSetCapture(HWND_DESKTOP, hwnd); + bMouseCaptured = 0; + } + } + } +#ifdef DEBUG_BUILD + printf("WM_ACTIVATE done\n"); fflush(stdout); +#endif + + break; + + case WM_BUTTON1DOWN: +#ifdef DEBUG_BUILD + printf("WM_BUTTON1DOWN\n"); fflush(stdout); +#endif + + pVideo = FSLib_GetUserParm(hwnd); + if (pVideo) + { + SDL_PrivateMouseButton(SDL_PRESSED, + SDL_BUTTON_LEFT, + 0, 0); // Don't report mouse movement! + + if (bMouseCapturable) + { + // We should capture the mouse! + if (!bMouseCaptured) + { + WinSetCapture(HWND_DESKTOP, hwnd); + WinSetPointer(HWND_DESKTOP, NULL); + bMouseCaptured = 1; + { + SWP swpClient; + POINTL ptl; + // Center the mouse to the middle of the window! + WinQueryWindowPos(pVideo->hidden->hwndClient, &swpClient); + ptl.x = 0; ptl.y = 0; + WinMapWindowPoints(pVideo->hidden->hwndClient, HWND_DESKTOP, &ptl, 1); + pVideo->hidden->iSkipWMMOUSEMOVE++; /* Don't take next WM_MOUSEMOVE into account! */ + WinSetPointerPos(HWND_DESKTOP, + ptl.x + swpClient.cx/2, + ptl.y + swpClient.cy/2); + } + } + } + } + break; + case WM_BUTTON1UP: +#ifdef DEBUG_BUILD + printf("WM_BUTTON1UP\n"); fflush(stdout); +#endif + SDL_PrivateMouseButton(SDL_RELEASED, + SDL_BUTTON_LEFT, + 0, 0); // Don't report mouse movement! + break; + case WM_BUTTON2DOWN: +#ifdef DEBUG_BUILD + printf("WM_BUTTON2DOWN\n"); fflush(stdout); +#endif + + pVideo = FSLib_GetUserParm(hwnd); + if (pVideo) + { + SDL_PrivateMouseButton(SDL_PRESSED, + SDL_BUTTON_RIGHT, + 0, 0); // Don't report mouse movement! + + if (bMouseCapturable) + { + // We should capture the mouse! + if (!bMouseCaptured) + { + WinSetCapture(HWND_DESKTOP, hwnd); + WinSetPointer(HWND_DESKTOP, NULL); + bMouseCaptured = 1; + { + SWP swpClient; + POINTL ptl; + // Center the mouse to the middle of the window! + WinQueryWindowPos(pVideo->hidden->hwndClient, &swpClient); + ptl.x = 0; ptl.y = 0; + WinMapWindowPoints(pVideo->hidden->hwndClient, HWND_DESKTOP, &ptl, 1); + pVideo->hidden->iSkipWMMOUSEMOVE++; /* Don't take next WM_MOUSEMOVE into account! */ + WinSetPointerPos(HWND_DESKTOP, + ptl.x + swpClient.cx/2, + ptl.y + swpClient.cy/2); + } + } + } + + } + break; + case WM_BUTTON2UP: +#ifdef DEBUG_BUILD + printf("WM_BUTTON2UP\n"); fflush(stdout); +#endif + SDL_PrivateMouseButton(SDL_RELEASED, + SDL_BUTTON_RIGHT, + 0, 0); // Don't report mouse movement! + break; + case WM_BUTTON3DOWN: +#ifdef DEBUG_BUILD + printf("WM_BUTTON3DOWN\n"); fflush(stdout); +#endif + + pVideo = FSLib_GetUserParm(hwnd); + if (pVideo) + { + SDL_PrivateMouseButton(SDL_PRESSED, + SDL_BUTTON_MIDDLE, + 0, 0); // Don't report mouse movement! + + if (bMouseCapturable) + { + // We should capture the mouse! + if (!bMouseCaptured) + { + WinSetCapture(HWND_DESKTOP, hwnd); + WinSetPointer(HWND_DESKTOP, NULL); + bMouseCaptured = 1; + { + SWP swpClient; + POINTL ptl; + // Center the mouse to the middle of the window! + WinQueryWindowPos(pVideo->hidden->hwndClient, &swpClient); + ptl.x = 0; ptl.y = 0; + WinMapWindowPoints(pVideo->hidden->hwndClient, HWND_DESKTOP, &ptl, 1); + pVideo->hidden->iSkipWMMOUSEMOVE++; /* Don't take next WM_MOUSEMOVE into account! */ + WinSetPointerPos(HWND_DESKTOP, + ptl.x + swpClient.cx/2, + ptl.y + swpClient.cy/2); + } + } + } + } + break; + case WM_BUTTON3UP: +#ifdef DEBUG_BUILD + printf("WM_BUTTON3UP\n"); fflush(stdout); +#endif + SDL_PrivateMouseButton(SDL_RELEASED, + SDL_BUTTON_MIDDLE, + 0, 0); // Don't report mouse movement! + break; + case WM_MOUSEMOVE: +#ifdef DEBUG_BUILD +// printf("WM_MOUSEMOVE\n"); fflush(stdout); +#endif + + pVideo = FSLib_GetUserParm(hwnd); + if (pVideo) + { + if (pVideo->hidden->iSkipWMMOUSEMOVE) + { + pVideo->hidden->iSkipWMMOUSEMOVE--; + } else + { + POINTS *ppts = (POINTS *) (&mp1); + POINTL ptl; + + if (bMouseCaptured) + { + SWP swpClient; + + WinQueryWindowPos(pVideo->hidden->hwndClient, &swpClient); + + // Send relative mouse position, and re-center the mouse + // Reposition the mouse to the center of the screen/window + SDL_PrivateMouseMotion(0, // Buttons not changed + 1, // Relative position + ppts->x - (swpClient.cx/2), + (swpClient.cy/2) - ppts->y); + + ptl.x = 0; ptl.y = 0; + WinMapWindowPoints(pVideo->hidden->hwndClient, HWND_DESKTOP, &ptl, 1); + pVideo->hidden->iSkipWMMOUSEMOVE++; /* Don't take next WM_MOUSEMOVE into account! */ + // Center the mouse to the middle of the window! + WinSetPointerPos(HWND_DESKTOP, + ptl.x + swpClient.cx/2, + ptl.y + swpClient.cy/2); + } else + { + CONVERTMOUSEPOSITION(); + + // Send absolute mouse position + SDL_PrivateMouseMotion(0, // Buttons not changed + 0, // Absolute position + ppts->x, + ppts->y); + } + } + if ((pVideo->hidden->iMouseVisible) && (!bMouseCaptured)) + { +#ifdef DEBUG_BUILD +// printf("WM_MOUSEMOVE : ptr = %p\n", hptrGlobalPointer); fflush(stdout); +#endif + + if (hptrGlobalPointer) + WinSetPointer(HWND_DESKTOP, hptrGlobalPointer); + else + WinSetPointer(HWND_DESKTOP, WinQuerySysPointer(HWND_DESKTOP, SPTR_ARROW, FALSE)); + } + else + { + WinSetPointer(HWND_DESKTOP, NULL); + } + } +#ifdef DEBUG_BUILD +// printf("WM_MOUSEMOVE done\n"); fflush(stdout); +#endif + + return (MRESULT) FALSE; + case WM_CLOSE: // Window close +#ifdef DEBUG_BUILD + printf("WM_CLOSE\n"); fflush(stdout); +#endif + + pVideo = FSLib_GetUserParm(hwnd); + if (pVideo) + { + // Send Quit message to the SDL application! + SDL_PrivateQuit(); + return 0; + } + break; + +#ifdef BITBLT_IN_WINMESSAGEPROC + case WM_UPDATERECTSREQUEST: + pVideo = FSLib_GetUserParm(hwnd); + if ((pVideo) && (pVideo->hidden->pSDLSurface)) + { + if (DosRequestMutexSem(pVideo->hidden->hmtxUseSrcBuffer, SEM_INDEFINITE_WAIT)==NO_ERROR) + { + int numrects; + SDL_Rect *rects; + int i; + SWP swp; + + numrects = (int) mp1; + rects = (SDL_Rect *) mp2; + + WinQueryWindowPos(hwnd, &swp); +#ifndef RESIZE_EVEN_IF_RESIZABLE + if ((!pVideo->hidden->pSDLSurface) || + ( + (pVideo->hidden->pSDLSurface) && + (pVideo->hidden->pSDLSurface->flags & SDL_RESIZABLE) && + ((swp.cx != pVideo->hidden->SrcBufferDesc.uiXResolution) || + (swp.cy != pVideo->hidden->SrcBufferDesc.uiYResolution) + ) && + (!FSLib_QueryFSMode(hwnd)) + ) + ) + { + // Resizable surface and in resizing! + // So, don't blit now! +#ifdef DEBUG_BUILD + printf("[WM_UPDATERECTSREQUEST] : Skipping blit while resizing!\n"); fflush(stdout); +#endif + } else +#endif + { +#ifdef DEBUG_BUILD + printf("[WM_UPDATERECTSREQUEST] : Blitting!\n"); fflush(stdout); +#endif + + // Blit the changed areas + for (i=0; i<numrects; i++) + FSLIB_BITBLT(hwnd, pVideo->hidden->pchSrcBuffer, + rects[i].y, rects[i].x, rects[i].w, rects[i].h); + } + DosReleaseMutexSem(pVideo->hidden->hmtxUseSrcBuffer); + } + } + return 0; +#endif + + default: +#ifdef DEBUG_BUILD + printf("Unhandled: %x\n", msg); fflush(stdout); +#endif + + break; + } + // Run the default window procedure for unhandled stuffs + return WinDefWindowProc(hwnd, msg, mp1, mp2); +} + +///////////////////////////////////////////////////////////////////// +// +// FrameWndProc +// +// This is the message processing window procedure for the +// frame window of SDLWindowClass. +// +///////////////////////////////////////////////////////////////////// +static MRESULT EXPENTRY FrameWndProc( HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2) +{ + PFNWP pOldFrameProc; + MRESULT result; + PTRACKINFO ti; + int cx, cy, ncx, ncy; + RECTL rclTemp; + PSWP pswpTemp; + + SDL_VideoDevice *pVideo = NULL; + + pVideo = (SDL_VideoDevice *) WinQueryWindowULong(hwnd, QWL_USER); + + pOldFrameProc = pVideo->hidden->pfnOldFrameProc; + + if ((pVideo->hidden->bProportionalResize) && + (msg==WM_ADJUSTWINDOWPOS) && + (!FSLib_QueryFSMode(pVideo->hidden->hwndClient)) + ) + { + pswpTemp = (PSWP) mp1; + + /* Resizing? */ + if (pswpTemp->fl & SWP_SIZE) + { + /* Calculate client size */ + rclTemp.xLeft = pswpTemp->x; + rclTemp.xRight = pswpTemp->x + pswpTemp->cx; + rclTemp.yBottom = pswpTemp->y; + rclTemp.yTop = pswpTemp->y + pswpTemp->cy; + WinCalcFrameRect(hwnd, &rclTemp, TRUE); + + ncx = cx = rclTemp.xRight - rclTemp.xLeft; + ncy = cy = rclTemp.yTop - rclTemp.yBottom; + + /* Calculate new size to keep it proportional */ + + if ((pVideo->hidden->ulResizingFlag & TF_LEFT) || (pVideo->hidden->ulResizingFlag & TF_RIGHT)) + { + /* The window is resized horizontally */ + ncy = pVideo->hidden->SrcBufferDesc.uiYResolution * cx / pVideo->hidden->SrcBufferDesc.uiXResolution; + } else + if ((pVideo->hidden->ulResizingFlag & TF_TOP) || (pVideo->hidden->ulResizingFlag & TF_BOTTOM)) + { + /* The window is resized vertically */ + ncx = pVideo->hidden->SrcBufferDesc.uiXResolution * cy / pVideo->hidden->SrcBufferDesc.uiYResolution; + } + + /* Calculate back frame coordinates */ + rclTemp.xLeft = pswpTemp->x; + rclTemp.xRight = pswpTemp->x + ncx; + rclTemp.yBottom = pswpTemp->y; + rclTemp.yTop = pswpTemp->y + ncy; + WinCalcFrameRect(hwnd, &rclTemp, FALSE); + + /* Store new size/position info */ + pswpTemp->cx = rclTemp.xRight - rclTemp.xLeft; + + if (!(pVideo->hidden->ulResizingFlag & TF_TOP)) + { + pswpTemp->y = pswpTemp->y + pswpTemp->cy - (rclTemp.yTop - rclTemp.yBottom); + pswpTemp->cy = rclTemp.yTop - rclTemp.yBottom; + } else + { + pswpTemp->cy = rclTemp.yTop - rclTemp.yBottom; + } + } + } + + result = (*pOldFrameProc)(hwnd, msg, mp1, mp2); + + if ((pVideo->hidden->bProportionalResize) && (msg==WM_QUERYTRACKINFO)) + { + ti = (PTRACKINFO) mp2; + + /* Store the direction of resizing */ + if ((ti->fs & TF_LEFT) || (ti->fs & TF_RIGHT) || + (ti->fs & TF_TOP) || (ti->fs & TF_BOTTOM)) + pVideo->hidden->ulResizingFlag = ti->fs; + } + + return result; +} + +///////////////////////////////////////////////////////////////////// +// +// PMThreadFunc +// +// This function implements the PM-Thread, which initializes the +// application window itself, the DIVE, and start message processing. +// +///////////////////////////////////////////////////////////////////// +int iNumOfPMThreadInstances = 0; // Global! +static void PMThreadFunc(void *pParm) +{ + SDL_VideoDevice *pVideo = pParm; + HAB hab; + HMQ hmq; + QMSG msg; + ULONG fcf; + +#ifdef DEBUG_BUILD + printf("[PMThreadFunc] : Starting\n"); fflush(stdout); +#endif + + iNumOfPMThreadInstances++; + + // Initialize PM, create a message queue. + + hab=WinInitialize(0); + hmq=WinCreateMsgQueue(hab,0); + if (hmq==0) + { +#ifdef DEBUG_BUILD + printf("[PMThreadFunc] : Could not create message queue!\n"); + printf(" It might be that the application using SDL is not a PM app!\n"); + fflush(stdout); +#endif + pVideo->hidden->iPMThreadStatus = 2; + } else + { + int rc; + RECTL rectl; + + fcf = ulFCFToUse; // Get from global setting + +#ifdef DEBUG_BUILD + printf("[PMThreadFunc] : FSLib_CreateWindow()!\n"); + fflush(stdout); +#endif + + rc = FSLib_CreateWindow(HWND_DESKTOP, 0, &fcf, + "SDL Application", + NULLHANDLE, 0, + &(pVideo->hidden->SrcBufferDesc), + WndProc, + &(pVideo->hidden->hwndClient), + &(pVideo->hidden->hwndFrame)); + +#ifdef DEBUG_BUILD + printf("[PMThreadFunc] : FSLib_CreateWindow() rc = %d\n", rc); + fflush(stdout); +#endif + + if (!rc) + { +#ifdef DEBUG_BUILD + printf("[PMThreadFunc] : Could not create FSLib window!\n"); + fflush(stdout); +#endif + pVideo->hidden->iPMThreadStatus = 3; + } else + { +#ifdef DEBUG_BUILD + printf("[PMThreadFunc] : FSLib_AddUserParm()!\n"); + fflush(stdout); +#endif + + // Store pVideo pointer in window data for client window, so + // it will know the instance to which it belongs to. + FSLib_AddUserParm(pVideo->hidden->hwndClient, pVideo); + + // Now set default image width height and fourcc! +#ifdef DEBUG_BUILD + printf("[PMThreadFunc] : SetWindowPos()!\n"); + fflush(stdout); +#endif + + // Set the position and size of the main window, + // and make it visible! + // Calculate frame window size from client window size + rectl.xLeft = 0; + rectl.yBottom = 0; + rectl.xRight = pVideo->hidden->SrcBufferDesc.uiXResolution; // Noninclusive + rectl.yTop = pVideo->hidden->SrcBufferDesc.uiYResolution; // Noninclusive + WinCalcFrameRect(pVideo->hidden->hwndFrame, &rectl, FALSE); + + SetAccessableWindowPos(pVideo->hidden->hwndFrame, + HWND_TOP, + (WinQuerySysValue (HWND_DESKTOP, SV_CXSCREEN) - (rectl.xRight-rectl.xLeft)) / 2, + (WinQuerySysValue (HWND_DESKTOP, SV_CYSCREEN) - (rectl.yTop-rectl.yBottom)) / 2, + (rectl.xRight-rectl.xLeft), + (rectl.yTop-rectl.yBottom), + SWP_SIZE | SWP_ACTIVATE | SWP_SHOW | SWP_MOVE); + + // Subclass frame procedure and store old window proc address + pVideo->hidden->pfnOldFrameProc = + WinSubclassWindow(pVideo->hidden->hwndFrame, FrameWndProc); + WinSetWindowULong(pVideo->hidden->hwndFrame, QWL_USER, (ULONG) pVideo); + +#ifdef DEBUG_BUILD + printf("[PMThreadFunc] : Entering message loop\n"); fflush(stdout); +#endif + pVideo->hidden->iPMThreadStatus = 1; + + while (WinGetMsg(hab, (PQMSG)&msg, 0, 0, 0)) + WinDispatchMsg(hab, (PQMSG) &msg); + +#ifdef DEBUG_BUILD + printf("[PMThreadFunc] : Leaving message loop\n"); fflush(stdout); +#endif + // We should release the captured the mouse! + if (bMouseCaptured) + { + WinSetCapture(HWND_DESKTOP, NULLHANDLE); + bMouseCaptured = 0; + } + // Destroy our window + WinDestroyWindow(pVideo->hidden->hwndFrame); pVideo->hidden->hwndFrame=NULL; + // Show pointer to make sure it will not be left hidden. + WinSetPointer(HWND_DESKTOP, WinQuerySysPointer(HWND_DESKTOP, SPTR_ARROW, FALSE)); + WinShowPointer(HWND_DESKTOP, TRUE); + } + // Uninitialize PM + WinDestroyMsgQueue(hmq); + // All done! + pVideo->hidden->iPMThreadStatus = 0; + } + WinTerminate(hab); + /* Commented out, should not be needed anymore, because we send it + from WM_CLOSE. + // Notify SDL that it should really die now... + SDL_PrivateQuit(); SDL_PrivateQuit(); SDL_PrivateQuit(); //... :)) + */ +#ifdef DEBUG_BUILD + printf("[PMThreadFunc] : End, status is %d!\n", pVideo->hidden->iPMThreadStatus); fflush(stdout); +#endif + + iNumOfPMThreadInstances--; + + // HACK to prevent zombie and hanging SDL applications, which does not take + // care of closing the window for some reason: + // There are some apps which do not process messages, so do a lot of things + // without noticing that the application should close. To close these, + // I've thought about the following: + // If the window is closed (the execution came here), I wait a bit to + // give time to the app to finish its execution. If it does not, I kill it + // using DosExit(). Brute force, but should work. + if (pVideo->hidden->iPMThreadStatus==0) + { + DosSleep(5000); // Wait 5 secs + // If a new PM thread has been spawned (reinitializing video mode), then all right. + // Otherwise, we have a problem, the app doesn't want to stop. Kill! + if (iNumOfPMThreadInstances==0) + { +#ifdef DEBUG_BUILD + printf("[PMThreadFunc] : It seems that the application haven't terminated itself\n"); fflush(stdout); + printf("[PMThreadFunc] : in the last 5 seconds, so we go berserk.\n"); fflush(stdout); + printf("[PMThreadFunc] : Brute force mode. :) Killing process! Dieeeee...\n"); fflush(stdout); +#endif + DosExit(EXIT_PROCESS, -1); + } + } + _endthread(); +} + +struct WMcursor +{ + HBITMAP hbm; + HPOINTER hptr; + char *pchData; +}; + +/* Free a window manager cursor */ +void os2fslib_FreeWMCursor(_THIS, WMcursor *cursor) +{ + if (cursor) + { + GpiDeleteBitmap(cursor->hbm); + WinDestroyPointer(cursor->hptr); + SDL_free(cursor->pchData); + SDL_free(cursor); + } +} + +/* Local functions to convert the SDL cursor mask into OS/2 format */ +static void memnot(Uint8 *dst, Uint8 *src, int len) +{ + while ( len-- > 0 ) + *dst++ = ~*src++; +} +static void memxor(Uint8 *dst, Uint8 *src1, Uint8 *src2, int len) +{ + while ( len-- > 0 ) + *dst++ = (*src1++)^(*src2++); +} + +/* Create a black/white window manager cursor */ +WMcursor *os2fslib_CreateWMCursor_Win(_THIS, Uint8 *data, Uint8 *mask, + int w, int h, int hot_x, int hot_y) +{ + HPOINTER hptr; + HBITMAP hbm; + BITMAPINFOHEADER bmih; + BMPINFO bmi; + HPS hps; + char *pchTemp; + char *xptr, *aptr; + int maxx, maxy; + int i, run, pad; + WMcursor *pResult; + + maxx = WinQuerySysValue(HWND_DESKTOP, SV_CXPOINTER); + maxy = WinQuerySysValue(HWND_DESKTOP, SV_CYPOINTER); + + // Check for max size! + if ((w>maxx) || (h>maxy)) + return (WMcursor *) NULL; + + pResult = (WMcursor *) SDL_malloc(sizeof(WMcursor)); + if (!pResult) return (WMcursor *) NULL; + + pchTemp = (char *) SDL_malloc((maxx + 7)/8 * maxy*2); + if (!pchTemp) + { + SDL_free(pResult); + return (WMcursor *) NULL; + } + + SDL_memset(pchTemp, 0, (maxx + 7)/8 * maxy*2); + + hps = WinGetPS(_this->hidden->hwndClient); + + bmi.cbFix = sizeof(BITMAPINFOHEADER); + bmi.cx = maxx; + bmi.cy = 2*maxy; + bmi.cPlanes = 1; + bmi.cBitCount = 1; + bmi.argbColor[0].bBlue = 0x00; + bmi.argbColor[0].bGreen = 0x00; + bmi.argbColor[0].bRed = 0x00; + bmi.argbColor[1].bBlue = 0x00; + bmi.argbColor[1].bGreen = 0x00; + bmi.argbColor[1].bRed = 0xff; + + SDL_memset(&bmih, 0, sizeof(BITMAPINFOHEADER)); + bmih.cbFix = sizeof(BITMAPINFOHEADER); + bmih.cx = maxx; + bmih.cy = 2*maxy; + bmih.cPlanes = 1; + bmih.cBitCount = 1; + + run = (w+7)/8; + pad = (maxx+7)/8 - run; + + for (i=0; i<h; i++) + { + xptr = pchTemp + (maxx+7)/8 * (maxy-1-i); + aptr = pchTemp + (maxx+7)/8 * (maxy+maxy-1-i); + memxor(xptr, data, mask, run); + xptr += run; + data += run; + memnot(aptr, mask, run); + mask += run; + aptr += run; + SDL_memset(xptr, 0, pad); + xptr += pad; + SDL_memset(aptr, ~0, pad); + aptr += pad; + } + pad += run; + for (i=h ; i<maxy; i++ ) + { + xptr = pchTemp + (maxx+7)/8 * (maxy-1-i); + aptr = pchTemp + (maxx+7)/8 * (maxy+maxy-1-i); + + SDL_memset(xptr, 0, (maxx+7)/8); + xptr += (maxx+7)/8; + SDL_memset(aptr, ~0, (maxx+7)/8); + aptr += (maxx+7)/8; + } + + hbm = GpiCreateBitmap(hps, (PBITMAPINFOHEADER2)&bmih, CBM_INIT, (PBYTE) pchTemp, (PBITMAPINFO2)&bmi); + hptr = WinCreatePointer(HWND_DESKTOP, hbm, TRUE, hot_x, maxy - hot_y - 1); + +#ifdef DEBUG_BUILD + printf("HotSpot : %d ; %d\n", hot_x, hot_y); + printf("HPS returned : %x\n", (ULONG)hps); + printf("HBITMAP returned : %x\n", (ULONG)hbm); + printf("HPOINTER returned: %x\n", (ULONG)hptr); +#endif + + WinReleasePS(hps); + +#ifdef DEBUG_BUILD + printf("[CreateWMCursor] : ptr = %p\n", hptr); fflush(stdout); +#endif + + pResult->hptr = hptr; + pResult->hbm = hbm; + pResult->pchData = pchTemp; + +#ifdef DEBUG_BUILD + printf("[CreateWMCursor] : ptr = %p return.\n", hptr); fflush(stdout); +#endif + + return (WMcursor *) pResult; +} + +WMcursor *os2fslib_CreateWMCursor_FS(_THIS, Uint8 *data, Uint8 *mask, + int w, int h, int hot_x, int hot_y) +{ +#ifdef DEBUG_BUILD + printf("[CreateWMCursor_FS] : returning pointer NULL\n"); fflush(stdout); +#endif + + // In FS mode we'll use software cursor + return (WMcursor *) NULL; +} + +/* Show the specified cursor, or hide if cursor is NULL */ +int os2fslib_ShowWMCursor(_THIS, WMcursor *cursor) +{ +#ifdef DEBUG_BUILD + printf("[ShowWMCursor] : ptr = %p\n", cursor); fflush(stdout); +#endif + + if (cursor) + { + WinSetPointer(HWND_DESKTOP, cursor->hptr); + hptrGlobalPointer = cursor->hptr; + _this->hidden->iMouseVisible = 1; + } + else + { + WinSetPointer(HWND_DESKTOP, FALSE); + hptrGlobalPointer = NULL; + _this->hidden->iMouseVisible = 0; + } + +#ifdef DEBUG_BUILD + printf("[ShowWMCursor] : ptr = %p, DONE\n", cursor); fflush(stdout); +#endif + + return 1; +} + +/* Warp the window manager cursor to (x,y) + If NULL, a mouse motion event is posted internally. + */ +void os2fslib_WarpWMCursor(_THIS, Uint16 x, Uint16 y) +{ + LONG lx, ly; + SWP swpClient; + POINTL ptlPoints; + WinQueryWindowPos(_this->hidden->hwndClient, &swpClient); + ptlPoints.x = swpClient.x; + ptlPoints.y = swpClient.y; + WinMapWindowPoints(_this->hidden->hwndFrame, HWND_DESKTOP, &ptlPoints, 1); + lx = ptlPoints.x + (x*swpClient.cx) / _this->hidden->SrcBufferDesc.uiXResolution; + ly = ptlPoints.y + swpClient.cy - ((y*swpClient.cy) / _this->hidden->SrcBufferDesc.uiYResolution) - 1; + + SDL_PrivateMouseMotion(0, // Buttons not changed + 0, // Absolute position + x, + y); + + WinSetPointerPos(HWND_DESKTOP, lx, ly); + +} + +/* If not NULL, this is called when a mouse motion event occurs */ +void os2fslib_MoveWMCursor(_THIS, int x, int y) +{ + /* + SDL_Rect rect; + +#ifdef DEBUG_BUILD + printf("[MoveWMCursor] : at %d ; %d\n", x, y); fflush(stdout); +#endif + + rect.x = x; + rect.y = y; + rect.w = 32; + rect.h = 32; + os2fslib_UpdateRects(_this, 1, &rect); + // TODO! + */ +} + +/* Determine whether the mouse should be in relative mode or not. + This function is called when the input grab state or cursor + visibility state changes. + If the cursor is not visible, and the input is grabbed, the + driver can place the mouse in relative mode, which may result + in higher accuracy sampling of the pointer motion. + */ +void os2fslib_CheckMouseMode(_THIS) +{ +} + +static void os2fslib_PumpEvents(_THIS) +{ + // Notify SDL that if window has been resized! + if ( + (_this->hidden->pSDLSurface) && + (_this->hidden->pSDLSurface->flags & SDL_RESIZABLE) && + ( + (_this->hidden->SrcBufferDesc.uiXResolution!=iWindowSizeX) || + (_this->hidden->SrcBufferDesc.uiYResolution!=iWindowSizeY) + ) && + (iWindowSizeX>0) && + (iWindowSizeY>0) + ) + { + static time_t prev_time; + time_t curr_time; + + curr_time = time(NULL); + if ((difftime(curr_time, prev_time)>=0.25) || + (bWindowResized)) + { + // Make sure we won't flood the event queue with resize events, + // only send them at 250 msecs! + // (or when the window is resized) +#ifdef DEBUG_BUILD + printf("[os2fslib_PumpEvents] : Calling PrivateResize (%d %d).\n", + iWindowSizeX, iWindowSizeY); + fflush(stdout); +#endif + // Tell SDL the new size + SDL_PrivateResize(iWindowSizeX, iWindowSizeY); + prev_time = curr_time; + bWindowResized = 0; + } + } +} + +/* We don't actually allow hardware surfaces other than the main one */ +static int os2fslib_AllocHWSurface(_THIS, SDL_Surface *surface) +{ + return(-1); +} +static void os2fslib_FreeHWSurface(_THIS, SDL_Surface *surface) +{ + return; +} + +/* We need to wait for vertical retrace on page flipped displays */ +static int os2fslib_LockHWSurface(_THIS, SDL_Surface *surface) +{ + return(0); +} + +static void os2fslib_UnlockHWSurface(_THIS, SDL_Surface *surface) +{ + return; +} + +static int os2fslib_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors) +{ + printf("[os2fslib_SetColors] : TODO!\n"); fflush(stdout); + // TODO: Implement paletted modes + return(1); +} + +static void os2fslib_DestroyIcon(HWND hwndFrame) +{ + if (hptrCurrentIcon) + { + WinDestroyPointer(hptrCurrentIcon); + hptrCurrentIcon = NULL; + + WinSendMsg(hwndFrame, + WM_SETICON, + NULL, + NULL); + } + +} + +/* Set the window icon image */ +void os2fslib_SetIcon(_THIS, SDL_Surface *icon, Uint8 *mask) +{ + HWND hwndFrame; + SDL_Surface *icon_rgb; + HPOINTER hptrIcon; + HBITMAP hbm; + BITMAPINFOHEADER bmih; + BMPINFO bmi; + HPS hps; + char *pchTemp; + char *pptr, *mptr, *dptr, *dmptr; + int maxx, maxy, w, h, x, y; + SDL_Rect bounds; + +#ifdef DEBUG_BUILD + printf("[os2fslib_SetIcon] : Creating and setting new icon\n"); fflush(stdout); +#endif + + hwndFrame = WinQueryWindow(_this->hidden->hwndClient, QW_PARENT); + + // Make sure the old icon resource will be free'd! + os2fslib_DestroyIcon(hwndFrame); + + if ((!icon) || (!mask)) + return; + + w = icon->w; + h = icon->h; + + maxx = WinQuerySysValue(HWND_DESKTOP, SV_CXICON); + maxy = WinQuerySysValue(HWND_DESKTOP, SV_CYICON); + + // Check for max size! + if ((w>maxx) || (h>maxy)) + return; + + pchTemp = (char *) SDL_malloc(w * h*2 * 4); + if (!pchTemp) + return; + + SDL_memset(pchTemp, 0, w * h*2 * 4); + + // Convert surface to RGB, if it's not RGB yet! + icon_rgb = SDL_CreateRGBSurface(SDL_SWSURFACE, icon->w, icon->h, + 32, 0, 0, 0, 0); + if ( icon_rgb == NULL ) + { + SDL_free(pchTemp); + return; + } + bounds.x = 0; + bounds.y = 0; + bounds.w = icon->w; + bounds.h = icon->h; + if ( SDL_LowerBlit(icon, &bounds, icon_rgb, &bounds) < 0 ) + { + SDL_FreeSurface(icon_rgb); + SDL_free(pchTemp); + return; + } + + /* Copy pixels upside-down from RGB surface into BMP, masked with the icon mask */ + + // Pixels + pptr = (char *) (icon_rgb->pixels); + // Mask + mptr = mask; + + for (y=0; y<h; y++) + { + unsigned char uchMaskByte; + + // Destination + dptr = pchTemp + w*4 * (h-y-1); + // Destination mask + dmptr = pchTemp + w*h*4 + w*4 * (h-y-1); + + for (x=0; x<w; x++) + { + if (x%8==0) + { + uchMaskByte = (unsigned char) (*mptr); + mptr++; + } else + uchMaskByte <<= 1; + + if (uchMaskByte & 0x80) + { + // Copy RGB + *dptr++ = *pptr++; + *dptr++ = *pptr++; + *dptr++ = *pptr++; + *dptr++ = *pptr++; + + *dmptr++ = 0; + *dmptr++ = 0; + *dmptr++ = 0; + *dmptr++ = 0; + } else + { + // Set pixels to fully transparent + *dptr++ = 0; pptr++; + *dptr++ = 0; pptr++; + *dptr++ = 0; pptr++; + *dptr++ = 0; pptr++; + + *dmptr++ = 255; + *dmptr++ = 255; + *dmptr++ = 255; + *dmptr++ = 255; + } + } + } + + // There is no more need for the RGB surface + SDL_FreeSurface(icon_rgb); + + hps = WinGetPS(_this->hidden->hwndClient); + + bmi.cbFix = sizeof(BITMAPINFOHEADER); + bmi.cx = w; + bmi.cy = 2*h; + bmi.cPlanes = 1; + bmi.cBitCount = 32; + + SDL_memset(&bmih, 0, sizeof(BITMAPINFOHEADER)); + bmih.cbFix = sizeof(BITMAPINFOHEADER); + bmih.cx = w; + bmih.cy = 2*h; + bmih.cPlanes = 1; + bmih.cBitCount = 32; + + hbm = GpiCreateBitmap(hps, (PBITMAPINFOHEADER2)&bmih, CBM_INIT, (PBYTE) pchTemp, (PBITMAPINFO2)&bmi); + hptrIcon = WinCreatePointer(HWND_DESKTOP, hbm, FALSE, 0, 0); + + WinReleasePS(hps); + + // Free pixel array + SDL_free(pchTemp); + + // Change icon in frame window + WinSendMsg(hwndFrame, + WM_SETICON, + (MPARAM) hptrIcon, + NULL); + + /* + // Change icon in switchlist + // Seems like it's not needed, the WM_SETICON already does it. + { + PID pidFrame; + HSWITCH hswitchFrame; + SWCNTRL swctl; + + WinQueryWindowProcess(hwndFrame, &pidFrame, NULL); + hswitchFrame = WinQuerySwitchHandle(hwndFrame, pidFrame); + WinQuerySwitchEntry(hswitchFrame, &swctl); + + swctl.hwndIcon = hptrIcon; + + WinChangeSwitchEntry(hswitchFrame, &swctl); + } + */ + + // Store icon handle in global variable + hptrCurrentIcon = hptrIcon; +} + +// ------------------------ REAL FUNCTIONS ----------------- + + +static void os2fslib_SetCursorManagementFunctions(_THIS, int iForWindowedMode) +{ + if (iForWindowedMode) + { + _this->FreeWMCursor = os2fslib_FreeWMCursor; + _this->CreateWMCursor = os2fslib_CreateWMCursor_Win; + _this->ShowWMCursor = os2fslib_ShowWMCursor; + _this->WarpWMCursor = os2fslib_WarpWMCursor; + _this->MoveWMCursor = os2fslib_MoveWMCursor; + _this->CheckMouseMode = NULL;//os2fslib_CheckMouseMode; + } else + { + // We'll have software mouse cursor in FS mode! + _this->FreeWMCursor = os2fslib_FreeWMCursor; + _this->CreateWMCursor = os2fslib_CreateWMCursor_FS; + _this->ShowWMCursor = os2fslib_ShowWMCursor; + _this->WarpWMCursor = os2fslib_WarpWMCursor; + _this->MoveWMCursor = os2fslib_MoveWMCursor; + _this->CheckMouseMode = NULL;//os2fslib_CheckMouseMode; + } +} + +static void os2fslib_InitOSKeymap(_THIS) +{ + int i; + + iShiftIsPressed = 0; + + /* Map the VK and CH keysyms */ + for ( i=0; i<=255; ++i ) + HWScanKeyMap[i] = SDLK_UNKNOWN; + + // First line of keyboard: + HWScanKeyMap[0x1] = SDLK_ESCAPE; + HWScanKeyMap[0x3b] = SDLK_F1; + HWScanKeyMap[0x3c] = SDLK_F2; + HWScanKeyMap[0x3d] = SDLK_F3; + HWScanKeyMap[0x3e] = SDLK_F4; + HWScanKeyMap[0x3f] = SDLK_F5; + HWScanKeyMap[0x40] = SDLK_F6; + HWScanKeyMap[0x41] = SDLK_F7; + HWScanKeyMap[0x42] = SDLK_F8; + HWScanKeyMap[0x43] = SDLK_F9; + HWScanKeyMap[0x44] = SDLK_F10; + HWScanKeyMap[0x57] = SDLK_F11; + HWScanKeyMap[0x58] = SDLK_F12; + HWScanKeyMap[0x5d] = SDLK_PRINT; + HWScanKeyMap[0x46] = SDLK_SCROLLOCK; + HWScanKeyMap[0x5f] = SDLK_PAUSE; + + // Second line of keyboard: + HWScanKeyMap[0x29] = SDLK_BACKQUOTE; + HWScanKeyMap[0x2] = SDLK_1; + HWScanKeyMap[0x3] = SDLK_2; + HWScanKeyMap[0x4] = SDLK_3; + HWScanKeyMap[0x5] = SDLK_4; + HWScanKeyMap[0x6] = SDLK_5; + HWScanKeyMap[0x7] = SDLK_6; + HWScanKeyMap[0x8] = SDLK_7; + HWScanKeyMap[0x9] = SDLK_8; + HWScanKeyMap[0xa] = SDLK_9; + HWScanKeyMap[0xb] = SDLK_0; + HWScanKeyMap[0xc] = SDLK_MINUS; + HWScanKeyMap[0xd] = SDLK_EQUALS; + HWScanKeyMap[0xe] = SDLK_BACKSPACE; + HWScanKeyMap[0x68] = SDLK_INSERT; + HWScanKeyMap[0x60] = SDLK_HOME; + HWScanKeyMap[0x62] = SDLK_PAGEUP; + HWScanKeyMap[0x45] = SDLK_NUMLOCK; + HWScanKeyMap[0x5c] = SDLK_KP_DIVIDE; + HWScanKeyMap[0x37] = SDLK_KP_MULTIPLY; + HWScanKeyMap[0x4a] = SDLK_KP_MINUS; + + // Third line of keyboard: + HWScanKeyMap[0xf] = SDLK_TAB; + HWScanKeyMap[0x10] = SDLK_q; + HWScanKeyMap[0x11] = SDLK_w; + HWScanKeyMap[0x12] = SDLK_e; + HWScanKeyMap[0x13] = SDLK_r; + HWScanKeyMap[0x14] = SDLK_t; + HWScanKeyMap[0x15] = SDLK_y; + HWScanKeyMap[0x16] = SDLK_u; + HWScanKeyMap[0x17] = SDLK_i; + HWScanKeyMap[0x18] = SDLK_o; + HWScanKeyMap[0x19] = SDLK_p; + HWScanKeyMap[0x1a] = SDLK_LEFTBRACKET; + HWScanKeyMap[0x1b] = SDLK_RIGHTBRACKET; + HWScanKeyMap[0x1c] = SDLK_RETURN; + HWScanKeyMap[0x69] = SDLK_DELETE; + HWScanKeyMap[0x65] = SDLK_END; + HWScanKeyMap[0x67] = SDLK_PAGEDOWN; + HWScanKeyMap[0x47] = SDLK_KP7; + HWScanKeyMap[0x48] = SDLK_KP8; + HWScanKeyMap[0x49] = SDLK_KP9; + HWScanKeyMap[0x4e] = SDLK_KP_PLUS; + + // Fourth line of keyboard: + HWScanKeyMap[0x3a] = SDLK_CAPSLOCK; + HWScanKeyMap[0x1e] = SDLK_a; + HWScanKeyMap[0x1f] = SDLK_s; + HWScanKeyMap[0x20] = SDLK_d; + HWScanKeyMap[0x21] = SDLK_f; + HWScanKeyMap[0x22] = SDLK_g; + HWScanKeyMap[0x23] = SDLK_h; + HWScanKeyMap[0x24] = SDLK_j; + HWScanKeyMap[0x25] = SDLK_k; + HWScanKeyMap[0x26] = SDLK_l; + HWScanKeyMap[0x27] = SDLK_SEMICOLON; + HWScanKeyMap[0x28] = SDLK_QUOTE; + HWScanKeyMap[0x2b] = SDLK_BACKSLASH; + HWScanKeyMap[0x4b] = SDLK_KP4; + HWScanKeyMap[0x4c] = SDLK_KP5; + HWScanKeyMap[0x4d] = SDLK_KP6; + + // Fifth line of keyboard: + HWScanKeyMap[0x2a] = SDLK_LSHIFT; + HWScanKeyMap[0x56] = SDLK_WORLD_1; // Code 161, letter i' on hungarian keyboard + HWScanKeyMap[0x2c] = SDLK_z; + HWScanKeyMap[0x2d] = SDLK_x; + HWScanKeyMap[0x2e] = SDLK_c; + HWScanKeyMap[0x2f] = SDLK_v; + HWScanKeyMap[0x30] = SDLK_b; + HWScanKeyMap[0x31] = SDLK_n; + HWScanKeyMap[0x32] = SDLK_m; + HWScanKeyMap[0x33] = SDLK_COMMA; + HWScanKeyMap[0x34] = SDLK_PERIOD; + HWScanKeyMap[0x35] = SDLK_SLASH; + HWScanKeyMap[0x36] = SDLK_RSHIFT; + HWScanKeyMap[0x61] = SDLK_UP; + HWScanKeyMap[0x4f] = SDLK_KP1; + HWScanKeyMap[0x50] = SDLK_KP2; + HWScanKeyMap[0x51] = SDLK_KP3; + HWScanKeyMap[0x5a] = SDLK_KP_ENTER; + + // Sixth line of keyboard: + HWScanKeyMap[0x1d] = SDLK_LCTRL; + HWScanKeyMap[0x7e] = SDLK_LSUPER; // Windows key + HWScanKeyMap[0x38] = SDLK_LALT; + HWScanKeyMap[0x39] = SDLK_SPACE; + HWScanKeyMap[0x5e] = SDLK_RALT;// Actually, altgr on my keyboard... + HWScanKeyMap[0x7f] = SDLK_RSUPER; + HWScanKeyMap[0x7c] = SDLK_MENU; + HWScanKeyMap[0x5b] = SDLK_RCTRL; + HWScanKeyMap[0x63] = SDLK_LEFT; + HWScanKeyMap[0x66] = SDLK_DOWN; + HWScanKeyMap[0x64] = SDLK_RIGHT; + HWScanKeyMap[0x52] = SDLK_KP0; + HWScanKeyMap[0x53] = SDLK_KP_PERIOD; +} + + +/* Iconify the window. + This function returns 1 if there is a window manager and the + window was actually iconified, it returns 0 otherwise. + */ +int os2fslib_IconifyWindow(_THIS) +{ + HAB hab; + HMQ hmq; + ERRORID hmqerror; + + // If there is no more window, nothing we can do! + if (_this->hidden->iPMThreadStatus!=1) return 0; + + // Cannot do anything in fullscreen mode! + if (FSLib_QueryFSMode(_this->hidden->hwndClient)) + return 0; + + // Make sure this thread is prepared for using the Presentation Manager! + hab = WinInitialize(0); + hmq = WinCreateMsgQueue(hab,0); + // Remember if there was an error at WinCreateMsgQueue(), because we don't + // want to destroy somebody else's queue later. :) + hmqerror = WinGetLastError(hab); + + WinSetWindowPos(_this->hidden->hwndFrame, HWND_TOP, + 0, 0, 0, 0, SWP_MINIMIZE); + + // Now destroy the message queue, if we've created it! + if (ERRORIDERROR(hmqerror)==0) + WinDestroyMsgQueue(hmq); + + return 1; +} + +static SDL_GrabMode os2fslib_GrabInput(_THIS, SDL_GrabMode mode) +{ + HAB hab; + HMQ hmq; + ERRORID hmqerror; + + + // If there is no more window, nothing we can do! + if (_this->hidden->iPMThreadStatus!=1) + return SDL_GRAB_OFF; + + // Make sure this thread is prepared for using the Presentation Manager! + hab = WinInitialize(0); + hmq = WinCreateMsgQueue(hab,0); + // Remember if there was an error at WinCreateMsgQueue(), because we don't + // want to destroy somebody else's queue later. :) + hmqerror = WinGetLastError(hab); + + + if (mode == SDL_GRAB_OFF) + { +#ifdef DEBUG_BUILD + printf("[os2fslib_GrabInput] : Releasing mouse\n"); fflush(stdout); +#endif + + // Release the mouse + bMouseCapturable = 0; + if (bMouseCaptured) + { + WinSetCapture(HWND_DESKTOP, NULLHANDLE); + bMouseCaptured = 0; + } + } else + { +#ifdef DEBUG_BUILD + printf("[os2fslib_GrabInput] : Capturing mouse\n"); fflush(stdout); +#endif + + // Capture the mouse + bMouseCapturable = 1; + if (WinQueryFocus(HWND_DESKTOP) == _this->hidden->hwndClient) + { + WinSetCapture(HWND_DESKTOP, _this->hidden->hwndClient); + bMouseCaptured = 1; + { + SWP swpClient; + POINTL ptl; + // Center the mouse to the middle of the window! + WinQueryWindowPos(_this->hidden->hwndClient, &swpClient); + ptl.x = 0; ptl.y = 0; + WinMapWindowPoints(_this->hidden->hwndClient, HWND_DESKTOP, &ptl, 1); + _this->hidden->iSkipWMMOUSEMOVE++; /* Don't take next WM_MOUSEMOVE into account! */ + WinSetPointerPos(HWND_DESKTOP, + ptl.x + swpClient.cx/2, + ptl.y + swpClient.cy/2); + } + } + } + + // Now destroy the message queue, if we've created it! + if (ERRORIDERROR(hmqerror)==0) + WinDestroyMsgQueue(hmq); + + return mode; +} + +/* Set the title and icon text */ +static void os2fslib_SetCaption(_THIS, const char *title, const char *icon) +{ + HAB hab; + HMQ hmq; + ERRORID hmqerror; + + // If there is no more window, nothing we can do! + if (_this->hidden->iPMThreadStatus!=1) return; + + // Make sure this thread is prepared for using the Presentation Manager! + hab = WinInitialize(0); + hmq = WinCreateMsgQueue(hab,0); + // Remember if there was an error at WinCreateMsgQueue(), because we don't + // want to destroy somebody else's queue later. :) + hmqerror = WinGetLastError(hab); + + WinSetWindowText(_this->hidden->hwndFrame, (char *) title); + + // Now destroy the message queue, if we've created it! + if (ERRORIDERROR(hmqerror)==0) + WinDestroyMsgQueue(hmq); +} + +static int os2fslib_ToggleFullScreen(_THIS, int on) +{ +#ifdef DEBUG_BUILD + printf("[os2fslib_ToggleFullScreen] : %d\n", on); fflush(stdout); +#endif + // If there is no more window, nothing we can do! + if (_this->hidden->iPMThreadStatus!=1) return 0; + + FSLib_ToggleFSMode(_this->hidden->hwndClient, on); + /* Cursor manager functions to Windowed/FS mode*/ + os2fslib_SetCursorManagementFunctions(_this, !on); + return 1; +} + +/* This is called after the video mode has been set, to get the + initial mouse state. It should queue events as necessary to + properly represent the current mouse focus and position. + */ +static void os2fslib_UpdateMouse(_THIS) +{ + POINTL ptl; + HAB hab; + HMQ hmq; + ERRORID hmqerror; + SWP swpClient; + + // If there is no more window, nothing we can do! + if (_this->hidden->iPMThreadStatus!=1) return; + + + // Make sure this thread is prepared for using the Presentation Manager! + hab = WinInitialize(0); + hmq = WinCreateMsgQueue(hab,0); + // Remember if there was an error at WinCreateMsgQueue(), because we don't + // want to destroy somebody else's queue later. :) + hmqerror = WinGetLastError(hab); + + + + if (_this->hidden->fInFocus) + { + // If our app is in focus + SDL_PrivateAppActive(1, SDL_APPMOUSEFOCUS); + SDL_PrivateAppActive(1, SDL_APPINPUTFOCUS); + SDL_PrivateAppActive(1, SDL_APPACTIVE); + WinQueryPointerPos(HWND_DESKTOP, &ptl); + WinMapWindowPoints(HWND_DESKTOP, _this->hidden->hwndClient, &ptl, 1); + WinQueryWindowPos(_this->hidden->hwndClient, &swpClient); + // Convert OS/2 mouse position to SDL position, and also scale it! + ptl.x = ptl.x * _this->hidden->SrcBufferDesc.uiXResolution / swpClient.cx; + ptl.y = ptl.y * _this->hidden->SrcBufferDesc.uiYResolution / swpClient.cy; + ptl.y = _this->hidden->SrcBufferDesc.uiYResolution - ptl.y - 1; + SDL_PrivateMouseMotion(0, 0, (Sint16) (ptl.x), (Sint16) (ptl.y)); + } else + { + // If we're not in focus + SDL_PrivateAppActive(0, SDL_APPMOUSEFOCUS); + SDL_PrivateAppActive(0, SDL_APPINPUTFOCUS); + SDL_PrivateAppActive(0, SDL_APPACTIVE); + SDL_PrivateMouseMotion(0, 0, (Sint16) -1, (Sint16) -1); + } + + // Now destroy the message queue, if we've created it! + if (ERRORIDERROR(hmqerror)==0) + WinDestroyMsgQueue(hmq); + +} + +/* This pointer should exist in the native video subsystem and should + point to an appropriate update function for the current video mode + */ +static void os2fslib_UpdateRects(_THIS, int numrects, SDL_Rect *rects) +{ + // If there is no more window, nothing we can do! + if (_this->hidden->iPMThreadStatus!=1) return; + +#ifdef BITBLT_IN_WINMESSAGEPROC + WinSendMsg(_this->hidden->hwndClient, + WM_UPDATERECTSREQUEST, + (MPARAM) numrects, + (MPARAM) rects); +#else + if (DosRequestMutexSem(_this->hidden->hmtxUseSrcBuffer, SEM_INDEFINITE_WAIT)==NO_ERROR) + { + int i; + + if (_this->hidden->pSDLSurface) + { +#ifndef RESIZE_EVEN_IF_RESIZABLE + SWP swp; + // But only blit if the window is not resizable, or if + // the window is resizable and the source buffer size is the + // same as the destination buffer size! + WinQueryWindowPos(_this->hidden->hwndClient, &swp); + if ((_this->hidden->pSDLSurface) && + (_this->hidden->pSDLSurface->flags & SDL_RESIZABLE) && + ((swp.cx != _this->hidden->SrcBufferDesc.uiXResolution) || + (swp.cy != _this->hidden->SrcBufferDesc.uiYResolution) + ) && + (!FSLib_QueryFSMode(_this->hidden->hwndClient)) + ) + { + // Resizable surface and in resizing! + // So, don't blit now! +#ifdef DEBUG_BUILD + printf("[UpdateRects] : Skipping blit while resizing!\n"); fflush(stdout); +#endif + } else +#endif + { + /* + // Blit the whole window + FSLIB_BITBLT(_this->hidden->hwndClient, _this->hidden->pchSrcBuffer, + 0, 0, + _this->hidden->SrcBufferDesc.uiXResolution, + _this->hidden->SrcBufferDesc.uiYResolution); + */ +#ifdef DEBUG_BUILD + printf("[os2fslib_UpdateRects] : Blitting!\n"); fflush(stdout); +#endif + + // Blit the changed areas + for (i=0; i<numrects; i++) + FSLIB_BITBLT(_this->hidden->hwndClient, _this->hidden->pchSrcBuffer, + rects[i].y, rects[i].x, rects[i].w, rects[i].h); + } + } +#ifdef DEBUG_BUILD + else + printf("[os2fslib_UpdateRects] : No public surface!\n"); fflush(stdout); +#endif + DosReleaseMutexSem(_this->hidden->hmtxUseSrcBuffer); + } +#ifdef DEBUG_BUILD + else + printf("[os2fslib_UpdateRects] : Error in mutex!\n"); fflush(stdout); +#endif +#endif +} + + +/* Reverse the effects VideoInit() -- called if VideoInit() fails + or if the application is shutting down the video subsystem. + */ +static void os2fslib_VideoQuit(_THIS) +{ +#ifdef DEBUG_BUILD + printf("[os2fslib_VideoQuit]\n"); fflush(stdout); +#endif + // Close PM stuff if running! + if (_this->hidden->iPMThreadStatus == 1) + { + int iTimeout; + WinPostMsg(_this->hidden->hwndFrame, WM_QUIT, (MPARAM) 0, (MPARAM) 0); + // HACK: We had this line before: + //DosWaitThread((TID *) &(_this->hidden->tidPMThread), DCWW_WAIT); + // We don't use it, because the PMThread will never stop, or if it stops, + // it will kill the whole process as a emergency fallback. + // So, we only check for the iPMThreadStatus stuff! +#ifdef DEBUG_BUILD + printf("[os2fslib_VideoQuit] : Waiting for PM thread to die\n"); fflush(stdout); +#endif + + iTimeout=0; + while ((_this->hidden->iPMThreadStatus == 1) && (iTimeout<100)) + { + iTimeout++; + DosSleep(64); + } + +#ifdef DEBUG_BUILD + printf("[os2fslib_VideoQuit] : End of wait.\n"); fflush(stdout); +#endif + + if (_this->hidden->iPMThreadStatus == 1) + { +#ifdef DEBUG_BUILD + printf("[os2fslib_VideoQuit] : Killing PM thread!\n"); fflush(stdout); +#endif + + _this->hidden->iPMThreadStatus = 0; + DosKillThread(_this->hidden->tidPMThread); + + if (_this->hidden->hwndFrame) + { +#ifdef DEBUG_BUILD + printf("[os2fslib_VideoQuit] : Destroying PM window!\n"); fflush(stdout); +#endif + + WinDestroyWindow(_this->hidden->hwndFrame); _this->hidden->hwndFrame=NULL; + } + } + + } + + // Free result of an old ListModes() call, because there is + // no FreeListModes() call in SDL! + if (_this->hidden->pListModesResult) + { + SDL_free(_this->hidden->pListModesResult); _this->hidden->pListModesResult = NULL; + } + + // Free list of available fullscreen modes + if (_this->hidden->pAvailableFSLibVideoModes) + { + FSLib_FreeVideoModeList(_this->hidden->pAvailableFSLibVideoModes); + _this->hidden->pAvailableFSLibVideoModes = NULL; + } + + // Free application icon if we had one + if (hptrCurrentIcon) + { + WinDestroyPointer(hptrCurrentIcon); + hptrCurrentIcon = NULL; + } +} + +/* Set the requested video mode, returning a surface which will be + set to the SDL_VideoSurface. The width and height will already + be verified by ListModes(), and the video subsystem is free to + set the mode to a supported bit depth different from the one + specified -- the desired bpp will be emulated with a shadow + surface if necessary. If a new mode is returned, this function + should take care of cleaning up the current mode. + */ +static SDL_Surface *os2fslib_SetVideoMode(_THIS, SDL_Surface *current, + int width, int height, int bpp, Uint32 flags) +{ + static int bFirstCall = 1; + FSLib_VideoMode_p pModeInfo, pModeInfoFound; + FSLib_VideoMode TempModeInfo; + HAB hab; + HMQ hmq; + ERRORID hmqerror; + RECTL rectl; + SDL_Surface *pResult; + + // If there is no more window, nothing we can do! + if (_this->hidden->iPMThreadStatus!=1) return NULL; + +#ifdef DEBUG_BUILD + printf("[os2fslib_SetVideoMode] : Request for %dx%d @ %dBPP, flags=0x%x\n", width, height, bpp, flags); fflush(stdout); +#endif + + // We don't support palette modes! + if (bpp==8) bpp=32; + + // Also, we don't support resizable modes in fullscreen mode. + if (flags & SDL_RESIZABLE) + flags &= ~SDL_FULLSCREEN; + + // No double buffered mode + if (flags & SDL_DOUBLEBUF) + flags &= ~SDL_DOUBLEBUF; + + // And, we don't support HWSURFACE yet. + if (flags & SDL_HWSURFACE) + { + flags &= ~SDL_HWSURFACE; + flags |= SDL_SWSURFACE; + } + +#ifdef DEBUG_BUILD + printf("[os2fslib_SetVideoMode] : Changed request to %dx%d @ %dBPP, flags=0x%x\n", width, height, bpp, flags); fflush(stdout); +#endif + + // First check if there is such a video mode they want! + pModeInfoFound = NULL; + + // For fullscreen mode we don't support every resolution! + // So, go through the video modes, and check for such a resolution! + pModeInfoFound = NULL; + pModeInfo = _this->hidden->pAvailableFSLibVideoModes; + + while (pModeInfo) + { + // Check all available fullscreen modes for this resolution + if ((pModeInfo->uiXResolution == width) && + (pModeInfo->uiYResolution == height) && + (pModeInfo->uiBPP!=8)) // palettized modes not yet supported + { + // If good resolution, try to find the exact BPP, or at least + // something similar... + if (!pModeInfoFound) + pModeInfoFound = pModeInfo; + else + if ((pModeInfoFound->uiBPP!=bpp) && + (pModeInfoFound->uiBPP<pModeInfo->uiBPP)) + pModeInfoFound = pModeInfo; + } + pModeInfo = pModeInfo->pNext; + } + + // If we did not find a good fullscreen mode, then try a similar + if (!pModeInfoFound) + { +#ifdef DEBUG_BUILD + printf("[os2fslib_SetVideoMode] : Requested video mode not found, looking for a similar one!\n"); fflush(stdout); +#endif + // Go through the video modes again, and find a similar resolution! + pModeInfo = _this->hidden->pAvailableFSLibVideoModes; + while (pModeInfo) + { + // Check all available fullscreen modes for this resolution + if ((pModeInfo->uiXResolution >= width) && + (pModeInfo->uiYResolution >= height) && + (pModeInfo->uiBPP == bpp)) + { + if (!pModeInfoFound) + pModeInfoFound = pModeInfo; + else + if (((pModeInfoFound->uiXResolution-width)*(pModeInfoFound->uiYResolution-height))> + ((pModeInfo->uiXResolution-width)*(pModeInfo->uiYResolution-height))) + { + // Found a mode which is closer than the current one + pModeInfoFound = pModeInfo; + } + } + pModeInfo = pModeInfo->pNext; + } + } + + // If we did not find a good fullscreen mode, then return NULL + if (!pModeInfoFound) + { +#ifdef DEBUG_BUILD + printf("[os2fslib_SetVideoMode] : Requested video mode not found!\n"); fflush(stdout); +#endif + return NULL; + } + +#ifdef DEBUG_BUILD + printf("[os2fslib_SetVideoMode] : Found mode!\n"); fflush(stdout); +#endif + + // We'll possibly adjust the structure, so copy out the values + // into TempModeInfo! + SDL_memcpy(&TempModeInfo, pModeInfoFound, sizeof(TempModeInfo)); + pModeInfoFound = &TempModeInfo; + + if (flags & SDL_RESIZABLE) + { +#ifdef DEBUG_BUILD + printf("[os2fslib_SetVideoMode] : Requested mode is resizable, changing width/height\n"); fflush(stdout); +#endif + // Change width and height to requested one! + TempModeInfo.uiXResolution = width; + TempModeInfo.uiYResolution = height; + TempModeInfo.uiScanLineSize = width * ((TempModeInfo.uiBPP+7)/8); + } + + // We can try create new surface! + + // Make sure this thread is prepared for using the Presentation Manager! + hab = WinInitialize(0); + hmq = WinCreateMsgQueue(hab,0); + // Remember if there was an error at WinCreateMsgQueue(), because we don't + // want to destroy somebody else's queue later. :) + hmqerror = WinGetLastError(hab); + + + + if (DosRequestMutexSem(_this->hidden->hmtxUseSrcBuffer, SEM_INDEFINITE_WAIT)==NO_ERROR) + { +#ifdef DEBUG_BUILD + printf("[os2fslib_SetVideoMode] : Creating new SW surface\n"); fflush(stdout); +#endif + + // Create new software surface! + pResult = SDL_CreateRGBSurface(SDL_SWSURFACE, + pModeInfoFound->uiXResolution, + pModeInfoFound->uiYResolution, + pModeInfoFound->uiBPP, + ((unsigned int) pModeInfoFound->PixelFormat.ucRedMask) << pModeInfoFound->PixelFormat.ucRedPosition, + ((unsigned int) pModeInfoFound->PixelFormat.ucGreenMask) << pModeInfoFound->PixelFormat.ucGreenPosition, + ((unsigned int) pModeInfoFound->PixelFormat.ucBlueMask) << pModeInfoFound->PixelFormat.ucBluePosition, + ((unsigned int) pModeInfoFound->PixelFormat.ucAlphaMask) << pModeInfoFound->PixelFormat.ucAlphaPosition); + + if (pResult == NULL) + { + DosReleaseMutexSem(_this->hidden->hmtxUseSrcBuffer); + SDL_OutOfMemory(); + return NULL; + } + +#ifdef DEBUG_BUILD + printf("[os2fslib_SetVideoMode] : Adjusting pixel format\n"); fflush(stdout); +#endif + + // Adjust pixel format mask! + pResult->format->Rmask = ((unsigned int) pModeInfoFound->PixelFormat.ucRedMask) << pModeInfoFound->PixelFormat.ucRedPosition; + pResult->format->Rshift = pModeInfoFound->PixelFormat.ucRedPosition; + pResult->format->Rloss = pModeInfoFound->PixelFormat.ucRedAdjust; + pResult->format->Gmask = ((unsigned int) pModeInfoFound->PixelFormat.ucGreenMask) << pModeInfoFound->PixelFormat.ucGreenPosition; + pResult->format->Gshift = pModeInfoFound->PixelFormat.ucGreenPosition; + pResult->format->Gloss = pModeInfoFound->PixelFormat.ucGreenAdjust; + pResult->format->Bmask = ((unsigned int) pModeInfoFound->PixelFormat.ucBlueMask) << pModeInfoFound->PixelFormat.ucBluePosition; + pResult->format->Bshift = pModeInfoFound->PixelFormat.ucBluePosition; + pResult->format->Bloss = pModeInfoFound->PixelFormat.ucBlueAdjust; + pResult->format->Amask = ((unsigned int) pModeInfoFound->PixelFormat.ucAlphaMask) << pModeInfoFound->PixelFormat.ucAlphaPosition; + pResult->format->Ashift = pModeInfoFound->PixelFormat.ucAlphaPosition; + pResult->format->Aloss = pModeInfoFound->PixelFormat.ucAlphaAdjust; + +#ifdef REPORT_EMPTY_ALPHA_MASK + pResult->format->Amask = + pResult->format->Ashift = + pResult->format->Aloss = 0; +#endif + + // Adjust surface flags + pResult->flags |= (flags & SDL_FULLSCREEN); + pResult->flags |= (flags & SDL_RESIZABLE); + + // It might be that the software surface pitch is not the same as + // the pitch we have, so adjust that! + pModeInfoFound->uiScanLineSize = pResult->pitch; + + // Store new source buffer parameters! + SDL_memcpy(&(_this->hidden->SrcBufferDesc), pModeInfoFound, sizeof(*pModeInfoFound)); + _this->hidden->pchSrcBuffer = pResult->pixels; + +#ifdef DEBUG_BUILD + printf("[os2fslib_SetVideoMode] : Telling FSLib the stuffs\n"); fflush(stdout); +#endif + + // Tell the FSLib window the new source image format + FSLib_SetSrcBufferDesc(_this->hidden->hwndClient, &(_this->hidden->SrcBufferDesc)); + + if ( + ((flags & SDL_RESIZABLE)==0) || + (bFirstCall) + ) + { + bFirstCall = 0; +#ifdef DEBUG_BUILD + printf("[os2fslib_SetVideoMode] : Modifying window size\n"); fflush(stdout); +#endif + + // Calculate frame window size from client window size + rectl.xLeft = 0; + rectl.yBottom = 0; + rectl.xRight = pModeInfoFound->uiXResolution; // Noninclusive + rectl.yTop = pModeInfoFound->uiYResolution; // Noninclusive + WinCalcFrameRect(_this->hidden->hwndFrame, &rectl, FALSE); + + // Set the new size of the main window + SetAccessableWindowPos(_this->hidden->hwndFrame, + HWND_TOP, + 0, 0, + (rectl.xRight-rectl.xLeft), + (rectl.yTop-rectl.yBottom), + SWP_SIZE | SWP_ACTIVATE | SWP_SHOW); + } + + // Set fullscreen mode flag, and switch to fullscreen if needed! + if (flags & SDL_FULLSCREEN) + { +#ifdef DEBUG_BUILD + printf("[os2fslib_SetVideoMode] : Also trying to switch to fullscreen\n"); + fflush(stdout); +#endif + FSLib_ToggleFSMode(_this->hidden->hwndClient, 1); + /* Cursor manager functions to FS mode*/ + os2fslib_SetCursorManagementFunctions(_this, 0); + } else + { +#ifdef DEBUG_BUILD + printf("[os2fslib_SetVideoMode] : Also trying to switch to desktop mode\n"); + fflush(stdout); +#endif + FSLib_ToggleFSMode(_this->hidden->hwndClient, 0); + /* Cursor manager functions to Windowed mode*/ + os2fslib_SetCursorManagementFunctions(_this, 1); + } + + _this->hidden->pSDLSurface = pResult; + + DosReleaseMutexSem(_this->hidden->hmtxUseSrcBuffer); + } else + { +#ifdef DEBUG_BUILD + printf("[os2fslib_SetVideoMode] : Could not get hmtxUseSrcBuffer!\n"); fflush(stdout); +#endif + + pResult = NULL; + } + + // As we have the new surface, we don't need the current one anymore! + if ((pResult) && (current)) + { +#ifdef DEBUG_BUILD + printf("[os2fslib_SetVideoMode] : Freeing old surface\n"); fflush(stdout); +#endif + SDL_FreeSurface(current); + } + + // Redraw window + WinInvalidateRegion(_this->hidden->hwndClient, NULL, TRUE); + + // Now destroy the message queue, if we've created it! + if (ERRORIDERROR(hmqerror)==0) + { +#ifdef DEBUG_BUILD + printf("[os2fslib_SetVideoMode] : Destroying message queue\n"); fflush(stdout); +#endif + WinDestroyMsgQueue(hmq); + } + +#ifdef DEBUG_BUILD + printf("[os2fslib_SetVideoMode] : Done\n"); fflush(stdout); +#endif + + /* We're done */ + + // Return with the new surface! + return pResult; +} + +/* List the available video modes for the given pixel format, sorted + from largest to smallest. + */ +static SDL_Rect **os2fslib_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags) +{ +#ifdef DEBUG_BUILD + printf("[os2fslib_ListModes] : ListModes of %d Bpp\n", format->BitsPerPixel); +#endif + // Destroy result of previous call, if there is any + if (_this->hidden->pListModesResult) + { + SDL_free(_this->hidden->pListModesResult); _this->hidden->pListModesResult = NULL; + } + + // For resizable and windowed mode we support every resolution! + if ((flags & SDL_RESIZABLE) && ((flags & SDL_FULLSCREEN) == 0)) + return (SDL_Rect **)-1; + + // Check if they need fullscreen or non-fullscreen video modes! + if ((flags & SDL_FULLSCREEN) == 0) + + { + // For windowed mode we support every resolution! + return (SDL_Rect **)-1; + } else + { + FSLib_VideoMode_p pFSMode; + // For fullscreen mode we don't support every resolution! + // Now create a new list + pFSMode = _this->hidden->pAvailableFSLibVideoModes; + while (pFSMode) + { + if (pFSMode->uiBPP == format->BitsPerPixel) + { + SDL_Rect *pRect = (SDL_Rect *) SDL_malloc(sizeof(SDL_Rect)); + if (pRect) + { + // Fill description + pRect->x = 0; + pRect->y = 0; + pRect->w = pFSMode->uiXResolution; + pRect->h = pFSMode->uiYResolution; +#ifdef DEBUG_BUILD +// printf("!!! Seems to be good!\n"); +// printf("F: %dx%d\n", pRect->w, pRect->h); +#endif + // And insert into list of pRects + if (!(_this->hidden->pListModesResult)) + { +#ifdef DEBUG_BUILD +// printf("!!! Inserting to beginning\n"); +#endif + + // We're the first one to be inserted! + _this->hidden->pListModesResult = (SDL_Rect**) SDL_malloc(2*sizeof(SDL_Rect*)); + if (_this->hidden->pListModesResult) + { + _this->hidden->pListModesResult[0] = pRect; + _this->hidden->pListModesResult[1] = NULL; + } else + { + SDL_free(pRect); + } + } else + { + // We're not the first ones, so find the place where we + // have to insert ourselves + SDL_Rect **pNewList; + int iPlace, iNumOfSlots, i; + +#ifdef DEBUG_BUILD +// printf("!!! Searching where to insert\n"); +#endif + + iPlace = -1; iNumOfSlots = 1; // Count the last NULL too! + for (i=0; _this->hidden->pListModesResult[i]; i++) + { + iNumOfSlots++; + if (iPlace==-1) + { + if ((_this->hidden->pListModesResult[i]->w*_this->hidden->pListModesResult[i]->h)< + (pRect->w*pRect->h)) + { + iPlace = i; + } + } + } + if (iPlace==-1) iPlace = iNumOfSlots-1; + +#ifdef DEBUG_BUILD +// printf("!!! From %d slots, it will be at %d\n", iNumOfSlots, iPlace); +#endif + + pNewList = (SDL_Rect**) SDL_realloc(_this->hidden->pListModesResult, (iNumOfSlots+1)*sizeof(SDL_Rect*)); + if (pNewList) + { + for (i=iNumOfSlots;i>iPlace;i--) + pNewList[i] = pNewList[i-1]; + pNewList[iPlace] = pRect; + _this->hidden->pListModesResult = pNewList; + } else + { + SDL_free(pRect); + } + } + } + } + pFSMode = pFSMode->pNext; + } + } +#ifdef DEBUG_BUILD +// printf("Returning list\n"); +#endif + return _this->hidden->pListModesResult; +} + +/* Initialize the native video subsystem, filling 'vformat' with the + "best" display pixel format, returning 0 or -1 if there's an error. + */ +static int os2fslib_VideoInit(_THIS, SDL_PixelFormat *vformat) +{ + FSLib_VideoMode_p pDesktopMode; + +#ifdef DEBUG_BUILD + printf("[os2fslib_VideoInit] : Enter\n"); fflush(stdout); +#endif + + // Report the best pixel format. For this, + // we'll use the current desktop format. + pDesktopMode = FSLib_GetDesktopVideoMode(); + if (!pDesktopMode) + { + SDL_SetError("Could not query desktop video mode!"); +#ifdef DEBUG_BUILD + printf("[os2fslib_VideoInit] : Could not query desktop video mode!\n"); +#endif + return -1; + } + + /* Determine the current screen size */ + _this->info.current_w = pDesktopMode->uiXResolution; + _this->info.current_h = pDesktopMode->uiYResolution; + + /* Determine the screen depth */ + vformat->BitsPerPixel = pDesktopMode->uiBPP; + vformat->BytesPerPixel = (vformat->BitsPerPixel+7)/8; + + vformat->Rmask = ((unsigned int) pDesktopMode->PixelFormat.ucRedMask) << pDesktopMode->PixelFormat.ucRedPosition; + vformat->Rshift = pDesktopMode->PixelFormat.ucRedPosition; + vformat->Rloss = pDesktopMode->PixelFormat.ucRedAdjust; + vformat->Gmask = ((unsigned int) pDesktopMode->PixelFormat.ucGreenMask) << pDesktopMode->PixelFormat.ucGreenPosition; + vformat->Gshift = pDesktopMode->PixelFormat.ucGreenPosition; + vformat->Gloss = pDesktopMode->PixelFormat.ucGreenAdjust; + vformat->Bmask = ((unsigned int) pDesktopMode->PixelFormat.ucBlueMask) << pDesktopMode->PixelFormat.ucBluePosition; + vformat->Bshift = pDesktopMode->PixelFormat.ucBluePosition; + vformat->Bloss = pDesktopMode->PixelFormat.ucBlueAdjust; + vformat->Amask = ((unsigned int) pDesktopMode->PixelFormat.ucAlphaMask) << pDesktopMode->PixelFormat.ucAlphaPosition; + vformat->Ashift = pDesktopMode->PixelFormat.ucAlphaPosition; + vformat->Aloss = pDesktopMode->PixelFormat.ucAlphaAdjust; + +#ifdef REPORT_EMPTY_ALPHA_MASK + vformat->Amask = + vformat->Ashift = + vformat->Aloss = 0; +#endif + + // Fill in some window manager capabilities + _this->info.wm_available = 1; + + // Initialize some internal variables + _this->hidden->pListModesResult = NULL; + _this->hidden->fInFocus = 0; + _this->hidden->iSkipWMMOUSEMOVE = 0; + _this->hidden->iMouseVisible = 1; + + if (getenv("SDL_USE_PROPORTIONAL_WINDOW")) + _this->hidden->bProportionalResize = 1; + else + { + PPIB pib; + PTIB tib; + char *pchFileName, *pchTemp; + char achConfigFile[CCHMAXPATH]; + FILE *hFile; + + /* No environment variable to have proportional window. + * Ok, let's check if this executable is in config file! + */ + _this->hidden->bProportionalResize = 0; + + DosGetInfoBlocks(&tib, &pib); + pchTemp = pchFileName = pib->pib_pchcmd; + while (*pchTemp) + { + if (*pchTemp=='\\') + pchFileName = pchTemp+1; + pchTemp++; + } + if (getenv("HOME")) + { + sprintf(achConfigFile, "%s\\.sdl.proportionals", getenv("HOME")); + hFile = fopen(achConfigFile, "rt"); + if (!hFile) + { + /* Seems like the file cannot be opened or does not exist. + * Let's try to create it with defaults! + */ + hFile = fopen(achConfigFile, "wt"); + if (hFile) + { + fprintf(hFile, "; This file is a config file of SDL/2, containing\n"); + fprintf(hFile, "; the list of executables that must have proportional\n"); + fprintf(hFile, "; windows.\n"); + fprintf(hFile, ";\n"); + fprintf(hFile, "; You can add executable filenames into this file,\n"); + fprintf(hFile, "; one under the other. If SDL finds that a given\n"); + fprintf(hFile, "; program is in this list, then that application\n"); + fprintf(hFile, "; will have proportional windows, just like if\n"); + fprintf(hFile, "; the SET SDL_USE_PROPORTIONAL_WINDOW env. variable\n"); + fprintf(hFile, "; would have been set for that process.\n"); + fprintf(hFile, ";\n"); + fprintf(hFile, "\n"); + fprintf(hFile, "dosbox.exe\n"); + fclose(hFile); + } + + hFile = fopen(achConfigFile, "rt"); + } + + if (hFile) + { + while (fgets(achConfigFile, sizeof(achConfigFile), hFile)) + { + /* Cut \n from end of string */ + + while (achConfigFile[strlen(achConfigFile)-1] == '\n') + achConfigFile[strlen(achConfigFile)-1] = 0; + + /* Compare... */ + if (stricmp(achConfigFile, pchFileName)==0) + { + /* Found it in config file! */ + _this->hidden->bProportionalResize = 1; + break; + } + } + fclose(hFile); + } + } + } + + DosCreateMutexSem(NULL, &(_this->hidden->hmtxUseSrcBuffer), 0, FALSE); + + // Now create our window with a default size + + // For this, we select the first available fullscreen mode as + // current window size! + SDL_memcpy(&(_this->hidden->SrcBufferDesc), _this->hidden->pAvailableFSLibVideoModes, sizeof(_this->hidden->SrcBufferDesc)); + // Allocate new video buffer! + _this->hidden->pchSrcBuffer = (char *) SDL_malloc(_this->hidden->pAvailableFSLibVideoModes->uiScanLineSize * _this->hidden->pAvailableFSLibVideoModes->uiYResolution); + if (!_this->hidden->pchSrcBuffer) + { +#ifdef DEBUG_BUILD + printf("[os2fslib_VideoInit] : Yikes, not enough memory for new video buffer!\n"); fflush(stdout); +#endif + SDL_SetError("Not enough memory for new video buffer!\n"); + return -1; + } + + // For this, we need a message processing thread. + // We'll create a new thread for this, which will do everything + // what is related to PM + _this->hidden->iPMThreadStatus = 0; + _this->hidden->tidPMThread = _beginthread(PMThreadFunc, NULL, 65536, (void *) _this); + if (_this->hidden->tidPMThread <= 0) + { +#ifdef DEBUG_BUILD + printf("[os2fslib_VideoInit] : Could not create PM thread!\n"); +#endif + SDL_SetError("Could not create PM thread"); + return -1; + } +#ifdef USE_DOSSETPRIORITY + // Burst the priority of PM Thread! + DosSetPriority(PRTYS_THREAD, PRTYC_TIMECRITICAL, 0, _this->hidden->tidPMThread); +#endif + // Wait for the PM thread to initialize! + while (_this->hidden->iPMThreadStatus==0) + DosSleep(32); + // If the PM thread could not set up everything, then + // report an error! + if (_this->hidden->iPMThreadStatus!=1) + { +#ifdef DEBUG_BUILD + printf("[os2fslib_VideoInit] : PMThread reported an error : %d\n", _this->hidden->iPMThreadStatus); +#endif + SDL_SetError("Error initializing PM thread"); + return -1; + } + + return 0; +} + + +static void os2fslib_DeleteDevice(_THIS) +{ +#ifdef DEBUG_BUILD + printf("[os2fslib_DeleteDevice]\n"); fflush(stdout); +#endif + // Free used memory + FSLib_FreeVideoModeList(_this->hidden->pAvailableFSLibVideoModes); + if (_this->hidden->pListModesResult) + SDL_free(_this->hidden->pListModesResult); + if (_this->hidden->pchSrcBuffer) + SDL_free(_this->hidden->pchSrcBuffer); + DosCloseMutexSem(_this->hidden->hmtxUseSrcBuffer); + SDL_free(_this->hidden); + SDL_free(_this); + FSLib_Uninitialize(); +} + +static int os2fslib_Available(void) +{ + + // If we can run, it means that we could load FSLib, + // so we assume that it's available then! + return 1; +} + +static void os2fslib_MorphToPM() +{ + PPIB pib; + PTIB tib; + + DosGetInfoBlocks(&tib, &pib); + + // Change flag from VIO to PM: + if (pib->pib_ultype==2) pib->pib_ultype = 3; +} + +static SDL_VideoDevice *os2fslib_CreateDevice(int devindex) +{ + SDL_VideoDevice *device; + +#ifdef DEBUG_BUILD + printf("[os2fslib_CreateDevice] : Enter\n"); fflush(stdout); +#endif + + /* Initialize all variables that we clean on shutdown */ + device = (SDL_VideoDevice *)SDL_malloc(sizeof(SDL_VideoDevice)); + if ( device ) + { + SDL_memset(device, 0, (sizeof *device)); + // Also allocate memory for private data + device->hidden = (struct SDL_PrivateVideoData *) SDL_malloc((sizeof(struct SDL_PrivateVideoData))); + } + if ( (device == NULL) || (device->hidden == NULL) ) + { + SDL_OutOfMemory(); + if ( device ) + SDL_free(device); + return NULL; + } + SDL_memset(device->hidden, 0, (sizeof *device->hidden)); + + /* Set the function pointers */ +#ifdef DEBUG_BUILD + printf("[os2fslib_CreateDevice] : VideoInit is %p\n", os2fslib_VideoInit); fflush(stdout); +#endif + + /* Initialization/Query functions */ + device->VideoInit = os2fslib_VideoInit; + device->ListModes = os2fslib_ListModes; + device->SetVideoMode = os2fslib_SetVideoMode; + device->ToggleFullScreen = os2fslib_ToggleFullScreen; + device->UpdateMouse = os2fslib_UpdateMouse; + device->CreateYUVOverlay = NULL; + device->SetColors = os2fslib_SetColors; + device->UpdateRects = os2fslib_UpdateRects; + device->VideoQuit = os2fslib_VideoQuit; + /* Hardware acceleration functions */ + device->AllocHWSurface = os2fslib_AllocHWSurface; + device->CheckHWBlit = NULL; + device->FillHWRect = NULL; + device->SetHWColorKey = NULL; + device->SetHWAlpha = NULL; + device->LockHWSurface = os2fslib_LockHWSurface; + device->UnlockHWSurface = os2fslib_UnlockHWSurface; + device->FlipHWSurface = NULL; + device->FreeHWSurface = os2fslib_FreeHWSurface; + /* Window manager functions */ + device->SetCaption = os2fslib_SetCaption; + device->SetIcon = os2fslib_SetIcon; + device->IconifyWindow = os2fslib_IconifyWindow; + device->GrabInput = os2fslib_GrabInput; + device->GetWMInfo = NULL; + /* Cursor manager functions to Windowed mode*/ + os2fslib_SetCursorManagementFunctions(device, 1); + /* Event manager functions */ + device->InitOSKeymap = os2fslib_InitOSKeymap; + device->PumpEvents = os2fslib_PumpEvents; + /* The function used to dispose of this structure */ + device->free = os2fslib_DeleteDevice; + + // Make sure we'll be able to use Win* API even if the application + // was linked to be a VIO application! + os2fslib_MorphToPM(); + + // Now initialize FSLib, and query available video modes! + if (!FSLib_Initialize()) + { + // Could not initialize FSLib! +#ifdef DEBUG_BUILD + printf("[os2fslib_CreateDevice] : Could not initialize FSLib!\n"); +#endif + SDL_SetError("Could not initialize FSLib!"); + SDL_free(device->hidden); + SDL_free(device); + return NULL; + } + device->hidden->pAvailableFSLibVideoModes = + FSLib_GetVideoModeList(); + + return device; +} + +VideoBootStrap OS2FSLib_bootstrap = { + "os2fslib", "OS/2 Video Output using FSLib", + os2fslib_Available, os2fslib_CreateDevice +}; + diff --git a/3rdparty/SDL/src/video/os2fslib/SDL_os2fslib.h b/3rdparty/SDL/src/video/os2fslib/SDL_os2fslib.h new file mode 100644 index 0000000..6d58baf --- /dev/null +++ b/3rdparty/SDL/src/video/os2fslib/SDL_os2fslib.h @@ -0,0 +1,71 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#ifndef _SDL_os2fslib_h +#define _SDL_os2fslib_h + + +// OS2 specific includes +#define INCL_TYPES +#define INCL_DOS +#define INCL_DOSERRORS +#define INCL_DOSPROCESS +#define INCL_WIN +#define INCL_GPI +#include <os2.h> + +#include <FSLib.h> + +/* Hidden "this" pointer for the video functions */ +#define _THIS SDL_VideoDevice *_this + +/* Private display data */ +struct SDL_PrivateVideoData +{ + FSLib_VideoMode_p pAvailableFSLibVideoModes; + SDL_Rect **pListModesResult; // Allocated memory to return list of modes for os2fslib_ListModes() API + + FSLib_VideoMode SrcBufferDesc; // Description of current source image buffer + char *pchSrcBuffer; // The source image buffer itself + SDL_Surface *pSDLSurface; // The SDL surface describing the buffer + HMTX hmtxUseSrcBuffer; // Mutex semaphore to manipulate src buffer + HWND hwndFrame, hwndClient; // Window handle of frame and client + int iPMThreadStatus; // 0: Not running + // 1: Running + // Other: Not running, had an error + int tidPMThread; // Thread ID of PM Thread + int fInFocus; // True if we're in focus! + int iSkipWMMOUSEMOVE; // Number of WM_MOUSEMOVE messages to skip! + int iMouseVisible; // + + PFNWP pfnOldFrameProc; // Old window frame procedure + int bProportionalResize; // 0: No proportional resizing + // 1: Do proportional resizing + ULONG ulResizingFlag; // First resizing flag value +}; + +/* OS/2 specific backdoor function to be able to set FrameControlFlags of */ +/* the SDL window before creating it. */ +extern DECLSPEC void SDLCALL SDL_OS2FSLIB_SetFCFToUse(ULONG ulFCF); + +#endif /* _SDL_os2fslib_h */ diff --git a/3rdparty/SDL/src/video/os2fslib/SDL_vkeys.h b/3rdparty/SDL/src/video/os2fslib/SDL_vkeys.h new file mode 100644 index 0000000..79380d5 --- /dev/null +++ b/3rdparty/SDL/src/video/os2fslib/SDL_vkeys.h @@ -0,0 +1,74 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ + +#ifndef VK_0 +#define VK_0 '0' +#define VK_1 '1' +#define VK_2 '2' +#define VK_3 '3' +#define VK_4 '4' +#define VK_5 '5' +#define VK_6 '6' +#define VK_7 '7' +#define VK_8 '8' +#define VK_9 '9' +#define VK_A 'A' +#define VK_B 'B' +#define VK_C 'C' +#define VK_D 'D' +#define VK_E 'E' +#define VK_F 'F' +#define VK_G 'G' +#define VK_H 'H' +#define VK_I 'I' +#define VK_J 'J' +#define VK_K 'K' +#define VK_L 'L' +#define VK_M 'M' +#define VK_N 'N' +#define VK_O 'O' +#define VK_P 'P' +#define VK_Q 'Q' +#define VK_R 'R' +#define VK_S 'S' +#define VK_T 'T' +#define VK_U 'U' +#define VK_V 'V' +#define VK_W 'W' +#define VK_X 'X' +#define VK_Y 'Y' +#define VK_Z 'Z' +#endif /* VK_0 */ + +/* These keys haven't been defined, but were experimentally determined */ +#define VK_SEMICOLON 0xBA +#define VK_EQUALS 0xBB +#define VK_COMMA 0xBC +#define VK_MINUS 0xBD +#define VK_PERIOD 0xBE +#define VK_SLASH 0xBF +#define VK_GRAVE 0xC0 +#define VK_LBRACKET 0xDB +#define VK_BACKSLASH 0xDC +#define VK_RBRACKET 0xDD +#define VK_APOSTROPHE 0xDE +#define VK_BACKTICK 0xDF diff --git a/3rdparty/SDL/src/video/photon/SDL_ph_events.c b/3rdparty/SDL/src/video/photon/SDL_ph_events.c new file mode 100644 index 0000000..9b7538c --- /dev/null +++ b/3rdparty/SDL/src/video/photon/SDL_ph_events.c @@ -0,0 +1,624 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* Handle the event stream, converting photon events into SDL events */ + +#include <stdio.h> +#include <setjmp.h> +#include <sys/time.h> + +#include <Ph.h> +#include <photon/PkKeyDef.h> + +#include "SDL.h" +#include "SDL_syswm.h" +#include "../SDL_sysvideo.h" +#include "../../events/SDL_sysevents.h" +#include "../../events/SDL_events_c.h" +#include "SDL_ph_video.h" +#include "SDL_ph_modes_c.h" +#include "SDL_ph_image_c.h" +#include "SDL_ph_events_c.h" +#include "SDL_phyuv_c.h" + +/* The translation tables from a photon keysym to a SDL keysym */ +static SDLKey ODD_keymap[256]; +static SDLKey MISC_keymap[0xFF + 1]; +SDL_keysym *ph_TranslateKey(PhKeyEvent_t *key, SDL_keysym *keysym); + +/* Check to see if this is a repeated key. + (idea shamelessly lifted from GII -- thanks guys! :) */ +static int ph_WarpedMotion(_THIS, PhEvent_t *winEvent) +{ + PhRect_t *rect = PhGetRects( winEvent ); + + int centre_x, centre_y; + int dx, dy; + short abs_x, abs_y; + int posted; + + centre_x = SDL_VideoSurface->w / 2; + centre_y = SDL_VideoSurface->h / 2; + + dx = rect->ul.x - centre_x; + dy = rect->ul.y - centre_y; + + posted = SDL_PrivateMouseMotion( 0, 1, dx, dy ); + + /* Move mouse cursor to middle of the window */ + PtGetAbsPosition( window, &abs_x, &abs_y ); + PhMoveCursorAbs(PhInputGroup(NULL), abs_x + centre_x, abs_y + centre_y); + + return (posted); +} + +/* Control which motion flags the window has set, a flags value of -1 sets + * MOTION_BUTTON and MOTION_NOBUTTON */ + +static void set_motion_sensitivity(_THIS, unsigned int flags) +{ + int rid; + int fields = Ph_EV_PTR_MOTION_BUTTON | Ph_EV_PTR_MOTION_NOBUTTON; + PhRegion_t region; + + if( window ) + { + rid = PtWidgetRid(window); + if( rid != 0 && PhRegionQuery(rid, ®ion, NULL, NULL, 0) == 0 ) + { + region.events_sense=(region.events_sense & ~fields)|(flags & fields); + PhRegionChange(Ph_REGION_EV_SENSE, 0, ®ion, NULL, NULL); + } + } +} + +/* Convert the photon button state value to an SDL value */ +static Uint8 ph2sdl_mousebutton(unsigned short button_state) +{ + Uint8 mouse_button = 0; + + if (button_state & Ph_BUTTON_SELECT) + mouse_button |= SDL_BUTTON_LEFT; + if (button_state & Ph_BUTTON_MENU) + mouse_button |= SDL_BUTTON_RIGHT; + if (button_state & Ph_BUTTON_ADJUST) + mouse_button |= SDL_BUTTON_MIDDLE; + + return (mouse_button); +} + +static int ph_DispatchEvent(_THIS) +{ + int posted; + PhRect_t* rect; + PhPointerEvent_t* pointerEvent; + PhKeyEvent_t* keyEvent; + PhWindowEvent_t* winEvent; + int i, buttons; + SDL_Rect sdlrects[PH_SDL_MAX_RECTS]; + + posted = 0; + + switch (phevent->type) + { + case Ph_EV_BOUNDARY: + { + if (phevent->subtype == Ph_EV_PTR_ENTER) + { + posted = SDL_PrivateAppActive(1, SDL_APPMOUSEFOCUS); + } + else if (phevent->subtype ==Ph_EV_PTR_LEAVE) + { + posted = SDL_PrivateAppActive(0, SDL_APPMOUSEFOCUS); + } + } + break; + + case Ph_EV_PTR_MOTION_BUTTON: + case Ph_EV_PTR_MOTION_NOBUTTON: + { + if (SDL_VideoSurface) + { + pointerEvent = PhGetData(phevent); + rect = PhGetRects(phevent); + + if (mouse_relative) + { + posted = ph_WarpedMotion(this, phevent); + } + else + { + posted = SDL_PrivateMouseMotion(0, 0, rect->ul.x, rect->ul.y); + } + } + } + break; + + case Ph_EV_BUT_PRESS: + { + pointerEvent = PhGetData(phevent); + buttons = ph2sdl_mousebutton(pointerEvent->buttons); + if (buttons != 0) + { + posted = SDL_PrivateMouseButton(SDL_PRESSED, buttons, 0, 0); + } + } + break; + + case Ph_EV_BUT_RELEASE: + { + pointerEvent = PhGetData(phevent); + buttons = ph2sdl_mousebutton(pointerEvent->buttons); + if (phevent->subtype == Ph_EV_RELEASE_REAL && buttons != 0) + { + posted = SDL_PrivateMouseButton(SDL_RELEASED, buttons, 0, 0); + } + else if(phevent->subtype == Ph_EV_RELEASE_PHANTOM) + { + /* If the mouse is outside the window, + * only a phantom release event is sent, so + * check if the window doesn't have mouse focus. + * Not perfect, maybe checking the mouse button + * state for Ph_EV_BOUNDARY events would be + * better. */ + if ((SDL_GetAppState() & SDL_APPMOUSEFOCUS) == 0) + { + posted = SDL_PrivateMouseButton(SDL_RELEASED, buttons, 0, 0); + } + } + } + break; + + case Ph_EV_WM: + { + winEvent = PhGetData(phevent); + + /* losing focus */ + if ((winEvent->event_f==Ph_WM_FOCUS) && (winEvent->event_state==Ph_WM_EVSTATE_FOCUSLOST)) + { + set_motion_sensitivity(this, Ph_EV_PTR_MOTION_BUTTON); + posted = SDL_PrivateAppActive(0, SDL_APPINPUTFOCUS); + } + /* gaining focus */ + else if ((winEvent->event_f==Ph_WM_FOCUS) && (winEvent->event_state==Ph_WM_EVSTATE_FOCUS)) + { + set_motion_sensitivity(this, -1); + posted = SDL_PrivateAppActive(1, SDL_APPINPUTFOCUS); + } + /* request quit */ + else if (winEvent->event_f==Ph_WM_CLOSE) + { + posted = SDL_PrivateQuit(); + } + /* request hide/unhide */ + else if (winEvent->event_f==Ph_WM_HIDE) + { + if (currently_hided) + { + /* got unhide window event */ + /* TODO: restore application's palette if in palette mode */ + currently_hided=0; + } + else + { + /* got hide window event */ + /* TODO: restore original palette if in palette mode */ + currently_hided=1; + } + } + /* request to resize */ + else if (winEvent->event_f==Ph_WM_RESIZE) + { + currently_maximized=0; + #if (_NTO_VERSION < 630) + SDL_PrivateResize(winEvent->size.w+1, winEvent->size.h+1); + #else + /* QNX 6.3.0 have this bug fixed */ + SDL_PrivateResize(winEvent->size.w, winEvent->size.h); + #endif /* _NTO_VERSION */ + } + /* request to move */ + else if (winEvent->event_f==Ph_WM_MOVE) + { + if (current_overlay!=NULL) + { + int lockedstate=current_overlay->hwdata->locked; + int chromastate=current_overlay->hwdata->ischromakey; + int error; + SDL_Rect src, dst; + + current_overlay->hwdata->locked=1; + src.x = 0; + src.y = 0; + src.w = current_overlay->w; + src.y = current_overlay->h; + dst.x=current_overlay->hwdata->CurrentViewPort.pos.x; + dst.y=current_overlay->hwdata->CurrentViewPort.pos.y; + dst.w=current_overlay->hwdata->CurrentViewPort.size.w; + dst.h=current_overlay->hwdata->CurrentViewPort.size.h; + current_overlay->hwdata->ischromakey=0; + error=ph_DisplayYUVOverlay(this, current_overlay, &src, &dst); + if (!error) + { + current_overlay->hwdata->ischromakey=chromastate; + current_overlay->hwdata->locked=lockedstate; + } + } + } + /* maximize request */ + else if (winEvent->event_f==Ph_WM_MAX) + { + /* window already moved and resized here */ + currently_maximized=1; + } + /* restore request */ + else if (winEvent->event_f==Ph_WM_RESTORE) + { + /* window already moved and resized here */ + currently_maximized=0; + } + } + break; + + /* window has been resized, moved or removed */ + case Ph_EV_EXPOSE: + { + if (phevent->num_rects!=0) + { + int numrects; + + if (SDL_VideoSurface) + { + rect = PhGetRects(phevent); + if (phevent->num_rects>PH_SDL_MAX_RECTS) + { + /* sorry, buffers underrun, we'll update only first PH_SDL_MAX_RECTS rects */ + numrects=PH_SDL_MAX_RECTS; + } + + for(i=0; i<phevent->num_rects; i++) + { + sdlrects[i].x = rect[i].ul.x; + sdlrects[i].y = rect[i].ul.y; + sdlrects[i].w = rect[i].lr.x - rect[i].ul.x + 1; + sdlrects[i].h = rect[i].lr.y - rect[i].ul.y + 1; + } + + this->UpdateRects(this, phevent->num_rects, sdlrects); + + if (current_overlay!=NULL) + { + int lockedstate=current_overlay->hwdata->locked; + int error; + SDL_Rect src, dst; + + current_overlay->hwdata->locked=1; + src.x = 0; + src.y = 0; + src.w = current_overlay->w; + src.y = current_overlay->h; + dst.x=current_overlay->hwdata->CurrentViewPort.pos.x; + dst.y=current_overlay->hwdata->CurrentViewPort.pos.y; + dst.w=current_overlay->hwdata->CurrentViewPort.size.w; + dst.h=current_overlay->hwdata->CurrentViewPort.size.h; + current_overlay->hwdata->forcedredraw=1; + error=ph_DisplayYUVOverlay(this, current_overlay, &src, &dst); + if (!error) + { + current_overlay->hwdata->forcedredraw=0; + current_overlay->hwdata->locked=lockedstate; + } + } + } + } + } + break; + + case Ph_EV_KEY: + { + SDL_keysym keysym; + + posted = 0; + + keyEvent = PhGetData(phevent); + + if (Pk_KF_Key_Down & keyEvent->key_flags) + { + /* split the wheel events from real key events */ + if ((keyEvent->key_cap==Pk_Up) && (keyEvent->key_scan==0) && ((keyEvent->key_flags & Pk_KF_Scan_Valid)==Pk_KF_Scan_Valid)) + { + posted = SDL_PrivateMouseButton(SDL_PRESSED, SDL_BUTTON_WHEELUP, 0, 0); + break; + } + if ((keyEvent->key_cap==Pk_Down) && (keyEvent->key_scan==0) && ((keyEvent->key_flags & Pk_KF_Scan_Valid)==Pk_KF_Scan_Valid)) + { + posted = SDL_PrivateMouseButton(SDL_PRESSED, SDL_BUTTON_WHEELDOWN, 0, 0); + break; + } + posted = SDL_PrivateKeyboard(SDL_PRESSED, ph_TranslateKey(keyEvent, &keysym)); + } + else /* must be key release */ + { + /* split the wheel events from real key events */ + if ((keyEvent->key_cap==Pk_Up) && (keyEvent->key_scan==0) && ((keyEvent->key_flags & Pk_KF_Scan_Valid)==Pk_KF_Scan_Valid)) + { + posted = SDL_PrivateMouseButton(SDL_RELEASED, SDL_BUTTON_WHEELUP, 0, 0); + break; + } + if ((keyEvent->key_cap==Pk_Down) && (keyEvent->key_scan==0) && ((keyEvent->key_flags & Pk_KF_Scan_Valid)==Pk_KF_Scan_Valid)) + { + posted = SDL_PrivateMouseButton(SDL_RELEASED, SDL_BUTTON_WHEELDOWN, 0, 0); + break; + } + posted = SDL_PrivateKeyboard(SDL_RELEASED, ph_TranslateKey( keyEvent, &keysym)); + } + } + break; + + case Ph_EV_INFO: + { + if (phevent->subtype==Ph_OFFSCREEN_INVALID) + { + unsigned long* EvInfoData; + + EvInfoData=(unsigned long*)PhGetData(phevent); + + switch (*EvInfoData) + { + case Pg_VIDEO_MODE_SWITCHED: + { + } + break; + case Pg_ENTERED_DIRECT: + { + } + break; + case Pg_EXITED_DIRECT: + { + } + break; + case Pg_DRIVER_STARTED: + { + } + break; + } + } + } + break; + } + + return(posted); +} + +/* perform a blocking read if no events available */ +int ph_Pending(_THIS) +{ + /* Flush the display connection and look to see if events are queued */ + PgFlush(); + + while (1) + { + switch(PhEventPeek(phevent, EVENT_SIZE)) + { + case Ph_EVENT_MSG: + return 1; + case -1: + SDL_SetError("ph_Pending(): PhEventNext failed.\n"); + return 0; + default: + return 0; + } + } + + /* Oh well, nothing is ready .. */ + return(0); +} + +void ph_PumpEvents(_THIS) +{ + /* Flush the display connection and look to see if events are queued */ + PgFlush(); + + while (ph_Pending(this)) + { + PtEventHandler(phevent); + ph_DispatchEvent(this); + } +} + +void ph_InitKeymap(void) +{ + int i; + + /* Odd keys used in international keyboards */ + for (i=0; i<SDL_arraysize(ODD_keymap); ++i) + { + ODD_keymap[i] = SDLK_UNKNOWN; + } + + /* Map the miscellaneous keys */ + for (i=0; i<SDL_arraysize(MISC_keymap); ++i) + { + MISC_keymap[i] = SDLK_UNKNOWN; + } + + MISC_keymap[Pk_BackSpace&0xFF] = SDLK_BACKSPACE; + MISC_keymap[Pk_Tab&0xFF] = SDLK_TAB; + MISC_keymap[Pk_Clear&0xFF] = SDLK_CLEAR; + MISC_keymap[Pk_Return&0xFF] = SDLK_RETURN; + MISC_keymap[Pk_Pause&0xFF] = SDLK_PAUSE; + MISC_keymap[Pk_Escape&0xFF] = SDLK_ESCAPE; + MISC_keymap[Pk_Delete&0xFF] = SDLK_DELETE; + + MISC_keymap[Pk_KP_0&0xFF] = SDLK_KP0; + MISC_keymap[Pk_KP_1&0xFF] = SDLK_KP1; + MISC_keymap[Pk_KP_2&0xFF] = SDLK_KP2; + MISC_keymap[Pk_KP_3&0xFF] = SDLK_KP3; + MISC_keymap[Pk_KP_4&0xFF] = SDLK_KP4; + MISC_keymap[Pk_KP_5&0xFF] = SDLK_KP5; + MISC_keymap[Pk_KP_6&0xFF] = SDLK_KP6; + MISC_keymap[Pk_KP_7&0xFF] = SDLK_KP7; + MISC_keymap[Pk_KP_8&0xFF] = SDLK_KP8; + MISC_keymap[Pk_KP_9&0xFF] = SDLK_KP9; + + MISC_keymap[Pk_KP_Decimal&0xFF] = SDLK_KP_PERIOD; + MISC_keymap[Pk_KP_Divide&0xFF] = SDLK_KP_DIVIDE; + MISC_keymap[Pk_KP_Multiply&0xFF] = SDLK_KP_MULTIPLY; + MISC_keymap[Pk_KP_Subtract&0xFF] = SDLK_KP_MINUS; + MISC_keymap[Pk_KP_Add&0xFF] = SDLK_KP_PLUS; + MISC_keymap[Pk_KP_Enter&0xFF] = SDLK_KP_ENTER; + MISC_keymap[Pk_KP_Equal&0xFF] = SDLK_KP_EQUALS; + + MISC_keymap[Pk_Up&0xFF] = SDLK_UP; + MISC_keymap[Pk_Down&0xFF] = SDLK_DOWN; + MISC_keymap[Pk_Right&0xFF] = SDLK_RIGHT; + MISC_keymap[Pk_Left&0xFF] = SDLK_LEFT; + MISC_keymap[Pk_Insert&0xFF] = SDLK_INSERT; + MISC_keymap[Pk_Home&0xFF] = SDLK_HOME; + MISC_keymap[Pk_End&0xFF] = SDLK_END; + MISC_keymap[Pk_Pg_Up&0xFF] = SDLK_PAGEUP; + MISC_keymap[Pk_Pg_Down&0xFF] = SDLK_PAGEDOWN; + + MISC_keymap[Pk_F1&0xFF] = SDLK_F1; + MISC_keymap[Pk_F2&0xFF] = SDLK_F2; + MISC_keymap[Pk_F3&0xFF] = SDLK_F3; + MISC_keymap[Pk_F4&0xFF] = SDLK_F4; + MISC_keymap[Pk_F5&0xFF] = SDLK_F5; + MISC_keymap[Pk_F6&0xFF] = SDLK_F6; + MISC_keymap[Pk_F7&0xFF] = SDLK_F7; + MISC_keymap[Pk_F8&0xFF] = SDLK_F8; + MISC_keymap[Pk_F9&0xFF] = SDLK_F9; + MISC_keymap[Pk_F10&0xFF] = SDLK_F10; + MISC_keymap[Pk_F11&0xFF] = SDLK_F11; + MISC_keymap[Pk_F12&0xFF] = SDLK_F12; + MISC_keymap[Pk_F13&0xFF] = SDLK_F13; + MISC_keymap[Pk_F14&0xFF] = SDLK_F14; + MISC_keymap[Pk_F15&0xFF] = SDLK_F15; + + MISC_keymap[Pk_Num_Lock&0xFF] = SDLK_NUMLOCK; + MISC_keymap[Pk_Caps_Lock&0xFF] = SDLK_CAPSLOCK; + MISC_keymap[Pk_Scroll_Lock&0xFF] = SDLK_SCROLLOCK; + MISC_keymap[Pk_Shift_R&0xFF] = SDLK_RSHIFT; + MISC_keymap[Pk_Shift_L&0xFF] = SDLK_LSHIFT; + MISC_keymap[Pk_Control_R&0xFF] = SDLK_RCTRL; + MISC_keymap[Pk_Control_L&0xFF] = SDLK_LCTRL; + MISC_keymap[Pk_Alt_R&0xFF] = SDLK_RALT; + MISC_keymap[Pk_Alt_L&0xFF] = SDLK_LALT; + MISC_keymap[Pk_Meta_R&0xFF] = SDLK_RMETA; + MISC_keymap[Pk_Meta_L&0xFF] = SDLK_LMETA; + MISC_keymap[Pk_Super_L&0xFF] = SDLK_LSUPER; + MISC_keymap[Pk_Super_R&0xFF] = SDLK_RSUPER; + MISC_keymap[Pk_Mode_switch&0xFF] = SDLK_MODE; /* "Alt Gr" key */ + + MISC_keymap[Pk_Help&0xFF] = SDLK_HELP; + MISC_keymap[Pk_Print&0xFF] = SDLK_PRINT; + MISC_keymap[Pk_Break&0xFF] = SDLK_BREAK; + MISC_keymap[Pk_Menu&0xFF] = SDLK_MENU; /* Windows "Menu" key */ + + MISC_keymap[Pk_Hyper_R&0xFF] = SDLK_RSUPER; /* Right "Windows" */ + + /* Left "Windows" key, but it can't be catched by application */ + MISC_keymap[Pk_Hyper_L&0xFF] = SDLK_LSUPER; +} + +static unsigned long cap; + +SDL_keysym *ph_TranslateKey(PhKeyEvent_t *key, SDL_keysym *keysym) +{ + /* 'sym' is set to the value of the key with modifiers applied to it. + This member is valid only if Pk_KF_Sym_Valid is set in the key_flags. + We will assume it is valid. */ + + /* FIXME: This needs to check whether the cap & scancode is valid */ + + cap = key->key_cap; + + switch (cap>>8) + { + case 0x00: /* Latin 1 */ + case 0x01: /* Latin 2 */ + case 0x02: /* Latin 3 */ + case 0x03: /* Latin 4 */ + case 0x04: /* Katakana */ + case 0x05: /* Arabic */ + case 0x06: /* Cyrillic */ + case 0x07: /* Greek */ + case 0x08: /* Technical */ + case 0x0A: /* Publishing */ + case 0x0C: /* Hebrew */ + case 0x0D: /* Thai */ + keysym->sym = (SDLKey)(cap&0xFF); + /* Map capital letter syms to lowercase */ + if ((keysym->sym >= 'A')&&(keysym->sym <= 'Z')) + keysym->sym += ('a'-'A'); + break; + case 0xF0: + keysym->sym = MISC_keymap[cap&0xFF]; + break; + default: + keysym->sym = SDLK_UNKNOWN; + break; + } + + keysym->scancode = key->key_scan; + keysym->unicode = 0; + + if (SDL_TranslateUNICODE) + { + char utf8[MB_CUR_MAX]; + int utf8len; + wchar_t unicode; + + switch (keysym->scancode) + { + /* Esc key */ + case 0x01: keysym->unicode = 27; + break; + /* BackSpace key */ + case 0x0E: keysym->unicode = 127; + break; + /* Enter key */ + case 0x1C: keysym->unicode = 10; + break; + default: + utf8len = PhKeyToMb(utf8, key); + if (utf8len > 0) + { + utf8len = mbtowc(&unicode, utf8, utf8len); + if (utf8len > 0) + { + keysym->unicode = unicode; + } + } + break; + } + + } + + return (keysym); +} + +void ph_InitOSKeymap(_THIS) +{ + ph_InitKeymap(); +} diff --git a/3rdparty/SDL/src/video/photon/SDL_ph_events_c.h b/3rdparty/SDL/src/video/photon/SDL_ph_events_c.h new file mode 100644 index 0000000..4aa939b --- /dev/null +++ b/3rdparty/SDL/src/video/photon/SDL_ph_events_c.h @@ -0,0 +1,37 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#ifndef __SDL_PH_EVENTS_H__ +#define __SDL_PH_EVENTS_H__ + +#include "SDL_ph_video.h" + +#define PH_SDL_MAX_RECTS 256 +#define PH_EVENT_SAFETY_POOL 512 +#define EVENT_SIZE (sizeof(PhEvent_t) + 1000 + PH_EVENT_SAFETY_POOL) + +/* Functions to be exported */ +extern void ph_InitOSKeymap(_THIS); +extern void ph_PumpEvents(_THIS); + +#endif /* __SDL_PH_EVENTS_H__ */ diff --git a/3rdparty/SDL/src/video/photon/SDL_ph_gl.c b/3rdparty/SDL/src/video/photon/SDL_ph_gl.c new file mode 100644 index 0000000..3121777 --- /dev/null +++ b/3rdparty/SDL/src/video/photon/SDL_ph_gl.c @@ -0,0 +1,406 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#include <dlfcn.h> +#include "SDL.h" +#include "SDL_ph_gl.h" + +#if SDL_VIDEO_OPENGL + +#if (_NTO_VERSION >= 630) + /* PhotonGL functions */ + GLPH_DECLARE_FUNCS; +#endif /* 6.3.0 */ + +#if (_NTO_VERSION < 630) +void ph_GL_SwapBuffers(_THIS) +{ + PgSetRegion(PtWidgetRid(window)); + PdOpenGLContextSwapBuffers(oglctx); +} +#else +void ph_GL_SwapBuffers(_THIS) +{ + qnxgl_swap_buffers(oglbuffers); +} +#endif /* 6.3.0 */ + +int ph_GL_GetAttribute(_THIS, SDL_GLattr attrib, int* value) +{ + switch (attrib) + { + case SDL_GL_DOUBLEBUFFER: + *value=this->gl_config.double_buffer; + break; + case SDL_GL_STENCIL_SIZE: + *value=this->gl_config.stencil_size; + break; + case SDL_GL_DEPTH_SIZE: + *value=this->gl_config.depth_size; + break; +#if (_NTO_VERSION >= 630) + case SDL_GL_RED_SIZE: + *value=this->gl_config.red_size; + break; + case SDL_GL_GREEN_SIZE: + *value=this->gl_config.green_size; + break; + case SDL_GL_BLUE_SIZE: + *value=this->gl_config.blue_size; + break; + case SDL_GL_ALPHA_SIZE: + *value=this->gl_config.alpha_size; + break; + case SDL_GL_ACCUM_RED_SIZE: + *value=this->gl_config.accum_red_size; + break; + case SDL_GL_ACCUM_GREEN_SIZE: + *value=this->gl_config.accum_green_size; + break; + case SDL_GL_ACCUM_BLUE_SIZE: + *value=this->gl_config.accum_blue_size; + break; + case SDL_GL_ACCUM_ALPHA_SIZE: + *value=this->gl_config.accum_alpha_size; + break; + case SDL_GL_STEREO: + *value=this->gl_config.stereo; + break; +#endif /* 6.3.0 */ + default: + *value=0; + return(-1); + } + return 0; +} + +#if (_NTO_VERSION < 630) +int ph_GL_LoadLibrary(_THIS, const char* path) +{ + /* if code compiled with SDL_VIDEO_OPENGL, that mean that library already linked */ + this->gl_config.driver_loaded = 1; + + return 0; +} +#else +int ph_GL_LoadLibrary(_THIS, const char* path) +{ + void* handle; + int dlopen_flags=RTLD_WORLD | RTLD_GROUP; + + if (this->gl_config.dll_handle!=NULL) + { + return 0; + } + + handle = dlopen(path, dlopen_flags); + + if (handle==NULL) + { + SDL_SetError("ph_GL_LoadLibrary(): Could not load OpenGL library"); + return -1; + } + + this->gl_config.dll_handle = handle; + this->gl_config.driver_loaded = 1; + + SDL_strlcpy(this->gl_config.driver_path, path, SDL_arraysize(this->gl_config.driver_path)); + + return 0; +} +#endif /* 6.3.0 */ + +#if (_NTO_VERSION < 630) +void* ph_GL_GetProcAddress(_THIS, const char* proc) +{ + return NULL; +} +#else +void* ph_GL_GetProcAddress(_THIS, const char* proc) +{ + void* function; + + if (this->gl_config.dll_handle==NULL) + { + ph_GL_LoadLibrary(this, DEFAULT_OPENGL); + if (this->gl_config.dll_handle==NULL) + { + return NULL; + } + } + + function=qnxgl_get_func(proc, oglctx, 0); + if (function==NULL) + { + function=dlsym(this->gl_config.dll_handle, proc); + } + + return function; +} +#endif /* 6.3.0 */ + +#if (_NTO_VERSION < 630) +int ph_GL_MakeCurrent(_THIS) +{ + PgSetRegion(PtWidgetRid(window)); + + if (oglctx!=NULL) + { + PhDCSetCurrent(oglctx); + } + + return 0; +} +#else +int ph_GL_MakeCurrent(_THIS) +{ + PgSetRegion(PtWidgetRid(window)); + + if (oglctx!=NULL) + { + if (qnxgl_set_current(oglctx) == -1) + { + return -1; + } + } + + return 0; +} +#endif /* 6.3.0 */ + +#if (_NTO_VERSION < 630) + +/* This code is actual for the Photon3D Runtime which was available prior to 6.3 only */ + +int ph_SetupOpenGLContext(_THIS, int width, int height, int bpp, Uint32 flags) +{ + PhDim_t dim; + uint64_t OGLAttrib[PH_OGL_MAX_ATTRIBS]; + int exposepost=0; + int OGLargc; + + dim.w=width; + dim.h=height; + + if ((oglctx!=NULL) && (oglflags==flags) && (oglbpp==bpp)) + { + PdOpenGLContextResize(oglctx, &dim); + PhDCSetCurrent(oglctx); + return 0; + } + else + { + if (oglctx!=NULL) + { + PhDCSetCurrent(NULL); + PhDCRelease(oglctx); + oglctx=NULL; + exposepost=1; + } + } + + OGLargc=0; + if (this->gl_config.depth_size) + { + OGLAttrib[OGLargc++]=PHOGL_ATTRIB_DEPTH_BITS; + OGLAttrib[OGLargc++]=this->gl_config.depth_size; + } + if (this->gl_config.stencil_size) + { + OGLAttrib[OGLargc++]=PHOGL_ATTRIB_STENCIL_BITS; + OGLAttrib[OGLargc++]=this->gl_config.stencil_size; + } + OGLAttrib[OGLargc++]=PHOGL_ATTRIB_FORCE_SW; + if (flags & SDL_FULLSCREEN) + { + OGLAttrib[OGLargc++]=PHOGL_ATTRIB_FULLSCREEN; + OGLAttrib[OGLargc++]=PHOGL_ATTRIB_DIRECT; + OGLAttrib[OGLargc++]=PHOGL_ATTRIB_FULLSCREEN_BEST; + OGLAttrib[OGLargc++]=PHOGL_ATTRIB_FULLSCREEN_CENTER; + } + OGLAttrib[OGLargc++]=PHOGL_ATTRIB_NONE; + + if (this->gl_config.double_buffer) + { + oglctx=PdCreateOpenGLContext(2, &dim, 0, OGLAttrib); + } + else + { + oglctx=PdCreateOpenGLContext(1, &dim, 0, OGLAttrib); + } + + if (oglctx==NULL) + { + SDL_SetError("ph_SetupOpenGLContext(): cannot create OpenGL context !\n"); + return -1; + } + + PhDCSetCurrent(oglctx); + + PtFlush(); + + oglflags=flags; + oglbpp=bpp; + + if (exposepost!=0) + { + /* OpenGL context has been recreated, so report about this fact */ + SDL_PrivateExpose(); + } + + return 0; +} + +#else /* _NTO_VERSION */ + +/* This code is actual for the built-in PhGL support, which became available since 6.3 */ + +int ph_SetupOpenGLContext(_THIS, int width, int height, int bpp, Uint32 flags) +{ + qnxgl_buf_attrib_t qnxgl_attribs[PH_OGL_MAX_ATTRIBS]; + qnxgl_buf_attrib_t* qnxgl_attribs_slide; + int num_interfaces = 0; + int num_buffers = 0; + + /* Initialize the OpenGL subsystem */ + + num_interfaces = qnxgl_init(NULL, NULL, 0); + + if (num_interfaces < 0) + { + SDL_SetError("ph_SetupOpenGLContext(): cannot initialize OpenGL subsystem !\n"); + return -1; + } + if (num_interfaces == 0) + { + SDL_SetError("ph_SetupOpenGLContext(): there are no available OpenGL renderers was found !\n"); + return -1; + } + + /* Driver is linked */ + this->gl_config.driver_loaded=1; + + /* Initialize the OpenGL context attributes */ + qnxgl_attribs_slide=qnxgl_attribs; + + /* Depth size */ + if (this->gl_config.depth_size) + { + fprintf(stderr, "setted depth size %d\n", this->gl_config.depth_size); + qnxgl_attribs_slide = qnxgl_attrib_set_depth(qnxgl_attribs_slide, this->gl_config.depth_size); + } + + /* Stencil size */ + if (this->gl_config.stencil_size) + { + qnxgl_attribs_slide = qnxgl_attrib_set_stencil(qnxgl_attribs_slide, this->gl_config.stencil_size); + } + + /* The sum of the accum bits of each channel */ + if ((this->gl_config.accum_red_size != 0) && (this->gl_config.accum_blue_size != 0) && + (this->gl_config.accum_green_size != 0)) + { + qnxgl_attribs_slide = qnxgl_attrib_set_accum(qnxgl_attribs_slide, + this->gl_config.accum_red_size + this->gl_config.accum_blue_size + + this->gl_config.accum_green_size + this->gl_config.accum_alpha_size); + } + + /* Stereo mode */ + if (this->gl_config.stereo) + { + qnxgl_attribs_slide = qnxgl_attrib_set_stereo(qnxgl_attribs_slide); + } + + /* Fullscreen mode */ + if ((flags & SDL_FULLSCREEN) == SDL_FULLSCREEN) + { + qnxgl_attribs_slide = qnxgl_attrib_set_hint_fullscreen(qnxgl_attribs_slide); + } + + /* Double buffering mode */ + if (this->gl_config.double_buffer) + { + num_buffers=2; + } + else + { + num_buffers=1; + } + + /* Loading the function pointers so we can use the extensions */ + GLPH_LOAD_FUNCS_GC(oglctx); + + /* Set the buffers region to be that of our window's region */ + qnxgl_attribs_slide = glph_attrib_set_region(qnxgl_attribs_slide, PtWidgetRid(window)); + + /* End of the attributes array */ + qnxgl_attribs_slide = qnxgl_attrib_set_end(qnxgl_attribs_slide); + + /* Create the buffers with the specified color model */ + fprintf(stderr, "ARGB: %d, %d, %d, %d\n", this->gl_config.alpha_size, this->gl_config.red_size, this->gl_config.green_size, this->gl_config.blue_size); + oglbuffers = qnxgl_buffers_create( + QNXGL_FORMAT_BEST_RGB, +/* __QNXGL_BUILD_FORMAT(0, __QNXGL_COLOR_MODEL_RGB, this->gl_config.alpha_size, + this->gl_config.red_size, this->gl_config.green_size, this->gl_config.blue_size), */ + num_buffers, width, height, qnxgl_attribs, -1); + + + if (oglbuffers == NULL) + { + SDL_SetError("ph_SetupOpenGLContext(): failed to create OpenGL buffers !\n"); + qnxgl_finish(); + return -1; + } + + /* Create a QNXGL context for the previously created buffer */ + oglctx = qnxgl_context_create(oglbuffers, NULL); + + if (oglctx == NULL) + { + SDL_SetError("ph_SetupOpenGLContext(): failed to create OpenGL context !\n"); + qnxgl_buffers_destroy(oglbuffers); + qnxgl_finish(); + return -1; + } + + /* Attempt to make the context current so we can use OpenGL commands */ + if (qnxgl_set_current(oglctx) == -1) + { + SDL_SetError("ph_SetupOpenGLContext(): failed to make the OpenGL context current !\n"); + qnxgl_context_destroy(oglctx); + qnxgl_buffers_destroy(oglbuffers); + qnxgl_finish(); + return -1; + } + + PtFlush(); + + oglflags=flags; + oglbpp=bpp; + + return 0; +} + +#endif /* _NTO_VERSION */ + +#endif /* SDL_VIDEO_OPENGL */ diff --git a/3rdparty/SDL/src/video/photon/SDL_ph_gl.h b/3rdparty/SDL/src/video/photon/SDL_ph_gl.h new file mode 100644 index 0000000..1fb134a --- /dev/null +++ b/3rdparty/SDL/src/video/photon/SDL_ph_gl.h @@ -0,0 +1,41 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#ifndef __SDL_PH_GL_H__ +#define __SDL_PH_GL_H__ + +#include "SDL_ph_video.h" + +#define DEFAULT_OPENGL "/usr/lib/libGL.so" + +#if SDL_VIDEO_OPENGL + void ph_GL_SwapBuffers(_THIS); + int ph_GL_GetAttribute(_THIS, SDL_GLattr attrib, int* value); + int ph_GL_LoadLibrary(_THIS, const char* path); + void* ph_GL_GetProcAddress(_THIS, const char* proc); + int ph_GL_MakeCurrent(_THIS); + + int ph_SetupOpenGLContext(_THIS, int width, int height, int bpp, Uint32 flags); +#endif /* SDL_VIDEO_OPENGL */ + +#endif /* __SDL_PH_GL_H__ */ diff --git a/3rdparty/SDL/src/video/photon/SDL_ph_image.c b/3rdparty/SDL/src/video/photon/SDL_ph_image.c new file mode 100644 index 0000000..7d64970 --- /dev/null +++ b/3rdparty/SDL/src/video/photon/SDL_ph_image.c @@ -0,0 +1,1059 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#include <Ph.h> +#include <photon/Pg.h> + +#include "SDL_endian.h" +#include "SDL_video.h" +#include "../SDL_pixels_c.h" +#include "SDL_ph_video.h" +#include "SDL_ph_image_c.h" +#include "SDL_ph_modes_c.h" +#include "SDL_ph_gl.h" + +int ph_SetupImage(_THIS, SDL_Surface *screen) +{ + PgColor_t* palette=NULL; + int type=0; + int bpp; + + bpp=screen->format->BitsPerPixel; + + /* Determine image type */ + switch(bpp) + { + case 8:{ + type = Pg_IMAGE_PALETTE_BYTE; + } + break; + case 15:{ + type = Pg_IMAGE_DIRECT_555; + } + break; + case 16:{ + type = Pg_IMAGE_DIRECT_565; + } + break; + case 24:{ + type = Pg_IMAGE_DIRECT_888; + } + break; + case 32:{ + type = Pg_IMAGE_DIRECT_8888; + } + break; + default:{ + SDL_SetError("ph_SetupImage(): unsupported bpp=%d !\n", bpp); + return -1; + } + break; + } + + /* palette emulation code */ + if ((bpp==8) && (desktoppal==SDLPH_PAL_EMULATE)) + { + /* creating image palette */ + palette=SDL_malloc(_Pg_MAX_PALETTE*sizeof(PgColor_t)); + if (palette==NULL) + { + SDL_SetError("ph_SetupImage(): can't allocate memory for palette !\n"); + return -1; + } + PgGetPalette(palette); + + /* using shared memory for speed (set last param to 1) */ + if ((SDL_Image = PhCreateImage(NULL, screen->w, screen->h, type, palette, _Pg_MAX_PALETTE, 1)) == NULL) + { + SDL_SetError("ph_SetupImage(): PhCreateImage() failed for bpp=8 !\n"); + SDL_free(palette); + return -1; + } + } + else + { + /* using shared memory for speed (set last param to 1) */ + if ((SDL_Image = PhCreateImage(NULL, screen->w, screen->h, type, NULL, 0, 1)) == NULL) + { + SDL_SetError("ph_SetupImage(): PhCreateImage() failed for bpp=%d !\n", bpp); + return -1; + } + } + + screen->pixels = SDL_Image->image; + screen->pitch = SDL_Image->bpl; + + this->UpdateRects = ph_NormalUpdate; + + return 0; +} + +int ph_SetupOCImage(_THIS, SDL_Surface *screen) +{ + int type = 0; + int bpp; + + OCImage.flags = screen->flags; + + bpp=screen->format->BitsPerPixel; + + /* Determine image type */ + switch(bpp) + { + case 8: { + type = Pg_IMAGE_PALETTE_BYTE; + } + break; + case 15:{ + type = Pg_IMAGE_DIRECT_555; + } + break; + case 16:{ + type = Pg_IMAGE_DIRECT_565; + } + break; + case 24:{ + type = Pg_IMAGE_DIRECT_888; + } + break; + case 32:{ + type = Pg_IMAGE_DIRECT_8888; + } + break; + default:{ + SDL_SetError("ph_SetupOCImage(): unsupported bpp=%d !\n", bpp); + return -1; + } + break; + } + + /* Currently offscreen contexts with the same bit depth as display bpp only can be created */ + OCImage.offscreen_context = PdCreateOffscreenContext(0, screen->w, screen->h, Pg_OSC_MEM_PAGE_ALIGN); + + if (OCImage.offscreen_context == NULL) + { + SDL_SetError("ph_SetupOCImage(): PdCreateOffscreenContext() function failed !\n"); + return -1; + } + + screen->pitch = OCImage.offscreen_context->pitch; + + OCImage.dc_ptr = (unsigned char *)PdGetOffscreenContextPtr(OCImage.offscreen_context); + + if (OCImage.dc_ptr == NULL) + { + SDL_SetError("ph_SetupOCImage(): PdGetOffscreenContextPtr function failed !\n"); + PhDCRelease(OCImage.offscreen_context); + return -1; + } + + OCImage.FrameData0 = OCImage.dc_ptr; + OCImage.CurrentFrameData = OCImage.FrameData0; + OCImage.current = 0; + + PhDCSetCurrent(OCImage.offscreen_context); + + screen->pixels = OCImage.CurrentFrameData; + + this->UpdateRects = ph_OCUpdate; + + return 0; +} + +int ph_SetupFullScreenImage(_THIS, SDL_Surface* screen) +{ + OCImage.flags = screen->flags; + + /* Begin direct and fullscreen mode */ + if (!ph_EnterFullScreen(this, screen, PH_ENTER_DIRECTMODE)) + { + return -1; + } + + /* store palette for fullscreen */ + if ((screen->format->BitsPerPixel==8) && (desktopbpp!=8)) + { + PgGetPalette(savedpal); + PgGetPalette(syspalph); + } + + OCImage.offscreen_context = PdCreateOffscreenContext(0, 0, 0, Pg_OSC_MAIN_DISPLAY | Pg_OSC_MEM_PAGE_ALIGN | Pg_OSC_CRTC_SAFE); + if (OCImage.offscreen_context == NULL) + { + SDL_SetError("ph_SetupFullScreenImage(): PdCreateOffscreenContext() function failed !\n"); + return -1; + } + + if ((screen->flags & SDL_DOUBLEBUF) == SDL_DOUBLEBUF) + { + OCImage.offscreen_backcontext = PdDupOffscreenContext(OCImage.offscreen_context, Pg_OSC_MEM_PAGE_ALIGN | Pg_OSC_CRTC_SAFE); + if (OCImage.offscreen_backcontext == NULL) + { + SDL_SetError("ph_SetupFullScreenImage(): PdCreateOffscreenContext(back) function failed !\n"); + return -1; + } + } + + OCImage.FrameData0 = (unsigned char *)PdGetOffscreenContextPtr(OCImage.offscreen_context); + if (OCImage.FrameData0 == NULL) + { + SDL_SetError("ph_SetupFullScreenImage(): PdGetOffscreenContextPtr() function failed !\n"); + ph_DestroyImage(this, screen); + return -1; + } + + if ((screen->flags & SDL_DOUBLEBUF) == SDL_DOUBLEBUF) + { + OCImage.FrameData1 = (unsigned char *)PdGetOffscreenContextPtr(OCImage.offscreen_backcontext); + if (OCImage.FrameData1 == NULL) + { + SDL_SetError("ph_SetupFullScreenImage(back): PdGetOffscreenContextPtr() function failed !\n"); + ph_DestroyImage(this, screen); + return -1; + } + } + + /* wait for the hardware */ + PgFlush(); + PgWaitHWIdle(); + + if ((screen->flags & SDL_DOUBLEBUF) == SDL_DOUBLEBUF) + { + OCImage.current = 0; + PhDCSetCurrent(OCImage.offscreen_context); + screen->pitch = OCImage.offscreen_context->pitch; + screen->pixels = OCImage.FrameData0; + + /* emulate 640x400 videomode */ + if (videomode_emulatemode==1) + { + int i; + + for (i=0; i<40; i++) + { + SDL_memset(screen->pixels+screen->pitch*i, 0x00, screen->pitch); + } + for (i=440; i<480; i++) + { + SDL_memset(screen->pixels+screen->pitch*i, 0x00, screen->pitch); + } + screen->pixels+=screen->pitch*40; + } + PgSwapDisplay(OCImage.offscreen_backcontext, 0); + } + else + { + OCImage.current = 0; + PhDCSetCurrent(OCImage.offscreen_context); + screen->pitch = OCImage.offscreen_context->pitch; + screen->pixels = OCImage.FrameData0; + + /* emulate 640x400 videomode */ + if (videomode_emulatemode==1) + { + int i; + + for (i=0; i<40; i++) + { + SDL_memset(screen->pixels+screen->pitch*i, 0x00, screen->pitch); + } + for (i=440; i<480; i++) + { + SDL_memset(screen->pixels+screen->pitch*i, 0x00, screen->pitch); + } + screen->pixels+=screen->pitch*40; + } + } + + this->UpdateRects = ph_OCDCUpdate; + + /* wait for the hardware */ + PgFlush(); + PgWaitHWIdle(); + + return 0; +} + +#if SDL_VIDEO_OPENGL + +int ph_SetupOpenGLImage(_THIS, SDL_Surface* screen) +{ + this->UpdateRects = ph_OpenGLUpdate; + screen->pixels=NULL; + screen->pitch=NULL; + + #if (_NTO_VERSION >= 630) + if ((screen->flags & SDL_FULLSCREEN) == SDL_FULLSCREEN) + { + if (!ph_EnterFullScreen(this, screen, PH_IGNORE_DIRECTMODE)) + { + screen->flags &= ~SDL_FULLSCREEN; + return -1; + } + } + #endif /* 6.3.0 */ + + if (ph_SetupOpenGLContext(this, screen->w, screen->h, screen->format->BitsPerPixel, screen->flags)!=0) + { + screen->flags &= ~SDL_OPENGL; + return -1; + } + + return 0; +} + +#endif /* SDL_VIDEO_OPENGL */ + +void ph_DestroyImage(_THIS, SDL_Surface* screen) +{ + +#if SDL_VIDEO_OPENGL + if ((screen->flags & SDL_OPENGL)==SDL_OPENGL) + { + if (oglctx) + { + #if (_NTO_VERSION < 630) + PhDCSetCurrent(NULL); + PhDCRelease(oglctx); + #else + qnxgl_context_destroy(oglctx); + qnxgl_buffers_destroy(oglbuffers); + qnxgl_finish(); + #endif /* 6.3.0 */ + oglctx=NULL; + oglbuffers=NULL; + oglflags=0; + oglbpp=0; + } + + #if (_NTO_VERSION >= 630) + if (currently_fullscreen) + { + ph_LeaveFullScreen(this); + } + #endif /* 6.3.0 */ + + return; + } +#endif /* SDL_VIDEO_OPENGL */ + + if (currently_fullscreen) + { + /* if we right now in 8bpp fullscreen we must release palette */ + if ((screen->format->BitsPerPixel==8) && (desktopbpp!=8)) + { + PgSetPalette(syspalph, 0, -1, 0, 0, 0); + PgSetPalette(savedpal, 0, 0, _Pg_MAX_PALETTE, Pg_PALSET_GLOBAL | Pg_PALSET_FORCE_EXPOSE, 0); + PgFlush(); + } + ph_LeaveFullScreen(this); + } + + if (OCImage.offscreen_context != NULL) + { + PhDCRelease(OCImage.offscreen_context); + OCImage.offscreen_context = NULL; + OCImage.FrameData0 = NULL; + } + if (OCImage.offscreen_backcontext != NULL) + { + PhDCRelease(OCImage.offscreen_backcontext); + OCImage.offscreen_backcontext = NULL; + OCImage.FrameData1 = NULL; + } + OCImage.CurrentFrameData = NULL; + + if (SDL_Image) + { + /* if palette allocated, free it */ + if (SDL_Image->palette) + { + SDL_free(SDL_Image->palette); + } + PgShmemDestroy(SDL_Image->image); + SDL_free(SDL_Image); + } + + /* Must be zeroed everytime */ + SDL_Image = NULL; + + if (screen) + { + screen->pixels = NULL; + } +} + +int ph_UpdateHWInfo(_THIS) +{ + PgVideoModeInfo_t vmode; + PgHWCaps_t hwcaps; + + /* Update video ram amount */ + if (PgGetGraphicsHWCaps(&hwcaps) < 0) + { + SDL_SetError("ph_UpdateHWInfo(): GetGraphicsHWCaps() function failed !\n"); + return -1; + } + this->info.video_mem=hwcaps.currently_available_video_ram/1024; + + /* obtain current mode capabilities */ + if (PgGetVideoModeInfo(hwcaps.current_video_mode, &vmode) < 0) + { + SDL_SetError("ph_UpdateHWInfo(): GetVideoModeInfo() function failed !\n"); + return -1; + } + + if ((vmode.mode_capabilities1 & PgVM_MODE_CAP1_OFFSCREEN) == PgVM_MODE_CAP1_OFFSCREEN) + { + /* this is a special test for drivers which tries to lie about offscreen capability */ + if (hwcaps.currently_available_video_ram!=0) + { + this->info.hw_available = 1; + } + else + { + this->info.hw_available = 0; + } + } + else + { + this->info.hw_available = 0; + } + + if ((vmode.mode_capabilities2 & PgVM_MODE_CAP2_RECTANGLE) == PgVM_MODE_CAP2_RECTANGLE) + { + this->info.blit_fill = 1; + } + else + { + this->info.blit_fill = 0; + } + + if ((vmode.mode_capabilities2 & PgVM_MODE_CAP2_BITBLT) == PgVM_MODE_CAP2_BITBLT) + { + this->info.blit_hw = 1; + } + else + { + this->info.blit_hw = 0; + } + + if ((vmode.mode_capabilities2 & PgVM_MODE_CAP2_ALPHA_BLEND) == PgVM_MODE_CAP2_ALPHA_BLEND) + { + this->info.blit_hw_A = 1; + } + else + { + this->info.blit_hw_A = 0; + } + + if ((vmode.mode_capabilities2 & PgVM_MODE_CAP2_CHROMA) == PgVM_MODE_CAP2_CHROMA) + { + this->info.blit_hw_CC = 1; + } + else + { + this->info.blit_hw_CC = 0; + } + + return 0; +} + +int ph_SetupUpdateFunction(_THIS, SDL_Surface* screen, Uint32 flags) +{ + int setupresult=-1; + + ph_DestroyImage(this, screen); + +#if SDL_VIDEO_OPENGL + if ((flags & SDL_OPENGL)==SDL_OPENGL) + { + setupresult=ph_SetupOpenGLImage(this, screen); + } + else + { +#endif + if ((flags & SDL_FULLSCREEN)==SDL_FULLSCREEN) + { + setupresult=ph_SetupFullScreenImage(this, screen); + } + else + { + if ((flags & SDL_HWSURFACE)==SDL_HWSURFACE) + { + setupresult=ph_SetupOCImage(this, screen); + } + else + { + setupresult=ph_SetupImage(this, screen); + } + } +#if SDL_VIDEO_OPENGL + } +#endif + if (setupresult!=-1) + { + ph_UpdateHWInfo(this); + } + + return setupresult; +} + +int ph_AllocHWSurface(_THIS, SDL_Surface* surface) +{ + PgHWCaps_t hwcaps; + + if (surface->hwdata!=NULL) + { + SDL_SetError("ph_AllocHWSurface(): hwdata already exists!\n"); + return -1; + } + surface->hwdata=SDL_malloc(sizeof(struct private_hwdata)); + SDL_memset(surface->hwdata, 0x00, sizeof(struct private_hwdata)); + surface->hwdata->offscreenctx=PdCreateOffscreenContext(0, surface->w, surface->h, Pg_OSC_MEM_PAGE_ALIGN); + if (surface->hwdata->offscreenctx == NULL) + { + SDL_SetError("ph_AllocHWSurface(): PdCreateOffscreenContext() function failed !\n"); + return -1; + } + surface->pixels=PdGetOffscreenContextPtr(surface->hwdata->offscreenctx); + if (surface->pixels==NULL) + { + PhDCRelease(surface->hwdata->offscreenctx); + SDL_SetError("ph_AllocHWSurface(): PdGetOffscreenContextPtr() function failed !\n"); + return -1; + } + surface->pitch=surface->hwdata->offscreenctx->pitch; + surface->flags|=SDL_HWSURFACE; + surface->flags|=SDL_PREALLOC; + +#if 0 /* FIXME */ + /* create simple offscreen lock */ + surface->hwdata->crlockparam.flags=0; + if (PdCreateOffscreenLock(surface->hwdata->offscreenctx, &surface->hwdata->crlockparam)!=EOK) + { + PhDCRelease(surface->hwdata->offscreenctx); + SDL_SetError("ph_AllocHWSurface(): Can't create offscreen lock !\n"); + return -1; + } +#endif /* 0 */ + + /* Update video ram amount */ + if (PgGetGraphicsHWCaps(&hwcaps) < 0) + { + PdDestroyOffscreenLock(surface->hwdata->offscreenctx); + PhDCRelease(surface->hwdata->offscreenctx); + SDL_SetError("ph_AllocHWSurface(): GetGraphicsHWCaps() function failed !\n"); + return -1; + } + this->info.video_mem=hwcaps.currently_available_video_ram/1024; + + return 0; +} + +void ph_FreeHWSurface(_THIS, SDL_Surface* surface) +{ + PgHWCaps_t hwcaps; + + if (surface->hwdata==NULL) + { + SDL_SetError("ph_FreeHWSurface(): no hwdata!\n"); + return; + } + if (surface->hwdata->offscreenctx == NULL) + { + SDL_SetError("ph_FreeHWSurface(): no offscreen context to delete!\n"); + return; + } + +#if 0 /* FIXME */ + /* unlock the offscreen context if it has been locked before destroy it */ + if (PdIsOffscreenLocked(surface->hwdata->offscreenctx)==Pg_OSC_LOCKED) + { + PdUnlockOffscreen(surface->hwdata->offscreenctx); + } + + PdDestroyOffscreenLock(surface->hwdata->offscreenctx); +#endif /* 0 */ + + PhDCRelease(surface->hwdata->offscreenctx); + + SDL_free(surface->hwdata); + surface->hwdata=NULL; + + /* Update video ram amount */ + if (PgGetGraphicsHWCaps(&hwcaps) < 0) + { + SDL_SetError("ph_FreeHWSurface(): GetGraphicsHWCaps() function failed !\n"); + return; + } + this->info.video_mem=hwcaps.currently_available_video_ram/1024; + + return; +} + +int ph_CheckHWBlit(_THIS, SDL_Surface *src, SDL_Surface *dst) +{ + if ((src->hwdata==NULL) && (src != this->screen)) + { + SDL_SetError("ph_CheckHWBlit(): Source surface haven't hardware specific data.\n"); + src->flags&=~SDL_HWACCEL; + return -1; + } + if ((src->flags & SDL_HWSURFACE) != SDL_HWSURFACE) + { + SDL_SetError("ph_CheckHWBlit(): Source surface isn't a hardware surface.\n"); + src->flags&=~SDL_HWACCEL; + return -1; + } + + if ((src->flags & SDL_SRCCOLORKEY) == SDL_SRCCOLORKEY) + { + if (this->info.blit_hw_CC!=1) + { + src->flags&=~SDL_HWACCEL; + src->map->hw_blit=NULL; + return -1; + } + } + + if ((src->flags & SDL_SRCALPHA) == SDL_SRCALPHA) + { + if (this->info.blit_hw_A!=1) + { + src->flags&=~SDL_HWACCEL; + src->map->hw_blit=NULL; + return -1; + } + } + + src->flags|=SDL_HWACCEL; + src->map->hw_blit = ph_HWAccelBlit; + + return 1; +} + +PgColor_t ph_ExpandColor(_THIS, SDL_Surface* surface, Uint32 color) +{ + Uint32 truecolor; + + /* Photon API accepts true colors only during hw filling operations */ + switch(surface->format->BitsPerPixel) + { + case 8: + { + if ((surface->format->palette) && (color<=surface->format->palette->ncolors)) + { + truecolor=PgRGB(surface->format->palette->colors[color].r, + surface->format->palette->colors[color].g, + surface->format->palette->colors[color].b); + } + else + { + SDL_SetError("ph_ExpandColor(): Color out of range for the 8bpp mode !\n"); + return 0xFFFFFFFFUL; + } + } + break; + case 15: + { + truecolor = ((color & 0x00007C00UL) << 9) | /* R */ + ((color & 0x000003E0UL) << 6) | /* G */ + ((color & 0x0000001FUL) << 3) | /* B */ + ((color & 0x00007000UL) << 4) | /* R compensation */ + ((color & 0x00000380UL) << 1) | /* G compensation */ + ((color & 0x0000001CUL) >> 2); /* B compensation */ + } + break; + case 16: + { + truecolor = ((color & 0x0000F800UL) << 8) | /* R */ + ((color & 0x000007E0UL) << 5) | /* G */ + ((color & 0x0000001FUL) << 3) | /* B */ + ((color & 0x0000E000UL) << 3) | /* R compensation */ + ((color & 0x00000600UL) >> 1) | /* G compensation */ + ((color & 0x0000001CUL) >> 2); /* B compensation */ + + } + break; + case 24: + { + truecolor=color & 0x00FFFFFFUL; + } + break; + case 32: + { + truecolor=color; + } + break; + default: + { + SDL_SetError("ph_ExpandColor(): Unsupported depth for the hardware operations !\n"); + return 0xFFFFFFFFUL; + } + } + + return truecolor; +} + +int ph_FillHWRect(_THIS, SDL_Surface* surface, SDL_Rect* rect, Uint32 color) +{ + PgColor_t oldcolor; + Uint32 truecolor; + int ydisp=0; + + if (this->info.blit_fill!=1) + { + return -1; + } + + truecolor=ph_ExpandColor(this, surface, color); + if (truecolor==0xFFFFFFFFUL) + { + return -1; + } + + oldcolor=PgSetFillColor(truecolor); + + /* 640x400 videomode emulation */ + if (videomode_emulatemode==1) + { + ydisp+=40; + } + + PgDrawIRect(rect->x, rect->y+ydisp, rect->w+rect->x-1, rect->h+rect->y+ydisp-1, Pg_DRAW_FILL); + PgSetFillColor(oldcolor); + PgFlush(); + PgWaitHWIdle(); + + return 0; +} + +int ph_FlipHWSurface(_THIS, SDL_Surface* screen) +{ + PhArea_t farea; + + if ((screen->flags & SDL_FULLSCREEN) == SDL_FULLSCREEN) + { + /* flush all drawing ops before blitting */ + PgFlush(); + PgWaitHWIdle(); + + farea.pos.x=0; + farea.pos.y=0; + farea.size.w=screen->w; + farea.size.h=screen->h; + + /* emulate 640x400 videomode */ + if (videomode_emulatemode==1) + { + farea.pos.y+=40; + } + + PgContextBlitArea(OCImage.offscreen_context, &farea, OCImage.offscreen_backcontext, &farea); + + /* flush the blitting */ + PgFlush(); + PgWaitHWIdle(); + } + return 0; +} + +int ph_LockHWSurface(_THIS, SDL_Surface* surface) +{ + +#if 0 /* FIXME */ + int lockresult; + + if (surface->hwdata == NULL) + { + return; + } + + surface->hwdata->lockparam.flags=0; + surface->hwdata->lockparam.time_out=NULL; + lockresult=PdLockOffscreen(surface->hwdata->offscreenctx, &surface->hwdata->lockparam); + + switch (lockresult) + { + case EOK: + break; + case Pg_OSC_LOCK_DEADLOCK: + SDL_SetError("ph_LockHWSurface(): Deadlock detected !\n"); + return -1; + case Pg_OSC_LOCK_INVALID: + SDL_SetError("ph_LockHWSurface(): Lock invalid !\n"); + return -1; + default: + SDL_SetError("ph_LockHWSurface(): Can't lock the surface !\n"); + return -1; + } +#endif /* 0 */ + + return 0; +} + +void ph_UnlockHWSurface(_THIS, SDL_Surface* surface) +{ + +#if 0 /* FIXME */ + int unlockresult; + + if ((surface == NULL) || (surface->hwdata == NULL)) + { + return; + } + + if (PdIsOffscreenLocked(surface->hwdata->offscreenctx)==Pg_OSC_LOCKED) + { + unlockresult=PdUnlockOffscreen(surface->hwdata->offscreenctx); + } +#endif /* 0 */ + + return; +} + +int ph_HWAccelBlit(SDL_Surface* src, SDL_Rect* srcrect, SDL_Surface* dst, SDL_Rect* dstrect) +{ + SDL_VideoDevice* this=current_video; + PhArea_t srcarea; + PhArea_t dstarea; + int ydisp=0; + + /* 640x400 videomode emulation */ + if (videomode_emulatemode==1) + { + ydisp+=40; + } + + srcarea.pos.x=srcrect->x; + srcarea.pos.y=srcrect->y; + srcarea.size.w=srcrect->w; + srcarea.size.h=srcrect->h; + + dstarea.pos.x=dstrect->x; + dstarea.pos.y=dstrect->y; + dstarea.size.w=dstrect->w; + dstarea.size.h=dstrect->h; + + if (((src == this->screen) || (src->hwdata!=NULL)) && ((dst == this->screen) || (dst->hwdata!=NULL))) + { + if ((src->flags & SDL_SRCCOLORKEY) == SDL_SRCCOLORKEY) + { + ph_SetHWColorKey(this, src, src->format->colorkey); + PgChromaOn(); + } + + if ((src->flags & SDL_SRCALPHA) == SDL_SRCALPHA) + { + ph_SetHWAlpha(this, src, src->format->alpha); + PgAlphaOn(); + } + + if (dst == this->screen) + { + if (src == this->screen) + { + /* blitting from main screen to main screen */ + dstarea.pos.y+=ydisp; + srcarea.pos.y+=ydisp; + PgContextBlitArea(OCImage.offscreen_context, &srcarea, OCImage.offscreen_context, &dstarea); + } + else + { + /* blitting from offscreen to main screen */ + dstarea.pos.y+=ydisp; + PgContextBlitArea(src->hwdata->offscreenctx, &srcarea, OCImage.offscreen_context, &dstarea); + } + } + else + { + if (src == this->screen) + { + /* blitting from main screen to offscreen */ + srcarea.pos.y+=ydisp; + PgContextBlitArea(OCImage.offscreen_context, &srcarea, dst->hwdata->offscreenctx, &dstarea); + } + else + { + /* blitting offscreen to offscreen */ + PgContextBlitArea(src->hwdata->offscreenctx, &srcarea, dst->hwdata->offscreenctx, &dstarea); + } + } + + if ((src->flags & SDL_SRCALPHA) == SDL_SRCALPHA) + { + PgAlphaOff(); + } + + if ((src->flags & SDL_SRCCOLORKEY) == SDL_SRCCOLORKEY) + { + PgChromaOff(); + } + } + else + { + SDL_SetError("ph_HWAccelBlit(): Source or target surface is not a hardware surface !\n"); + return -1; + } + + PgFlush(); + PgWaitHWIdle(); + + return 0; +} + +int ph_SetHWColorKey(_THIS, SDL_Surface *surface, Uint32 key) +{ + if (this->info.blit_hw_CC!=1) + { + return -1; + } + + if (surface->hwdata!=NULL) + { + surface->hwdata->colorkey=ph_ExpandColor(this, surface, key); + if (surface->hwdata->colorkey==0xFFFFFFFFUL) + { + return -1; + } + } + PgSetChroma(surface->hwdata->colorkey, Pg_CHROMA_SRC_MATCH | Pg_CHROMA_NODRAW); + + return 0; +} + +int ph_SetHWAlpha(_THIS, SDL_Surface* surface, Uint8 alpha) +{ + if (this->info.blit_hw_A!=1) + { + return -1; + } + + PgSetAlphaBlend(NULL, alpha); + + return 0; +} + +#if SDL_VIDEO_OPENGL +void ph_OpenGLUpdate(_THIS, int numrects, SDL_Rect* rects) +{ + this->GL_SwapBuffers(this); + + return; +} +#endif /* SDL_VIDEO_OPENGL */ + +void ph_NormalUpdate(_THIS, int numrects, SDL_Rect *rects) +{ + PhPoint_t ph_pos; + PhRect_t ph_rect; + int i; + + for (i=0; i<numrects; ++i) + { + if (rects[i].w==0) /* Clipped? dunno why but this occurs sometime. */ + { + continue; + } + + if (rects[i].h==0) /* Clipped? dunno why but this occurs sometime. */ + { + continue; + } + + ph_pos.x = rects[i].x; + ph_pos.y = rects[i].y; + ph_rect.ul.x = rects[i].x; + ph_rect.ul.y = rects[i].y; + ph_rect.lr.x = rects[i].x + rects[i].w; + ph_rect.lr.y = rects[i].y + rects[i].h; + + if (PgDrawPhImageRectmx(&ph_pos, SDL_Image, &ph_rect, 0) < 0) + { + SDL_SetError("ph_NormalUpdate(): PgDrawPhImageRectmx failed!\n"); + return; + } + } + + if (PgFlush() < 0) + { + SDL_SetError("ph_NormalUpdate(): PgFlush() function failed!\n"); + } +} + +void ph_OCUpdate(_THIS, int numrects, SDL_Rect *rects) +{ + int i; + + PhPoint_t zero = {0, 0}; + PhArea_t src_rect; + PhArea_t dest_rect; + + PgSetTranslation(&zero, 0); + PgSetRegion(PtWidgetRid(window)); + PgSetClipping(0, NULL); + + PgFlush(); + PgWaitHWIdle(); + + for (i=0; i<numrects; ++i) + { + if (rects[i].w == 0) /* Clipped? */ + { + continue; + } + + if (rects[i].h == 0) /* Clipped? */ + { + continue; + } + + src_rect.pos.x=rects[i].x; + src_rect.pos.y=rects[i].y; + dest_rect.pos.x=rects[i].x; + dest_rect.pos.y=rects[i].y; + + src_rect.size.w=rects[i].w; + src_rect.size.h=rects[i].h; + dest_rect.size.w=rects[i].w; + dest_rect.size.h=rects[i].h; + + PgContextBlitArea(OCImage.offscreen_context, &src_rect, NULL, &dest_rect); + } + + if (PgFlush() < 0) + { + SDL_SetError("ph_OCUpdate(): PgFlush failed.\n"); + } +} + +void ph_OCDCUpdate(_THIS, int numrects, SDL_Rect *rects) +{ + PgWaitHWIdle(); + + if (PgFlush() < 0) + { + SDL_SetError("ph_OCDCUpdate(): PgFlush failed.\n"); + } +} diff --git a/3rdparty/SDL/src/video/photon/SDL_ph_image_c.h b/3rdparty/SDL/src/video/photon/SDL_ph_image_c.h new file mode 100644 index 0000000..cfd9669 --- /dev/null +++ b/3rdparty/SDL/src/video/photon/SDL_ph_image_c.h @@ -0,0 +1,59 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#ifndef __SDL_PH_IMAGE_H__ +#define __SDL_PH_IMAGE_H__ + +#include "../../events/SDL_events_c.h" +#include "SDL_ph_video.h" + +struct private_hwdata +{ + PdOffscreenContext_t* offscreenctx; + PdOSCCreateLockParams_t crlockparam; + PdOSCLockParams_t lockparam; + Uint32 colorkey; +}; + +extern int ph_SetupImage(_THIS, SDL_Surface* screen); +extern void ph_DestroyImage(_THIS, SDL_Surface* screen); +extern int ph_SetupUpdateFunction(_THIS, SDL_Surface* screen, Uint32 flags); + +extern int ph_AllocHWSurface(_THIS, SDL_Surface* surface); +extern void ph_FreeHWSurface(_THIS, SDL_Surface* surface); +extern int ph_CheckHWBlit(_THIS, SDL_Surface *src, SDL_Surface *dst); +extern int ph_FillHWRect(_THIS, SDL_Surface* surface, SDL_Rect* rect, Uint32 color); +extern int ph_LockHWSurface(_THIS, SDL_Surface* surface); +extern void ph_UnlockHWSurface(_THIS, SDL_Surface* surface); +extern int ph_FlipHWSurface(_THIS, SDL_Surface* surface); +extern int ph_SetHWColorKey(_THIS, SDL_Surface* surface, Uint32 key); +extern int ph_SetHWAlpha(_THIS, SDL_Surface* surface, Uint8 alpha); +extern int ph_HWAccelBlit(SDL_Surface* src, SDL_Rect *srcrect, SDL_Surface* dst, SDL_Rect* dstrect); +extern int ph_UpdateHWInfo(_THIS); + +extern void ph_NormalUpdate(_THIS, int numrects, SDL_Rect* rects); +extern void ph_OCUpdate(_THIS, int numrects, SDL_Rect* rects); +extern void ph_OCDCUpdate(_THIS, int numrects, SDL_Rect* rects); +extern void ph_OpenGLUpdate(_THIS, int numrects, SDL_Rect* rects); + +#endif /* __SDL_PH_IMAGE_H__ */ diff --git a/3rdparty/SDL/src/video/photon/SDL_ph_modes.c b/3rdparty/SDL/src/video/photon/SDL_ph_modes.c new file mode 100644 index 0000000..8c2bf7e --- /dev/null +++ b/3rdparty/SDL/src/video/photon/SDL_ph_modes.c @@ -0,0 +1,390 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#include "SDL_ph_modes_c.h" + +static PgVideoModeInfo_t mode_info; +static PgVideoModes_t mode_list; + +/* The current list of available video modes */ +SDL_Rect SDL_modelist[PH_MAX_VIDEOMODES]; +SDL_Rect* SDL_modearray[PH_MAX_VIDEOMODES]; + +static int compare_modes_by_res(const void* mode1, const void* mode2) +{ + PgVideoModeInfo_t mode1_info; + PgVideoModeInfo_t mode2_info; + + if (PgGetVideoModeInfo(*(unsigned short*)mode1, &mode1_info) < 0) + { + return 0; + } + + if (PgGetVideoModeInfo(*(unsigned short*)mode2, &mode2_info) < 0) + { + return 0; + } + + if (mode1_info.width == mode2_info.width) + { + return mode2_info.height - mode1_info.height; + } + else + { + return mode2_info.width - mode1_info.width; + } +} + +SDL_Rect **ph_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags) +{ + int i = 0; + int j = 0; + SDL_Rect Amodelist[PH_MAX_VIDEOMODES]; + + for (i=0; i<PH_MAX_VIDEOMODES; i++) + { + SDL_modearray[i]=&SDL_modelist[i]; + } + + if (PgGetVideoModeList(&mode_list) < 0) + { + SDL_SetError("ph_ListModes(): PgGetVideoModeList() function failed !\n"); + return NULL; + } + + mode_info.bits_per_pixel = 0; + + for (i=0; i < mode_list.num_modes; i++) + { + if (PgGetVideoModeInfo(mode_list.modes[i], &mode_info) < 0) + { + SDL_SetError("ph_ListModes(): PgGetVideoModeInfo() function failed on mode: 0x%X.\n", mode_list.modes[i]); + return NULL; + } + if(mode_info.bits_per_pixel == format->BitsPerPixel) + { + Amodelist[j].w = mode_info.width; + Amodelist[j].h = mode_info.height; + Amodelist[j].x = 0; + Amodelist[j].y = 0; + j++; + } + } + + /* reorder biggest for smallest, assume width dominates */ + + for(i=0; i<j; i++) + { + SDL_modelist[i].w = Amodelist[j - i - 1].w; + SDL_modelist[i].h = Amodelist[j - i - 1].h; + SDL_modelist[i].x = Amodelist[j - i - 1].x; + SDL_modelist[i].y = Amodelist[j - i - 1].y; + } + SDL_modearray[j]=NULL; + + return SDL_modearray; +} + +void ph_FreeVideoModes(_THIS) +{ + return; +} + +/* return the mode associated with width, height and bpp */ +/* if there is no mode then zero is returned */ +int ph_GetVideoMode(int width, int height, int bpp) +{ + int i; + int modestage=0; + int closestmode=0; + + if (PgGetVideoModeList(&mode_list) < 0) + { + return -1; + } + + /* special case for the double-sized 320x200 mode */ + if ((width==640) && (height==400)) + { + modestage=1; + } + + /* search list for exact match */ + for (i=0; i<mode_list.num_modes; i++) + { + if (PgGetVideoModeInfo(mode_list.modes[i], &mode_info) < 0) + { + return 0; + } + + if ((mode_info.width == width) && (mode_info.height == height) && + (mode_info.bits_per_pixel == bpp)) + { + return mode_list.modes[i]; + } + else + { + if ((modestage) && (mode_info.width == width) && (mode_info.height == height+80) && + (mode_info.bits_per_pixel == bpp)) + { + modestage=2; + closestmode=mode_list.modes[i]; + } + } + } + + /* if we are here, then no 640x400xbpp mode found and we'll emulate it via 640x480xbpp mode */ + if (modestage==2) + { + return closestmode; + } + + return (i == mode_list.num_modes) ? 0 : mode_list.modes[i]; +} + +/* return the mode associated with width, height and bpp */ +/* if requested bpp is not found the mode with closest bpp is returned */ +int get_mode_any_format(int width, int height, int bpp) +{ + int i, closest, delta, min_delta; + + if (PgGetVideoModeList(&mode_list) < 0) + { + return -1; + } + + SDL_qsort(mode_list.modes, mode_list.num_modes, sizeof(unsigned short), compare_modes_by_res); + + for(i=0;i<mode_list.num_modes;i++) + { + if (PgGetVideoModeInfo(mode_list.modes[i], &mode_info) < 0) + { + return 0; + } + if ((mode_info.width == width) && (mode_info.height == height)) + { + break; + } + } + + if (i<mode_list.num_modes) + { + /* get closest bpp */ + closest = i++; + if (mode_info.bits_per_pixel == bpp) + { + return mode_list.modes[closest]; + } + + min_delta = abs(mode_info.bits_per_pixel - bpp); + + while(1) + { + if (PgGetVideoModeInfo(mode_list.modes[i], &mode_info) < 0) + { + return 0; + } + + if ((mode_info.width != width) || (mode_info.height != height)) + { + break; + } + else + { + if (mode_info.bits_per_pixel == bpp) + { + closest = i; + break; + } + else + { + delta = abs(mode_info.bits_per_pixel - bpp); + if (delta < min_delta) + { + closest = i; + min_delta = delta; + } + i++; + } + } + } + return mode_list.modes[closest]; + } + + return 0; +} + +int ph_ToggleFullScreen(_THIS, int on) +{ + return -1; +} + +int ph_EnterFullScreen(_THIS, SDL_Surface* screen, int fmode) +{ + PgDisplaySettings_t settings; + int mode; + char* refreshrate; + int refreshratenum; + + if (!currently_fullscreen) + { + /* Get the video mode and set it */ + if (screen->flags & SDL_ANYFORMAT) + { + if ((mode = get_mode_any_format(screen->w, screen->h, screen->format->BitsPerPixel)) == 0) + { + SDL_SetError("ph_EnterFullScreen(): can't find appropriate video mode !\n"); + return 0; + } + } + else + { + if ((mode = ph_GetVideoMode(screen->w, screen->h, screen->format->BitsPerPixel)) == 0) + { + SDL_SetError("ph_EnterFullScreen(): can't find appropriate video mode !\n"); + return 0; + } + if (PgGetVideoModeInfo(mode, &mode_info) < 0) + { + SDL_SetError("ph_EnterFullScreen(): can't get video mode capabilities !\n"); + return 0; + } + if (mode_info.height != screen->h) + { + if ((mode_info.height==480) && (screen->h==400)) + { + videomode_emulatemode=1; + } + } + else + { + videomode_emulatemode=0; + } + } + + /* save old video mode caps */ + PgGetVideoMode(&settings); + old_video_mode=settings.mode; + old_refresh_rate=settings.refresh; + + /* setup new video mode */ + settings.mode = mode; + settings.refresh = 0; + settings.flags = 0; + + refreshrate=SDL_getenv("SDL_PHOTON_FULLSCREEN_REFRESH"); + if (refreshrate!=NULL) + { + if (SDL_sscanf(refreshrate, "%d", &refreshratenum)==1) + { + settings.refresh = refreshratenum; + } + } + + if (PgSetVideoMode(&settings) < 0) + { + SDL_SetError("ph_EnterFullScreen(): PgSetVideoMode() call failed !\n"); + return 0; + } + + if (this->screen) + { + if ((this->screen->flags & SDL_OPENGL)==SDL_OPENGL) + { +#if !SDL_VIDEO_OPENGL || (_NTO_VERSION < 630) + return 0; /* 6.3.0 */ +#endif + } + } + + if (fmode==0) + { + if (OCImage.direct_context==NULL) + { + OCImage.direct_context=(PdDirectContext_t*)PdCreateDirectContext(); + if (!OCImage.direct_context) + { + SDL_SetError("ph_EnterFullScreen(): Can't create direct context !\n"); + ph_LeaveFullScreen(this); + return 0; + } + } + OCImage.oldDC=PdDirectStart(OCImage.direct_context); + } + + currently_fullscreen = 1; + } + PgFlush(); + + return 1; +} + +int ph_LeaveFullScreen(_THIS) +{ + PgDisplaySettings_t oldmode_settings; + + if (currently_fullscreen) + { + if ((this->screen) && ((this->screen->flags & SDL_OPENGL)==SDL_OPENGL)) + { +#if !SDL_VIDEO_OPENGL || (_NTO_VERSION < 630) + return 0; +#endif + } + + /* release routines starts here */ + { + if (OCImage.direct_context) + { + PdDirectStop(OCImage.direct_context); + PdReleaseDirectContext(OCImage.direct_context); + OCImage.direct_context=NULL; + } + if (OCImage.oldDC) + { + PhDCSetCurrent(OCImage.oldDC); + OCImage.oldDC=NULL; + } + + currently_fullscreen=0; + + /* Restore old video mode */ + if (old_video_mode != -1) + { + oldmode_settings.mode = (unsigned short) old_video_mode; + oldmode_settings.refresh = (unsigned short) old_refresh_rate; + oldmode_settings.flags = 0; + + if (PgSetVideoMode(&oldmode_settings) < 0) + { + SDL_SetError("Ph_LeaveFullScreen(): PgSetVideoMode() function failed !\n"); + return 0; + } + } + + old_video_mode=-1; + old_refresh_rate=-1; + } + } + return 1; +} diff --git a/3rdparty/SDL/src/video/photon/SDL_ph_modes_c.h b/3rdparty/SDL/src/video/photon/SDL_ph_modes_c.h new file mode 100644 index 0000000..117c5a3 --- /dev/null +++ b/3rdparty/SDL/src/video/photon/SDL_ph_modes_c.h @@ -0,0 +1,43 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#ifndef __SDL_PH_MODES_H__ +#define __SDL_PH_MODES_H__ + +#include "SDL_ph_video.h" + +#define PH_MAX_VIDEOMODES 127 + +#define PH_ENTER_DIRECTMODE 0 +#define PH_IGNORE_DIRECTMODE 1 + +extern SDL_Rect **ph_ListModes(_THIS,SDL_PixelFormat *format, Uint32 flags); +extern void ph_FreeVideoModes(_THIS); +extern int ph_ResizeFullScreen(_THIS); +extern int ph_EnterFullScreen(_THIS, SDL_Surface* screen, int fmode); +extern int ph_LeaveFullScreen(_THIS); +extern int ph_GetVideoMode(int width, int height, int bpp); +extern int get_mode_any_format(int width, int height, int bpp); +extern int ph_ToggleFullScreen(_THIS, int on); + +#endif /* __SDL_PH_MODES_H__ */ diff --git a/3rdparty/SDL/src/video/photon/SDL_ph_mouse.c b/3rdparty/SDL/src/video/photon/SDL_ph_mouse.c new file mode 100644 index 0000000..a25aa1f --- /dev/null +++ b/3rdparty/SDL/src/video/photon/SDL_ph_mouse.c @@ -0,0 +1,220 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#include "SDL_mouse.h" +#include "../../events/SDL_events_c.h" +#include "../SDL_cursor_c.h" +#include "SDL_ph_mouse_c.h" + +struct WMcursor +{ + PhCursorDef_t *ph_cursor ; +}; + +void ph_FreeWMCursor(_THIS, WMcursor *cursor) +{ + if (window != NULL) + { + SDL_Lock_EventThread(); + + if (PtSetResource(window, Pt_ARG_CURSOR_TYPE, Ph_CURSOR_INHERIT, 0) < 0) + { + /* TODO: output error msg */ + } + + SDL_Unlock_EventThread(); + } + + SDL_free(cursor); +} + +WMcursor *ph_CreateWMCursor(_THIS, Uint8 *data, Uint8 *mask, int w, int h, int hot_x, int hot_y) +{ + WMcursor* cursor; + int clen, i; + unsigned char bit, databit, maskbit; + + /* Allocate and initialize the cursor memory */ + if ((cursor = (WMcursor*)SDL_malloc(sizeof(WMcursor))) == NULL) + { + SDL_OutOfMemory(); + return(NULL); + } + SDL_memset(cursor,0,sizeof(WMcursor)); + + cursor->ph_cursor = (PhCursorDef_t *) SDL_malloc(sizeof(PhCursorDef_t) + 32*4*2); + + if (cursor->ph_cursor == NULL) + { + SDL_SetError("ph_CreateWMCursor(): cursor malloc failed !\n"); + return NULL; + } + + SDL_memset(cursor->ph_cursor,0,(sizeof(PhCursorDef_t) + 32*4*2)); + + cursor->ph_cursor->hdr.type =Ph_RDATA_CURSOR; + cursor->ph_cursor->size1.x = (short)w; + cursor->ph_cursor->size1.y = (short)h; + cursor->ph_cursor->offset1.x = (short)hot_x; + cursor->ph_cursor->offset1.y = (short)hot_y; + cursor->ph_cursor->bytesperline1 = (char)w/8; + cursor->ph_cursor->color1 = Pg_WHITE; + cursor->ph_cursor->size2.x = (short)w; + cursor->ph_cursor->size2.y = (short)h; + cursor->ph_cursor->offset2.x = (short)hot_x; + cursor->ph_cursor->offset2.y = (short)hot_y; + cursor->ph_cursor->bytesperline2 = (char)w/8; + cursor->ph_cursor->color2 = Pg_BLACK; + + clen = (w/8)*h; + + /* Copy the mask and the data to different bitmap planes */ + for (i=0; i<clen; ++i) + { + for (bit = 0; bit < 8; bit++) + { + databit = data[i] & (1 << bit); + maskbit = mask[i] & (1 << bit); + + cursor->ph_cursor->images[i] |= (databit == 0) ? maskbit : 0; + /* If the databit != 0, treat it as a black pixel and + * ignore the maskbit (can't do an inverted color) */ + cursor->ph_cursor->images[i+clen] |= databit; + } + } + + /* #bytes following the hdr struct */ + cursor->ph_cursor->hdr.len =sizeof(PhCursorDef_t) + clen*2 - sizeof(PhRegionDataHdr_t); + + return (cursor); +} + +PhCursorDef_t ph_GetWMPhCursor(WMcursor *cursor) +{ + return (*cursor->ph_cursor); +} + +int ph_ShowWMCursor(_THIS, WMcursor* cursor) +{ + PtArg_t args[3]; + int nargs = 0; + + /* Don't do anything if the display is gone */ + if (window == NULL) + { + return (0); + } + + /* looks like photon can't draw mouse cursor in direct mode */ + if ((this->screen->flags & SDL_FULLSCREEN) == SDL_FULLSCREEN) + { + /* disable the fake mouse in the fullscreen OpenGL mode */ + if ((this->screen->flags & SDL_OPENGL) == SDL_OPENGL) + { + cursor=NULL; + } + else + { + return (0); + } + } + + /* Set the photon cursor, or blank if cursor is NULL */ + if (cursor!=NULL) + { + PtSetArg(&args[0], Pt_ARG_CURSOR_TYPE, Ph_CURSOR_BITMAP, 0); + /* Could set next to any PgColor_t value */ + PtSetArg(&args[1], Pt_ARG_CURSOR_COLOR, Ph_CURSOR_DEFAULT_COLOR , 0); + PtSetArg(&args[2], Pt_ARG_BITMAP_CURSOR, cursor->ph_cursor, (cursor->ph_cursor->hdr.len + sizeof(PhRegionDataHdr_t))); + nargs = 3; + } + else /* Ph_CURSOR_NONE */ + { + PtSetArg(&args[0], Pt_ARG_CURSOR_TYPE, Ph_CURSOR_NONE, 0); + nargs = 1; + } + + SDL_Lock_EventThread(); + + if (PtSetResources(window, nargs, args) < 0 ) + { + return (0); + } + + SDL_Unlock_EventThread(); + + return (1); +} + + +void ph_WarpWMCursor(_THIS, Uint16 x, Uint16 y) +{ + short abs_x, abs_y; + + SDL_Lock_EventThread(); + PtGetAbsPosition( window, &abs_x, &abs_y ); + PhMoveCursorAbs( PhInputGroup(NULL), x + abs_x, y + abs_y ); + SDL_Unlock_EventThread(); +} + + +void ph_CheckMouseMode(_THIS) +{ + /* If the mouse is hidden and input is grabbed, we use relative mode */ + if ( !(SDL_cursorstate & CURSOR_VISIBLE) && (this->input_grab != SDL_GRAB_OFF)) + { + mouse_relative = 1; + } + else + { + mouse_relative = 0; + } +} + + +void ph_UpdateMouse(_THIS) +{ + PhCursorInfo_t phcursor; + short abs_x; + short abs_y; + + /* Lock the event thread, in multi-threading environments */ + SDL_Lock_EventThread(); + + /* synchronizing photon mouse cursor position and SDL mouse position, if cursor appears over window. */ + PtGetAbsPosition(window, &abs_x, &abs_y); + PhQueryCursor(PhInputGroup(NULL), &phcursor); + if (((phcursor.pos.x >= abs_x) && (phcursor.pos.x <= abs_x + this->screen->w)) && + ((phcursor.pos.y >= abs_y) && (phcursor.pos.y <= abs_y + this->screen->h))) + { + SDL_PrivateAppActive(1, SDL_APPMOUSEFOCUS); + SDL_PrivateMouseMotion(0, 0, phcursor.pos.x-abs_x, phcursor.pos.y-abs_y); + } + else + { + SDL_PrivateAppActive(0, SDL_APPMOUSEFOCUS); + } + + /* Unlock the event thread, in multi-threading environments */ + SDL_Unlock_EventThread(); +} diff --git a/3rdparty/SDL/src/video/photon/SDL_ph_mouse_c.h b/3rdparty/SDL/src/video/photon/SDL_ph_mouse_c.h new file mode 100644 index 0000000..55a92b6 --- /dev/null +++ b/3rdparty/SDL/src/video/photon/SDL_ph_mouse_c.h @@ -0,0 +1,39 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#ifndef __SDL_PH_MOUSE_H__ +#define __SDL_PH_MOUSE_H__ + +#include "SDL_ph_video.h" + +/* Functions to be exported */ +extern void ph_FreeWMCursor(_THIS, WMcursor *cursor); +extern WMcursor *ph_CreateWMCursor(_THIS, + Uint8 *data, Uint8 *mask, int w, int h, int hot_x, int hot_y); +extern PhCursorDef_t ph_GetWMPhCursor(WMcursor *cursor); +extern int ph_ShowWMCursor(_THIS, WMcursor *cursor); +extern void ph_WarpWMCursor(_THIS, Uint16 x, Uint16 y); +extern void ph_CheckMouseMode(_THIS); +extern void ph_UpdateMouse(_THIS); + +#endif /* __SDL_PH_MOUSE_H__ */ diff --git a/3rdparty/SDL/src/video/photon/SDL_ph_video.c b/3rdparty/SDL/src/video/photon/SDL_ph_video.c new file mode 100644 index 0000000..5e1a82b --- /dev/null +++ b/3rdparty/SDL/src/video/photon/SDL_ph_video.c @@ -0,0 +1,648 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#include <unistd.h> +#include <sys/ioctl.h> + +#include "SDL_endian.h" +#include "SDL_timer.h" +#include "SDL_thread.h" +#include "SDL_video.h" +#include "SDL_mouse.h" +#include "../SDL_sysvideo.h" +#include "../SDL_pixels_c.h" +#include "../../events/SDL_events_c.h" +#include "SDL_ph_video.h" +#include "SDL_ph_modes_c.h" +#include "SDL_ph_image_c.h" +#include "SDL_ph_events_c.h" +#include "SDL_ph_mouse_c.h" +#include "SDL_ph_wm_c.h" +#include "SDL_ph_gl.h" +#include "SDL_phyuv_c.h" +#include "../blank_cursor.h" + +static int ph_VideoInit(_THIS, SDL_PixelFormat *vformat); +static SDL_Surface *ph_SetVideoMode(_THIS, SDL_Surface *current, int width, int height, int bpp, Uint32 flags); +static int ph_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors); +static void ph_VideoQuit(_THIS); +static void ph_DeleteDevice(SDL_VideoDevice *device); + +static int phstatus=-1; + +static int ph_Available(void) +{ + if (phstatus!=0) + { + phstatus=PtInit(NULL); + if (phstatus==0) + { + return 1; + } + else + { + return 0; + } + } + return 1; +} + +static SDL_VideoDevice* ph_CreateDevice(int devindex) +{ + SDL_VideoDevice* device; + + /* Initialize all variables that we clean on shutdown */ + device = (SDL_VideoDevice *)SDL_malloc(sizeof(SDL_VideoDevice)); + if (device) + { + SDL_memset(device, 0, (sizeof *device)); + device->hidden = (struct SDL_PrivateVideoData*)SDL_malloc((sizeof *device->hidden)); + device->gl_data = NULL; + } + if ((device == NULL) || (device->hidden == NULL)) + { + SDL_OutOfMemory(); + ph_DeleteDevice(device); + return NULL; + } + SDL_memset(device->hidden, 0, (sizeof *device->hidden)); + + /* Set the driver flags */ + device->handles_any_size = 1; + + /* Set the function pointers */ + device->CreateYUVOverlay = ph_CreateYUVOverlay; + device->VideoInit = ph_VideoInit; + device->ListModes = ph_ListModes; + device->SetVideoMode = ph_SetVideoMode; + device->ToggleFullScreen = ph_ToggleFullScreen; + device->UpdateMouse = ph_UpdateMouse; + device->SetColors = ph_SetColors; + device->UpdateRects = NULL; /* set up in ph_SetupUpdateFunction */ + device->VideoQuit = ph_VideoQuit; + device->AllocHWSurface = ph_AllocHWSurface; + device->CheckHWBlit = ph_CheckHWBlit; + device->FillHWRect = ph_FillHWRect; + device->SetHWColorKey = ph_SetHWColorKey; + device->SetHWAlpha = ph_SetHWAlpha; + device->LockHWSurface = ph_LockHWSurface; + device->UnlockHWSurface = ph_UnlockHWSurface; + device->FlipHWSurface = ph_FlipHWSurface; + device->FreeHWSurface = ph_FreeHWSurface; + device->SetCaption = ph_SetCaption; + device->SetIcon = NULL; + device->IconifyWindow = ph_IconifyWindow; + device->GrabInput = ph_GrabInput; + device->GetWMInfo = ph_GetWMInfo; + device->FreeWMCursor = ph_FreeWMCursor; + device->CreateWMCursor = ph_CreateWMCursor; + device->ShowWMCursor = ph_ShowWMCursor; + device->WarpWMCursor = ph_WarpWMCursor; + device->MoveWMCursor = NULL; + device->CheckMouseMode = ph_CheckMouseMode; + device->InitOSKeymap = ph_InitOSKeymap; + device->PumpEvents = ph_PumpEvents; + + /* OpenGL support. */ +#if SDL_VIDEO_OPENGL + device->GL_MakeCurrent = ph_GL_MakeCurrent; + device->GL_SwapBuffers = ph_GL_SwapBuffers; + device->GL_GetAttribute = ph_GL_GetAttribute; + device->GL_LoadLibrary = ph_GL_LoadLibrary; + device->GL_GetProcAddress = ph_GL_GetProcAddress; +#endif /* SDL_VIDEO_OPENGL */ + + device->free = ph_DeleteDevice; + + return device; +} + +VideoBootStrap ph_bootstrap = { + "photon", "QNX Photon video output", + ph_Available, ph_CreateDevice +}; + +static void ph_DeleteDevice(SDL_VideoDevice *device) +{ + if (device) + { + if (device->hidden) + { + SDL_free(device->hidden); + device->hidden = NULL; + } + if (device->gl_data) + { + SDL_free(device->gl_data); + device->gl_data = NULL; + } + SDL_free(device); + device = NULL; + } +} + +static PtWidget_t *ph_CreateWindow(_THIS) +{ + PtWidget_t *widget; + + widget = PtCreateWidget(PtWindow, NULL, 0, NULL); + + return widget; +} + +static int ph_SetupWindow(_THIS, int w, int h, int flags) +{ + PtArg_t args[32]; + PhPoint_t pos = {0, 0}; + PhDim_t* olddim; + PhDim_t dim = {w, h}; + PhRect_t desktopextent; + int nargs = 0; + const char* windowpos; + const char* iscentered; + int x, y; + + /* check if window size has been changed by Window Manager */ + PtGetResource(window, Pt_ARG_DIM, &olddim, 0); + if ((olddim->w!=w) || (olddim->h!=h)) + { + PtSetArg(&args[nargs++], Pt_ARG_DIM, &dim, 0); + } + + if ((flags & SDL_RESIZABLE) == SDL_RESIZABLE) + { + PtSetArg(&args[nargs++], Pt_ARG_WINDOW_MANAGED_FLAGS, Pt_FALSE, Ph_WM_CLOSE); + PtSetArg(&args[nargs++], Pt_ARG_WINDOW_MANAGED_FLAGS, Pt_TRUE, Ph_WM_MAX | Ph_WM_RESTORE | Ph_WM_RESIZE); + PtSetArg(&args[nargs++], Pt_ARG_WINDOW_NOTIFY_FLAGS, Pt_TRUE, Ph_WM_RESIZE | Ph_WM_MOVE | Ph_WM_CLOSE | Ph_WM_MAX | Ph_WM_RESTORE); + PtSetArg(&args[nargs++], Pt_ARG_WINDOW_RENDER_FLAGS, Pt_TRUE, Ph_WM_RENDER_RESIZE | Ph_WM_RENDER_MAX | Ph_WM_RENDER_COLLAPSE | Ph_WM_RENDER_RETURN); + PtSetArg(&args[nargs++], Pt_ARG_RESIZE_FLAGS, Pt_TRUE, Pt_RESIZE_XY_AS_REQUIRED); + } + else + { + PtSetArg(&args[nargs++], Pt_ARG_WINDOW_MANAGED_FLAGS, Pt_FALSE, Ph_WM_RESIZE | Ph_WM_MAX | Ph_WM_RESTORE | Ph_WM_CLOSE); + PtSetArg(&args[nargs++], Pt_ARG_WINDOW_NOTIFY_FLAGS, Pt_FALSE, Ph_WM_RESIZE | Ph_WM_MAX | Ph_WM_RESTORE); + PtSetArg(&args[nargs++], Pt_ARG_WINDOW_NOTIFY_FLAGS, Pt_TRUE, Ph_WM_MOVE | Ph_WM_CLOSE); + PtSetArg(&args[nargs++], Pt_ARG_WINDOW_RENDER_FLAGS, Pt_FALSE, Ph_WM_RENDER_RESIZE | Ph_WM_RENDER_MAX | Ph_WM_RENDER_COLLAPSE | Ph_WM_RENDER_RETURN); + PtSetArg(&args[nargs++], Pt_ARG_RESIZE_FLAGS, Pt_FALSE, Pt_RESIZE_XY_AS_REQUIRED); + } + + if (((flags & SDL_NOFRAME)==SDL_NOFRAME) || ((flags & SDL_FULLSCREEN)==SDL_FULLSCREEN)) + { + if ((flags & SDL_RESIZABLE) != SDL_RESIZABLE) + { + PtSetArg(&args[nargs++], Pt_ARG_WINDOW_RENDER_FLAGS, Pt_FALSE, Pt_TRUE); + } + else + { + PtSetArg(&args[nargs++], Pt_ARG_WINDOW_RENDER_FLAGS, Pt_FALSE, Pt_TRUE); + PtSetArg(&args[nargs++], Pt_ARG_WINDOW_RENDER_FLAGS, Pt_TRUE, Ph_WM_RENDER_RESIZE | Ph_WM_RENDER_BORDER); + } + } + else + { + PtSetArg(&args[nargs++], Pt_ARG_WINDOW_RENDER_FLAGS, Pt_TRUE, Ph_WM_RENDER_BORDER | Ph_WM_RENDER_TITLE | + Ph_WM_RENDER_CLOSE | Ph_WM_RENDER_MENU | Ph_WM_RENDER_MIN); + } + + if ((flags & SDL_FULLSCREEN) == SDL_FULLSCREEN) + { + PtSetArg(&args[nargs++], Pt_ARG_POS, &pos, 0); + PtSetArg(&args[nargs++], Pt_ARG_BASIC_FLAGS, Pt_TRUE, Pt_BASIC_PREVENT_FILL); + PtSetArg(&args[nargs++], Pt_ARG_WINDOW_MANAGED_FLAGS, Pt_TRUE, Ph_WM_FFRONT | Ph_WM_MAX | Ph_WM_TOFRONT | Ph_WM_CONSWITCH); + PtSetArg(&args[nargs++], Pt_ARG_WINDOW_STATE, Pt_TRUE, Ph_WM_STATE_ISFRONT | Ph_WM_STATE_ISFOCUS | Ph_WM_STATE_ISALTKEY); + } + else + { + PtSetArg(&args[nargs++], Pt_ARG_WINDOW_MANAGED_FLAGS, Pt_FALSE, Ph_WM_FFRONT | Ph_WM_CONSWITCH); + PtSetArg(&args[nargs++], Pt_ARG_WINDOW_STATE, Pt_FALSE, Ph_WM_STATE_ISFRONT); + PtSetArg(&args[nargs++], Pt_ARG_WINDOW_STATE, Pt_TRUE, Ph_WM_STATE_ISALTKEY); + + if ((flags & SDL_HWSURFACE) == SDL_HWSURFACE) + { + PtSetArg(&args[nargs++], Pt_ARG_BASIC_FLAGS, Pt_TRUE, Pt_BASIC_PREVENT_FILL); + } + else + { + PtSetArg(&args[nargs++], Pt_ARG_FILL_COLOR, Pg_BLACK, 0); + } + if (!currently_maximized) + { + windowpos = SDL_getenv("SDL_VIDEO_WINDOW_POS"); + iscentered = SDL_getenv("SDL_VIDEO_CENTERED"); + + if ((iscentered) || ((windowpos) && (SDL_strcmp(windowpos, "center")==0))) + { + PhWindowQueryVisible(Ph_QUERY_CONSOLE, 0, 0, &desktopextent); + if (desktop_mode.width>w) + { + pos.x = (desktop_mode.width - w)/2; + } + if (desktop_mode.height>h) + { + pos.y = (desktop_mode.height - h)/2; + } + + pos.x+=desktopextent.ul.x; + pos.y+=desktopextent.ul.y; + PtSetArg(&args[nargs++], Pt_ARG_POS, &pos, 0); + } + else + { + if (windowpos) + { + if (SDL_sscanf(windowpos, "%d,%d", &x, &y) == 2) + { + if ((x<desktop_mode.width) && (y<desktop_mode.height)) + { + PhWindowQueryVisible(Ph_QUERY_CONSOLE, 0, 0, &desktopextent); + pos.x=x+desktopextent.ul.x; + pos.y=y+desktopextent.ul.y; + } + PtSetArg(&args[nargs++], Pt_ARG_POS, &pos, 0); + } + } + } + } + + /* if window is maximized render it as maximized */ + if (currently_maximized) + { + PtSetArg(&args[nargs++], Pt_ARG_WINDOW_STATE, Pt_TRUE, Ph_WM_STATE_ISMAX); + } + else + { + PtSetArg(&args[nargs++], Pt_ARG_WINDOW_STATE, Pt_FALSE, Ph_WM_STATE_ISMAX); + } + + /* do not grab the keyboard by default */ + PtSetArg(&args[nargs++], Pt_ARG_WINDOW_STATE, Pt_FALSE, Ph_WM_STATE_ISALTKEY); + + /* bring the focus to the window */ + PtSetArg(&args[nargs++], Pt_ARG_WINDOW_STATE, Pt_TRUE, Ph_WM_STATE_ISFOCUS); + + /* allow to catch hide event */ + PtSetArg(&args[nargs++], Pt_ARG_WINDOW_MANAGED_FLAGS, Pt_TRUE, Ph_WM_HIDE); + PtSetArg(&args[nargs++], Pt_ARG_WINDOW_NOTIFY_FLAGS, Pt_TRUE, Ph_WM_HIDE); + } + + PtSetResources(window, nargs, args); + PtRealizeWidget(window); + PtWindowToFront(window); + +#if 0 /* FIXME */ + PtGetResource(window, Pt_ARG_POS, &olddim, 0); + fprintf(stderr, "POSITION: %d, %d\n", olddim->w, olddim->h); +#endif + + return 0; +} + +static const struct ColourMasks* ph_GetColourMasks(int bpp) +{ + /* The alpha mask doesn't appears to be needed */ + static const struct ColourMasks phColorMasks[5] = { + /* 8 bit */ {0, 0, 0, 0, 8}, + /* 15 bit ARGB */ {0x7C00, 0x03E0, 0x001F, 0x8000, 15}, + /* 16 bit RGB */ {0xF800, 0x07E0, 0x001F, 0x0000, 16}, + /* 24 bit RGB */ {0xFF0000, 0x00FF00, 0x0000FF, 0x000000, 24}, + /* 32 bit ARGB */ {0x00FF0000, 0x0000FF00, 0x000000FF, 0xFF000000, 32}, + }; + + switch (bpp) + { + case 8: + return &phColorMasks[0]; + case 15: + return &phColorMasks[1]; + case 16: + return &phColorMasks[2]; + case 24: + return &phColorMasks[3]; + case 32: + return &phColorMasks[4]; + } + return NULL; +} + +static int ph_VideoInit(_THIS, SDL_PixelFormat* vformat) +{ + PgHWCaps_t hwcaps; + int i; + + window=NULL; + desktoppal=SDLPH_PAL_NONE; + +#if SDL_VIDEO_OPENGL + oglctx=NULL; + oglbuffers=NULL; + oglflags=0; + oglbpp=0; +#endif + + old_video_mode=-1; + old_refresh_rate=-1; + + if (NULL == (phevent = SDL_malloc(EVENT_SIZE))) + { + SDL_OutOfMemory(); + return -1; + } + SDL_memset(phevent, 0x00, EVENT_SIZE); + + window = ph_CreateWindow(this); + if (window == NULL) + { + SDL_SetError("ph_VideoInit(): Couldn't create video window !\n"); + return -1; + } + + /* Create the blank cursor */ + SDL_BlankCursor = this->CreateWMCursor(this, blank_cdata, blank_cmask, + (int)BLANK_CWIDTH, (int)BLANK_CHEIGHT, + (int)BLANK_CHOTX, (int)BLANK_CHOTY); + + if (SDL_BlankCursor == NULL) + { + return -1; + } + + if (PgGetGraphicsHWCaps(&hwcaps) < 0) + { + SDL_SetError("ph_VideoInit(): GetGraphicsHWCaps function failed !\n"); + this->FreeWMCursor(this, SDL_BlankCursor); + return -1; + } + + if (PgGetVideoModeInfo(hwcaps.current_video_mode, &desktop_mode) < 0) + { + SDL_SetError("ph_VideoInit(): PgGetVideoModeInfo function failed !\n"); + this->FreeWMCursor(this, SDL_BlankCursor); + return -1; + } + + /* Determine the current screen size */ + this->info.current_w = desktop_mode.width; + this->info.current_h = desktop_mode.height; + + /* We need to return BytesPerPixel as it in used by CreateRGBsurface */ + vformat->BitsPerPixel = desktop_mode.bits_per_pixel; + vformat->BytesPerPixel = desktop_mode.bytes_per_scanline/desktop_mode.width; + desktopbpp = desktop_mode.bits_per_pixel; + + /* save current palette */ + if (desktopbpp==8) + { + PgGetPalette(savedpal); + PgGetPalette(syspalph); + } + else + { + for(i=0; i<_Pg_MAX_PALETTE; i++) + { + savedpal[i]=PgRGB(0, 0, 0); + syspalph[i]=PgRGB(0, 0, 0); + } + } + + currently_fullscreen = 0; + currently_hided = 0; + currently_maximized = 0; + current_overlay = NULL; + + OCImage.direct_context = NULL; + OCImage.offscreen_context = NULL; + OCImage.offscreen_backcontext = NULL; + OCImage.oldDC = NULL; + OCImage.CurrentFrameData = NULL; + OCImage.FrameData0 = NULL; + OCImage.FrameData1 = NULL; + videomode_emulatemode = 0; + + this->info.wm_available = 1; + + ph_UpdateHWInfo(this); + + return 0; +} + +static SDL_Surface* ph_SetVideoMode(_THIS, SDL_Surface *current, int width, int height, int bpp, Uint32 flags) +{ + const struct ColourMasks* mask; + + /* Lock the event thread, in multi-threading environments */ + SDL_Lock_EventThread(); + + current->flags = flags; + + /* if we do not have desired fullscreen mode, then fallback into window mode */ + if (((current->flags & SDL_FULLSCREEN) == SDL_FULLSCREEN) && (ph_GetVideoMode(width, height, bpp)==0)) + { + current->flags &= ~SDL_FULLSCREEN; + current->flags &= ~SDL_NOFRAME; + current->flags &= ~SDL_RESIZABLE; + } + + ph_SetupWindow(this, width, height, current->flags); + + mask = ph_GetColourMasks(bpp); + if (mask != NULL) + { + SDL_ReallocFormat(current, mask->bpp, mask->red, mask->green, mask->blue, 0); + } + else + { + SDL_SetError("ph_SetVideoMode(): desired bpp is not supported by photon !\n"); + return NULL; + } + + if ((current->flags & SDL_OPENGL)==SDL_OPENGL) + { +#if !SDL_VIDEO_OPENGL + /* if no built-in OpenGL support */ + SDL_SetError("ph_SetVideoMode(): no OpenGL support, you need to recompile SDL.\n"); + current->flags &= ~SDL_OPENGL; + return NULL; +#endif /* SDL_VIDEO_OPENGL */ + } + else + { + /* Initialize internal variables */ + if ((current->flags & SDL_FULLSCREEN) == SDL_FULLSCREEN) + { + if (bpp==8) + { + desktoppal=SDLPH_PAL_SYSTEM; + } + + current->flags &= ~SDL_RESIZABLE; /* no resize for Direct Context */ + current->flags |= SDL_HWSURFACE; + } + else + { + /* remove this if we'll have support for the non-fullscreen sw/hw+doublebuf one day */ + current->flags &= ~SDL_DOUBLEBUF; + + /* Use offscreen memory if SDL_HWSURFACE flag is set */ + if ((current->flags & SDL_HWSURFACE) == SDL_HWSURFACE) + { + if (desktopbpp!=bpp) + { + current->flags &= ~SDL_HWSURFACE; + } + } + + /* using palette emulation code in window mode */ + if (bpp==8) + { + if (desktopbpp>=15) + { + desktoppal = SDLPH_PAL_EMULATE; + } + else + { + desktoppal = SDLPH_PAL_SYSTEM; + } + } + else + { + desktoppal = SDLPH_PAL_NONE; + } + } + } + + current->w = width; + current->h = height; + + if (desktoppal==SDLPH_PAL_SYSTEM) + { + current->flags|=SDL_HWPALETTE; + } + + /* Must call at least once for setup image planes */ + if (ph_SetupUpdateFunction(this, current, current->flags)==-1) + { + /* Error string was filled in the ph_SetupUpdateFunction() */ + return NULL; + } + + /* finish window drawing, if we are not in fullscreen, of course */ + if ((current->flags & SDL_FULLSCREEN) != SDL_FULLSCREEN) + { + PtFlush(); + } + else + { + PgFlush(); + } + + visualbpp=bpp; + + ph_UpdateHWInfo(this); + + SDL_Unlock_EventThread(); + + /* We've done! */ + return (current); +} + +static void ph_VideoQuit(_THIS) +{ + /* restore palette */ + if (desktopbpp==8) + { + PgSetPalette(syspalph, 0, -1, 0, 0, 0); + PgSetPalette(savedpal, 0, 0, _Pg_MAX_PALETTE, Pg_PALSET_GLOBAL | Pg_PALSET_FORCE_EXPOSE, 0); + PgFlush(); + } + + ph_DestroyImage(this, SDL_VideoSurface); + + if (window) + { + PtUnrealizeWidget(window); + PtDestroyWidget(window); + window=NULL; + } + + if (phevent!=NULL) + { + SDL_free(phevent); + phevent=NULL; + } +} + +static int ph_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors) +{ + int i; + SDL_Rect updaterect; + + updaterect.x = updaterect.y = 0; + updaterect.w = this->screen->w; + updaterect.h = this->screen->h; + + /* palette emulation code, using palette of the PhImage_t struct */ + if (desktoppal==SDLPH_PAL_EMULATE) + { + if ((SDL_Image) && (SDL_Image->palette)) + { + for (i=firstcolor; i<firstcolor+ncolors; i++) + { + syspalph[i] = PgRGB(colors[i-firstcolor].r, colors[i-firstcolor].g, colors[i-firstcolor].b); + SDL_Image->palette[i] = syspalph[i]; + } + + /* image needs to be redrawn */ + this->UpdateRects(this, 1, &updaterect); + } + } + else + { + if (desktoppal==SDLPH_PAL_SYSTEM) + { + for (i=firstcolor; i<firstcolor+ncolors; i++) + { + syspalph[i] = PgRGB(colors[i-firstcolor].r, colors[i-firstcolor].g, colors[i-firstcolor].b); + } + + if ((this->screen->flags & SDL_FULLSCREEN) != SDL_FULLSCREEN) + { + /* window mode must use soft palette */ + PgSetPalette(&syspalph[firstcolor], 0, firstcolor, ncolors, Pg_PALSET_GLOBAL, 0); + /* image needs to be redrawn */ + this->UpdateRects(this, 1, &updaterect); + } + else + { + /* fullscreen mode must use hardware palette */ + PgSetPalette(&syspalph[firstcolor], 0, firstcolor, ncolors, Pg_PALSET_GLOBAL, 0); + } + } + else + { + /* SDLPH_PAL_NONE do nothing */ + } + } + + return 1; +} + diff --git a/3rdparty/SDL/src/video/photon/SDL_ph_video.h b/3rdparty/SDL/src/video/photon/SDL_ph_video.h new file mode 100644 index 0000000..3995d35 --- /dev/null +++ b/3rdparty/SDL/src/video/photon/SDL_ph_video.h @@ -0,0 +1,157 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#ifndef __SDL_PH_VIDEO_H__ +#define __SDL_PH_VIDEO_H__ + +#include "SDL_mouse.h" +#include "../SDL_sysvideo.h" + +#include <sys/neutrino.h> + +#include <Ph.h> +#include <Pt.h> +#include <photon/Pg.h> +#include <photon/PdDirect.h> + +#if SDL_VIDEO_OPENGL + #if (_NTO_VERSION < 630) + #include <photon/PdGL.h> + #else + #include <GL/qnxgl.h> + #include <GL/GLPh.h> + #endif /* 6.3.0 */ +#endif /* SDL_VIDEO_OPENGL */ + +/* Hidden "this" pointer for the video functions */ +#define _THIS SDL_VideoDevice* this + +#define PH_OGL_MAX_ATTRIBS 32 + +#define SDLPH_PAL_NONE 0x00000000L +#define SDLPH_PAL_EMULATE 0x00000001L +#define SDLPH_PAL_SYSTEM 0x00000002L + +typedef struct +{ + unsigned char* Y; + unsigned char* V; + unsigned char* U; +} FRAMEDATA; + +/* Mask values for SDL_ReallocFormat() */ +struct ColourMasks +{ + Uint32 red; + Uint32 green; + Uint32 blue; + Uint32 alpha; + Uint32 bpp; +}; + +/* Private display data */ +struct SDL_PrivateVideoData +{ + PgDisplaySettings_t mode_settings; + PtWidget_t *Window; /* used to handle input events */ + PhImage_t *image; /* used to display image */ +#if SDL_VIDEO_OPENGL + #if (_NTO_VERSION < 630) + PdOpenGLContext_t* OGLContext; /* OpenGL context */ + void* OGLBuffers; /* OpenGL buffers (unused) */ + #else + qnxglc_t* OGLContext; /* OpenGL context for the 6.3 */ + qnxgl_bufs_t* OGLBuffers; /* OpenGL buffers for the 6.3 */ + #endif /* 630 */ + + Uint32 OGLFlags; /* OpenGL flags */ + Uint32 OGLBPP; /* OpenGL bpp */ +#endif /* SDL_VIDEO_OPENGL */ + PgColor_t savedpal[_Pg_MAX_PALETTE]; + PgColor_t syspalph[_Pg_MAX_PALETTE]; + + struct + { + PdDirectContext_t* direct_context; + PdOffscreenContext_t* offscreen_context; + PdOffscreenContext_t* offscreen_backcontext; + PhDrawContext_t* oldDC; + uint8_t* dc_ptr; + unsigned char* CurrentFrameData; + unsigned char* FrameData0; + unsigned char* FrameData1; + Uint32 current; + Uint32 flags; + } ocimage; + + PgHWCaps_t graphics_card_caps; /* Graphics card caps at the moment of start */ + PgVideoModeInfo_t desktop_mode; /* Current desktop video mode information */ + int old_video_mode; /* Stored mode before fullscreen switch */ + int old_refresh_rate; /* Stored refresh rate befor fullscreen switch */ + + int mouse_relative; + WMcursor* BlankCursor; + uint32_t videomode_emulatemode; + + Uint32 visualbpp; /* current visual bpp */ + Uint32 desktopbpp; /* bpp of desktop at the moment of start */ + Uint32 desktoppal; /* palette mode emulation or system */ + + int currently_fullscreen; + int currently_hided; /* 1 - window hided (minimazed), 0 - normal */ + int currently_maximized; /* 1 - window hided (minimazed), 0 - normal */ + + PhEvent_t* event; + SDL_Overlay* overlay; +}; + +#define mode_settings (this->hidden->mode_settings) +#define window (this->hidden->Window) +#define SDL_Image (this->hidden->image) +#define OCImage (this->hidden->ocimage) +#define old_video_mode (this->hidden->old_video_mode) +#define old_refresh_rate (this->hidden->old_refresh_rate) +#define graphics_card_caps (this->hidden->graphics_card_caps) +#define desktopbpp (this->hidden->desktopbpp) +#define visualbpp (this->hidden->visualbpp) +#define desktoppal (this->hidden->desktoppal) +#define savedpal (this->hidden->savedpal) +#define syspalph (this->hidden->syspalph) +#define currently_fullscreen (this->hidden->currently_fullscreen) +#define currently_hided (this->hidden->currently_hided) +#define currently_maximized (this->hidden->currently_maximized) +#define phevent (this->hidden->event) +#define current_overlay (this->hidden->overlay) +#define desktop_mode (this->hidden->desktop_mode) +#define mouse_relative (this->hidden->mouse_relative) +#define SDL_BlankCursor (this->hidden->BlankCursor) +#define videomode_emulatemode (this->hidden->videomode_emulatemode) + +#if SDL_VIDEO_OPENGL + #define oglctx (this->hidden->OGLContext) + #define oglbuffers (this->hidden->OGLBuffers) + #define oglflags (this->hidden->OGLFlags) + #define oglbpp (this->hidden->OGLBPP) +#endif /* SDL_VIDEO_OPENGL */ + +#endif /* __SDL_PH_VIDEO_H__ */ diff --git a/3rdparty/SDL/src/video/photon/SDL_ph_wm.c b/3rdparty/SDL/src/video/photon/SDL_ph_wm.c new file mode 100644 index 0000000..8e75d0b --- /dev/null +++ b/3rdparty/SDL/src/video/photon/SDL_ph_wm.c @@ -0,0 +1,118 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#include <Ph.h> +#include <photon/PpProto.h> +#include <photon/PhWm.h> +#include <photon/wmapi.h> + +#include "SDL_version.h" +#include "SDL_timer.h" +#include "SDL_video.h" +#include "SDL_syswm.h" +#include "../SDL_pixels_c.h" +#include "../../events/SDL_events_c.h" +#include "SDL_ph_modes_c.h" +#include "SDL_ph_wm_c.h" + +void ph_SetIcon(_THIS, SDL_Surface *icon, Uint8 *mask) +{ + return; +} + +/* Set window caption */ +void ph_SetCaption(_THIS, const char *title, const char *icon) +{ + SDL_Lock_EventThread(); + + /* sanity check for set caption call before window init */ + if (window!=NULL) + { + PtSetResource(window, Pt_ARG_WINDOW_TITLE, title, 0); + } + + SDL_Unlock_EventThread(); +} + +/* Iconify current window */ +int ph_IconifyWindow(_THIS) +{ + PhWindowEvent_t windowevent; + + SDL_Lock_EventThread(); + + SDL_memset(&windowevent, 0, sizeof(windowevent)); + windowevent.event_f = Ph_WM_HIDE; + windowevent.event_state = Ph_WM_EVSTATE_HIDE; + windowevent.rid = PtWidgetRid(window); + PtForwardWindowEvent(&windowevent); + + SDL_Unlock_EventThread(); + + return 0; +} + +SDL_GrabMode ph_GrabInputNoLock(_THIS, SDL_GrabMode mode) +{ + short abs_x, abs_y; + + if( mode == SDL_GRAB_OFF ) + { + PtSetResource(window, Pt_ARG_WINDOW_STATE, Pt_FALSE, Ph_WM_STATE_ISALTKEY); + } + else + { + PtSetResource(window, Pt_ARG_WINDOW_STATE, Pt_TRUE, Ph_WM_STATE_ISALTKEY); + + PtGetAbsPosition(window, &abs_x, &abs_y); + PhMoveCursorAbs(PhInputGroup(NULL), abs_x + SDL_VideoSurface->w/2, abs_y + SDL_VideoSurface->h/2); + } + + SDL_Unlock_EventThread(); + + return(mode); +} + +SDL_GrabMode ph_GrabInput(_THIS, SDL_GrabMode mode) +{ + SDL_Lock_EventThread(); + mode = ph_GrabInputNoLock(this, mode); + SDL_Unlock_EventThread(); + + return(mode); +} + + +int ph_GetWMInfo(_THIS, SDL_SysWMinfo *info) +{ + if (info->version.major <= SDL_MAJOR_VERSION) + { + return 1; + } + else + { + SDL_SetError("Application not compiled with SDL %d.%d\n", + SDL_MAJOR_VERSION, SDL_MINOR_VERSION); + return -1; + } +} diff --git a/3rdparty/SDL/src/video/photon/SDL_ph_wm_c.h b/3rdparty/SDL/src/video/photon/SDL_ph_wm_c.h new file mode 100644 index 0000000..72bbfd2 --- /dev/null +++ b/3rdparty/SDL/src/video/photon/SDL_ph_wm_c.h @@ -0,0 +1,37 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#ifndef __SDL_PH_WM_H__ +#define __SDL_PH_WM_H__ + +#include "SDL_ph_video.h" + +/* Functions to be exported */ +extern void ph_SetCaption(_THIS, const char *title, const char *icon); +extern void ph_SetIcon(_THIS, SDL_Surface *icon, Uint8 *mask); +extern int ph_IconifyWindow(_THIS); +extern SDL_GrabMode ph_GrabInputNoLock(_THIS, SDL_GrabMode mode); +extern SDL_GrabMode ph_GrabInput(_THIS, SDL_GrabMode mode); +extern int ph_GetWMInfo(_THIS, SDL_SysWMinfo *info); + +#endif /* __SDL_PH_WM_H__ */ diff --git a/3rdparty/SDL/src/video/photon/SDL_phyuv.c b/3rdparty/SDL/src/video/photon/SDL_phyuv.c new file mode 100644 index 0000000..06c72fd --- /dev/null +++ b/3rdparty/SDL/src/video/photon/SDL_phyuv.c @@ -0,0 +1,504 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* This is the QNX Realtime Platform version of SDL YUV video overlays */ + +#include <errno.h> + +#include <Ph.h> +#include <Pt.h> + +#include "SDL_video.h" +#include "SDL_phyuv_c.h" +#include "../SDL_yuvfuncs.h" + +#define OVERLAY_STATE_UNINIT 0 +#define OVERLAY_STATE_ACTIVE 1 + +/* The functions are used to manipulate software video overlays */ +static struct private_yuvhwfuncs ph_yuvfuncs = +{ + ph_LockYUVOverlay, + ph_UnlockYUVOverlay, + ph_DisplayYUVOverlay, + ph_FreeYUVOverlay +}; + +int grab_ptrs2(PgVideoChannel_t* channel, FRAMEDATA* Frame0, FRAMEDATA* Frame1) +{ + int planes = 0; + + /* Buffers have moved; re-obtain the pointers */ + Frame0->Y = (unsigned char *)PdGetOffscreenContextPtr(channel->yplane1); + Frame1->Y = (unsigned char *)PdGetOffscreenContextPtr(channel->yplane2); + Frame0->U = (unsigned char *)PdGetOffscreenContextPtr(channel->vplane1); + Frame1->U = (unsigned char *)PdGetOffscreenContextPtr(channel->vplane2); + Frame0->V = (unsigned char *)PdGetOffscreenContextPtr(channel->uplane1); + Frame1->V = (unsigned char *)PdGetOffscreenContextPtr(channel->uplane2); + + if (Frame0->Y) + planes++; + + if (Frame0->U) + planes++; + + if (Frame0->V) + planes++; + + return planes; +} + +SDL_Overlay* ph_CreateYUVOverlay(_THIS, int width, int height, Uint32 format, SDL_Surface* display) +{ + SDL_Overlay* overlay; + struct private_yuvhwdata* hwdata; + int vidport; + int rtncode; + int planes; + int i=0; + PhPoint_t pos; + + /* Create the overlay structure */ + overlay = SDL_calloc(1, sizeof(SDL_Overlay)); + + if (overlay == NULL) + { + SDL_OutOfMemory(); + return NULL; + } + + /* Fill in the basic members */ + overlay->format = format; + overlay->w = width; + overlay->h = height; + overlay->hwdata = NULL; + + /* Set up the YUV surface function structure */ + overlay->hwfuncs = &ph_yuvfuncs; + + /* Create the pixel data and lookup tables */ + hwdata = SDL_calloc(1, sizeof(struct private_yuvhwdata)); + + if (hwdata == NULL) + { + SDL_OutOfMemory(); + SDL_FreeYUVOverlay(overlay); + return NULL; + } + + overlay->hwdata = hwdata; + + PhDCSetCurrent(0); + if (overlay->hwdata->channel == NULL) + { + if ((overlay->hwdata->channel = PgCreateVideoChannel(Pg_VIDEO_CHANNEL_SCALER, 0)) == NULL) + { + SDL_SetError("ph_CreateYUVOverlay(): Create channel failed: %s\n", strerror(errno)); + SDL_FreeYUVOverlay(overlay); + return NULL; + + } + } + + overlay->hwdata->forcedredraw=0; + + PtGetAbsPosition(window, &pos.x, &pos.y); + overlay->hwdata->CurrentWindowPos.x = pos.x; + overlay->hwdata->CurrentWindowPos.y = pos.y; + overlay->hwdata->CurrentViewPort.pos.x = 0; + overlay->hwdata->CurrentViewPort.pos.y = 0; + overlay->hwdata->CurrentViewPort.size.w = width; + overlay->hwdata->CurrentViewPort.size.h = height; + overlay->hwdata->State = OVERLAY_STATE_UNINIT; + overlay->hwdata->FrameData0 = (FRAMEDATA *) SDL_calloc(1, sizeof(FRAMEDATA)); + overlay->hwdata->FrameData1 = (FRAMEDATA *) SDL_calloc(1, sizeof(FRAMEDATA)); + + vidport = -1; + i=0; + + overlay->hwdata->ischromakey=0; + + do { + SDL_memset(&overlay->hwdata->caps, 0x00, sizeof(PgScalerCaps_t)); + overlay->hwdata->caps.size = sizeof(PgScalerCaps_t); + rtncode = PgGetScalerCapabilities(overlay->hwdata->channel, i, &overlay->hwdata->caps); + if (rtncode==0) + { + if (overlay->hwdata->caps.format==format) + { + if ((overlay->hwdata->caps.flags & Pg_SCALER_CAP_DST_CHROMA_KEY) == Pg_SCALER_CAP_DST_CHROMA_KEY) + { + overlay->hwdata->ischromakey=1; + } + vidport=1; + break; + } + } + else + { + break; + } + i++; + } while(1); + + + if (vidport == -1) + { + SDL_SetError("No available video ports for requested format\n"); + SDL_FreeYUVOverlay(overlay); + return NULL; + } + + overlay->hwdata->format = format; + overlay->hwdata->props.format = format; + overlay->hwdata->props.size = sizeof(PgScalerProps_t); + overlay->hwdata->props.src_dim.w = width; + overlay->hwdata->props.src_dim.h = height; + + /* overlay->hwdata->chromakey = PgGetOverlayChromaColor(); */ + overlay->hwdata->chromakey = PgRGB(12, 6, 12); /* very dark pink color */ + overlay->hwdata->props.color_key = overlay->hwdata->chromakey; + + PhAreaToRect(&overlay->hwdata->CurrentViewPort, &overlay->hwdata->props.viewport); + + overlay->hwdata->props.flags = Pg_SCALER_PROP_DOUBLE_BUFFER; + + if ((overlay->hwdata->ischromakey)&&(overlay->hwdata->chromakey)) + { + overlay->hwdata->props.flags |= Pg_SCALER_PROP_CHROMA_ENABLE; + overlay->hwdata->props.flags |= Pg_SCALER_PROP_CHROMA_SPECIFY_KEY_MASK; + } + else + { + overlay->hwdata->props.flags &= ~Pg_SCALER_PROP_CHROMA_ENABLE; + } + + rtncode = PgConfigScalerChannel(overlay->hwdata->channel, &overlay->hwdata->props); + + switch(rtncode) + { + case -1: SDL_SetError("PgConfigScalerChannel failed\n"); + SDL_FreeYUVOverlay(overlay); + return NULL; + case 1: + case 0: + default: + break; + } + + planes = grab_ptrs2(overlay->hwdata->channel, overlay->hwdata->FrameData0, overlay->hwdata->FrameData1); + + if(overlay->hwdata->channel->yplane1 != NULL) + overlay->hwdata->YStride = overlay->hwdata->channel->yplane1->pitch; + if(overlay->hwdata->channel->vplane1 != NULL) + overlay->hwdata->UStride = overlay->hwdata->channel->vplane1->pitch; + if(overlay->hwdata->channel->uplane1 != NULL) + overlay->hwdata->VStride = overlay->hwdata->channel->uplane1->pitch; + + /* check for the validness of all planes */ + if ((overlay->hwdata->channel->yplane1 == NULL) && + (overlay->hwdata->channel->uplane1 == NULL) && + (overlay->hwdata->channel->vplane1 == NULL)) + { + SDL_FreeYUVOverlay(overlay); + SDL_SetError("PgConfigScaler() returns all planes equal NULL\n"); + return NULL; + } +/* + overlay->hwdata->current = PgNextVideoFrame(overlay->hwdata->channel); + + if (overlay->hwdata->current==0) + { + overlay->hwdata->CurrentFrameData = overlay->hwdata->FrameData0; + } + else + { + overlay->hwdata->CurrentFrameData = overlay->hwdata->FrameData1; + } +*/ + overlay->hwdata->CurrentFrameData = overlay->hwdata->FrameData0; + +/* + overlay->hwdata->locked = 1; +*/ + + /* Find the pitch and offset values for the overlay */ + overlay->planes = planes; + overlay->pitches = SDL_calloc(overlay->planes, sizeof(Uint16)); + overlay->pixels = SDL_calloc(overlay->planes, sizeof(Uint8*)); + if (!overlay->pitches || !overlay->pixels) + { + SDL_OutOfMemory(); + SDL_FreeYUVOverlay(overlay); + return(NULL); + } + + if (overlay->planes > 0) + { + overlay->pitches[0] = overlay->hwdata->channel->yplane1->pitch; + overlay->pixels[0] = overlay->hwdata->CurrentFrameData->Y; + } + if (overlay->planes > 1) + { + overlay->pitches[1] = overlay->hwdata->channel->vplane1->pitch; + overlay->pixels[1] = overlay->hwdata->CurrentFrameData->U; + } + if (overlay->planes > 2) + { + overlay->pitches[2] = overlay->hwdata->channel->uplane1->pitch; + overlay->pixels[2] = overlay->hwdata->CurrentFrameData->V; + } + + overlay->hwdata->State = OVERLAY_STATE_ACTIVE; + overlay->hwdata->scaler_on = 0; + overlay->hw_overlay = 1; + + current_overlay=overlay; + + return overlay; +} + +int ph_LockYUVOverlay(_THIS, SDL_Overlay* overlay) +{ + if (overlay == NULL) + { + return -1; + } + + overlay->hwdata->locked = 1; + +/* overlay->hwdata->current = PgNextVideoFrame(overlay->hwdata->channel); + if (overlay->hwdata->current == -1) + { + SDL_SetError("ph_LockYUVOverlay: PgNextFrame() failed, bailing out\n"); + SDL_FreeYUVOverlay(overlay); + return 0; + } + + if (overlay->hwdata->current == 0) + { + overlay->hwdata->CurrentFrameData = overlay->hwdata->FrameData0; + } + else + { + overlay->hwdata->CurrentFrameData = overlay->hwdata->FrameData1; + } + + if (overlay->planes > 0) + { + overlay->pitches[0] = overlay->hwdata->channel->yplane1->pitch; + overlay->pixels[0] = overlay->hwdata->CurrentFrameData->Y; + } + if (overlay->planes > 1) + { + overlay->pitches[1] = overlay->hwdata->channel->uplane1->pitch; + overlay->pixels[1] = overlay->hwdata->CurrentFrameData->U; + } + if (overlay->planes > 2) + { + overlay->pitches[2] = overlay->hwdata->channel->vplane1->pitch; + overlay->pixels[2] = overlay->hwdata->CurrentFrameData->V; + } +*/ + + return(0); +} + +void ph_UnlockYUVOverlay(_THIS, SDL_Overlay* overlay) +{ + if (overlay == NULL) + { + return; + } + + overlay->hwdata->locked = 0; +} + +int ph_DisplayYUVOverlay(_THIS, SDL_Overlay* overlay, SDL_Rect* src, SDL_Rect* dst) +{ + int rtncode; + PhPoint_t pos; + SDL_Rect backrect; + PhRect_t windowextent; + int winchanged=0; + + if ((overlay == NULL) || (overlay->hwdata==NULL)) + { + return -1; + } + + if (overlay->hwdata->State == OVERLAY_STATE_UNINIT) + { + return -1; + } + + PtGetAbsPosition(window, &pos.x, &pos.y); + if ((pos.x!=overlay->hwdata->CurrentWindowPos.x) || + (pos.y!=overlay->hwdata->CurrentWindowPos.y)) + { + winchanged=1; + overlay->hwdata->CurrentWindowPos.x=pos.x; + overlay->hwdata->CurrentWindowPos.y=pos.y; + } + + /* If CurrentViewPort position/size has been changed, then move/resize the viewport */ + if ((overlay->hwdata->CurrentViewPort.pos.x != dst->x) || + (overlay->hwdata->CurrentViewPort.pos.y != dst->y) || + (overlay->hwdata->CurrentViewPort.size.w != dst->w) || + (overlay->hwdata->CurrentViewPort.size.h != dst->h) || + (overlay->hwdata->scaler_on==0) || (winchanged==1) || + (overlay->hwdata->forcedredraw==1)) + { + + if (overlay->hwdata->ischromakey==1) + { + /* restore screen behind the overlay/chroma color. */ + backrect.x=overlay->hwdata->CurrentViewPort.pos.x; + backrect.y=overlay->hwdata->CurrentViewPort.pos.y; + backrect.w=overlay->hwdata->CurrentViewPort.size.w; + backrect.h=overlay->hwdata->CurrentViewPort.size.h; + this->UpdateRects(this, 1, &backrect); + + /* Draw the new rectangle of the chroma color at the viewport position */ + PgSetFillColor(overlay->hwdata->chromakey); + PgDrawIRect(dst->x, dst->y, dst->x+dst->w-1, dst->y+dst->h-1, Pg_DRAW_FILL); + PgFlush(); + } + + overlay->hwdata->props.flags |= Pg_SCALER_PROP_SCALER_ENABLE; + overlay->hwdata->scaler_on = 1; + + PhWindowQueryVisible(Ph_QUERY_CONSOLE, 0, PtWidgetRid(window), &windowextent); + overlay->hwdata->CurrentViewPort.pos.x = pos.x-windowextent.ul.x+dst->x; + overlay->hwdata->CurrentViewPort.pos.y = pos.y-windowextent.ul.y+dst->y; + overlay->hwdata->CurrentViewPort.size.w = dst->w; + overlay->hwdata->CurrentViewPort.size.h = dst->h; + PhAreaToRect(&overlay->hwdata->CurrentViewPort, &overlay->hwdata->props.viewport); + overlay->hwdata->CurrentViewPort.pos.x = dst->x; + overlay->hwdata->CurrentViewPort.pos.y = dst->y; + + rtncode = PgConfigScalerChannel(overlay->hwdata->channel, &(overlay->hwdata->props)); + + switch(rtncode) + { + case -1: + SDL_SetError("PgConfigScalerChannel() function failed\n"); + SDL_FreeYUVOverlay(overlay); + return -1; + case 1: + grab_ptrs2(overlay->hwdata->channel, overlay->hwdata->FrameData0, overlay->hwdata->FrameData1); + break; + case 0: + default: + break; + } + } + + +/* + if (overlay->hwdata->locked==0) + { + overlay->hwdata->current = PgNextVideoFrame(overlay->hwdata->channel); + if (overlay->hwdata->current == -1) + { + SDL_SetError("ph_LockYUVOverlay: PgNextFrame() failed, bailing out\n"); + SDL_FreeYUVOverlay(overlay); + return 0; + } + + if (overlay->hwdata->current == 0) + { + overlay->hwdata->CurrentFrameData = overlay->hwdata->FrameData0; + } + else + { + overlay->hwdata->CurrentFrameData = overlay->hwdata->FrameData1; + } + + if (overlay->planes > 0) + { + overlay->pitches[0] = overlay->hwdata->channel->yplane1->pitch; + overlay->pixels[0] = overlay->hwdata->CurrentFrameData->Y; + } + if (overlay->planes > 1) + { + overlay->pitches[1] = overlay->hwdata->channel->uplane1->pitch; + overlay->pixels[1] = overlay->hwdata->CurrentFrameData->U; + } + if (overlay->planes > 2) + { + overlay->pitches[2] = overlay->hwdata->channel->vplane1->pitch; + overlay->pixels[2] = overlay->hwdata->CurrentFrameData->V; + } + } +*/ + + return 0; +} + +void ph_FreeYUVOverlay(_THIS, SDL_Overlay *overlay) +{ + SDL_Rect backrect; + + if (overlay == NULL) + { + return; + } + + if (overlay->hwdata == NULL) + { + return; + } + + current_overlay=NULL; + + /* restore screen behind the overlay/chroma color. */ + backrect.x=overlay->hwdata->CurrentViewPort.pos.x; + backrect.y=overlay->hwdata->CurrentViewPort.pos.y; + backrect.w=overlay->hwdata->CurrentViewPort.size.w; + backrect.h=overlay->hwdata->CurrentViewPort.size.h; + this->UpdateRects(this, 1, &backrect); + + /* it is need for some buggy drivers, that can't hide overlay before */ + /* freeing buffer, so we got trash on the srceen */ + overlay->hwdata->props.flags &= ~Pg_SCALER_PROP_SCALER_ENABLE; + PgConfigScalerChannel(overlay->hwdata->channel, &(overlay->hwdata->props)); + + overlay->hwdata->scaler_on = 0; + overlay->hwdata->State = OVERLAY_STATE_UNINIT; + + if (overlay->hwdata->channel != NULL) + { + PgDestroyVideoChannel(overlay->hwdata->channel); + overlay->hwdata->channel = NULL; + return; + } + + overlay->hwdata->CurrentFrameData = NULL; + + SDL_free(overlay->hwdata->FrameData0); + SDL_free(overlay->hwdata->FrameData1); + overlay->hwdata->FrameData0 = NULL; + overlay->hwdata->FrameData1 = NULL; + SDL_free(overlay->hwdata); +} diff --git a/3rdparty/SDL/src/video/photon/SDL_phyuv_c.h b/3rdparty/SDL/src/video/photon/SDL_phyuv_c.h new file mode 100644 index 0000000..c6f73fe --- /dev/null +++ b/3rdparty/SDL/src/video/photon/SDL_phyuv_c.h @@ -0,0 +1,62 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#ifndef __SDL_PH_YUV_H__ +#define __SDL_PH_YUV_H__ + +/* This is the photon implementation of YUV video overlays */ + +#include "SDL_video.h" +#include "SDL_ph_video.h" + +struct private_yuvhwdata +{ + FRAMEDATA* CurrentFrameData; + FRAMEDATA* FrameData0; + FRAMEDATA* FrameData1; + PgScalerProps_t props; + PgScalerCaps_t caps; + PgVideoChannel_t* channel; + PhArea_t CurrentViewPort; + PhPoint_t CurrentWindowPos; + long format; + int scaler_on; + int current; + long YStride; + long VStride; + long UStride; + int ischromakey; + long chromakey; + int forcedredraw; + unsigned long State; + long flags; + int locked; +}; + +extern SDL_Overlay* ph_CreateYUVOverlay(_THIS, int width, int height, Uint32 format, SDL_Surface* display); +extern int ph_LockYUVOverlay(_THIS, SDL_Overlay* overlay); +extern void ph_UnlockYUVOverlay(_THIS, SDL_Overlay* overlay); +extern int ph_DisplayYUVOverlay(_THIS, SDL_Overlay* overlay, SDL_Rect* src, SDL_Rect* dst); +extern void ph_FreeYUVOverlay(_THIS, SDL_Overlay* overlay); + +#endif /* __SDL_PH_YUV_H__ */ diff --git a/3rdparty/SDL/src/video/picogui/SDL_pgevents.c b/3rdparty/SDL/src/video/picogui/SDL_pgevents.c new file mode 100644 index 0000000..5006c07 --- /dev/null +++ b/3rdparty/SDL/src/video/picogui/SDL_pgevents.c @@ -0,0 +1,117 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org + + Micah Dowty + micahjd@users.sourceforge.net +*/ +#include "SDL_config.h" + +#include "SDL.h" +#include "../../events/SDL_sysevents.h" +#include "../../events/SDL_events_c.h" +#include "SDL_pgvideo.h" +#include "SDL_pgevents_c.h" + +int PG_HandleClose(struct pgEvent *evt) +{ + SDL_PrivateQuit(); + return 1; /* Intercept the event's normal quit handling */ +} + +int PG_HandleResize(struct pgEvent *evt) +{ + SDL_PrivateResize(evt->e.size.w, evt->e.size.h); + return 0; +} + +int PG_HandleKey(struct pgEvent *evt) +{ + SDL_keysym sym; + SDL_memset(&sym,0,sizeof(sym)); + sym.sym = evt->e.kbd.key; + sym.mod = evt->e.kbd.mods; + SDL_PrivateKeyboard(evt->type == PG_WE_KBD_KEYDOWN, &sym); + return 0; +} + +int PG_HandleChar(struct pgEvent *evt) +{ + SDL_keysym sym; + SDL_memset(&sym,0,sizeof(sym)); + sym.unicode = evt->e.kbd.key; + sym.mod = evt->e.kbd.mods; + SDL_PrivateKeyboard(evt->type == PG_WE_KBD_KEYDOWN, &sym); + return 0; +} + +int PG_HandleMouseButton(struct pgEvent *evt) +{ + /* We need to focus the canvas when it's clicked */ + if (evt->extra) { + SDL_VideoDevice *this = (SDL_VideoDevice *) evt->extra; + pgFocus(this->hidden->wCanvas); + } + SDL_PrivateMouseButton(evt->type == PG_WE_PNTR_DOWN, evt->e.pntr.chbtn, + evt->e.pntr.x, evt->e.pntr.y); + return 0; +} + +int PG_HandleMouseMotion(struct pgEvent *evt) +{ + SDL_PrivateMouseMotion(evt->e.pntr.btn,0,evt->e.pntr.x, evt->e.pntr.y); + return 0; +} + +void PG_PumpEvents(_THIS) +{ + /* Process all pending events */ + pgEventPoll(); +} + +void PG_InitOSKeymap(_THIS) +{ + /* We need no keymap */ +} + +void PG_InitEvents(_THIS) +{ + /* Turn on all the mouse and keyboard triggers for our canvas, normally less important + * events like mouse movement are ignored to save bandwidth. */ + pgSetWidget(this->hidden->wCanvas, PG_WP_TRIGGERMASK, + pgGetWidget(this->hidden->wCanvas, PG_WP_TRIGGERMASK) | + PG_TRIGGER_UP | PG_TRIGGER_DOWN | PG_TRIGGER_MOVE | + PG_TRIGGER_KEYUP | PG_TRIGGER_KEYDOWN | PG_TRIGGER_CHAR,0); + + /* Start our canvas out focused, so we get keyboard input */ + pgFocus(this->hidden->wCanvas); + + /* Set up bindings for all the above event handlers */ + pgBind(this->hidden->wApp, PG_WE_CLOSE, &PG_HandleClose, NULL); + pgBind(this->hidden->wCanvas, PG_WE_BUILD, &PG_HandleResize, NULL); + pgBind(this->hidden->wCanvas, PG_WE_KBD_CHAR, &PG_HandleChar, NULL); + pgBind(this->hidden->wCanvas, PG_WE_KBD_KEYUP, &PG_HandleKey, NULL); + pgBind(this->hidden->wCanvas, PG_WE_KBD_KEYDOWN, &PG_HandleKey, NULL); + pgBind(this->hidden->wCanvas, PG_WE_PNTR_MOVE, &PG_HandleMouseMotion, NULL); + pgBind(this->hidden->wCanvas, PG_WE_PNTR_UP, &PG_HandleMouseButton, NULL); + pgBind(this->hidden->wCanvas, PG_WE_PNTR_DOWN, &PG_HandleMouseButton, this); +} + +/* end of SDL_pgevents.c ... */ diff --git a/3rdparty/SDL/src/video/picogui/SDL_pgevents_c.h b/3rdparty/SDL/src/video/picogui/SDL_pgevents_c.h new file mode 100644 index 0000000..a54e225 --- /dev/null +++ b/3rdparty/SDL/src/video/picogui/SDL_pgevents_c.h @@ -0,0 +1,37 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org + + Micah Dowty + micahjd@users.sourceforge.net +*/ +#include "SDL_config.h" + +#include "SDL_pgvideo.h" + +/* Variables and functions exported by SDL_sysevents.c to other parts + of the native video subsystem (SDL_sysvideo.c) +*/ +extern void PG_PumpEvents(_THIS); +extern void PG_InitEvents(_THIS); +extern void PG_InitOSKeymap(_THIS); + +/* end of SDL_pgevents_c.h ... */ + diff --git a/3rdparty/SDL/src/video/picogui/SDL_pgvideo.c b/3rdparty/SDL/src/video/picogui/SDL_pgvideo.c new file mode 100644 index 0000000..18b3fe4 --- /dev/null +++ b/3rdparty/SDL/src/video/picogui/SDL_pgvideo.c @@ -0,0 +1,364 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org + + Micah Dowty + micahjd@users.sourceforge.net +*/ +#include "SDL_config.h" + +#include "SDL_video.h" +#include "SDL_mouse.h" +#include "../SDL_sysvideo.h" +#include "../SDL_pixels_c.h" +#include "../../events/SDL_events_c.h" + +#include "SDL_pgvideo.h" +#include "SDL_pgevents_c.h" + +#define PGVID_DRIVER_NAME "picogui" + +/* Initialization/Query functions */ +static int PG_VideoInit(_THIS, SDL_PixelFormat *vformat); +static SDL_Rect **PG_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags); +static SDL_Surface *PG_SetVideoMode(_THIS, SDL_Surface *current, int width, int height, int bpp, Uint32 flags); +static int PG_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors); +static void PG_VideoQuit(_THIS); + +/* Hardware surface functions */ +static int PG_AllocHWSurface(_THIS, SDL_Surface *surface); +static int PG_LockHWSurface(_THIS, SDL_Surface *surface); +static void PG_UnlockHWSurface(_THIS, SDL_Surface *surface); +static void PG_FreeHWSurface(_THIS, SDL_Surface *surface); + +/* etc. */ +static void PG_UpdateRects(_THIS, int numrects, SDL_Rect *rects); + +// The implementation dependent data for the window manager cursor +struct WMcursor { + /* Our cursor is a PicoGUI theme */ + pghandle theme; +} ; + +/* WM functions */ +void PG_SetCaption(_THIS, const char *title, const char *icon); +WMcursor * PG_CreateWMCursor (_THIS,Uint8 * data, Uint8 * mask, + int w, int h, int hot_x, int hot_y); +void PG_FreeWMCursor (_THIS, WMcursor * cursor); +void PG_WarpWMCursor(_THIS, Uint16 x, Uint16 y); +int PG_ShowWMCursor (_THIS, WMcursor * cursor); + +/* PicoGUI driver bootstrap functions */ + +static int PG_Available(void) +{ + /* FIXME: The current client lib doesn't give a way to see if the picogui + * server is reachable without causing a fatal error if it isn't. + * This should be fixed in cli_c2, but until then assume we can + * connect. Since more common drivers like X11 are probed first anyway, + * this shouldn't be a huge problem. + */ + return(1); +} + +static void PG_DeleteDevice(SDL_VideoDevice *device) +{ + SDL_free(device->hidden); + SDL_free(device); +} + +static SDL_VideoDevice *PG_CreateDevice(int devindex) +{ + SDL_VideoDevice *device; + + /* Initialize all variables that we clean on shutdown */ + device = (SDL_VideoDevice *)SDL_malloc(sizeof(SDL_VideoDevice)); + if ( device ) { + SDL_memset(device, 0, (sizeof *device)); + device->hidden = (struct SDL_PrivateVideoData *) + SDL_malloc((sizeof *device->hidden)); + } + if ( (device == NULL) || (device->hidden == NULL) ) { + SDL_OutOfMemory(); + if ( device ) { + SDL_free(device); + } + return(0); + } + SDL_memset(device->hidden, 0, (sizeof *device->hidden)); + + /* Set the function pointers */ + device->VideoInit = PG_VideoInit; + device->ListModes = PG_ListModes; + device->SetVideoMode = PG_SetVideoMode; + device->CreateYUVOverlay = NULL; + device->SetColors = PG_SetColors; + device->UpdateRects = PG_UpdateRects; + device->VideoQuit = PG_VideoQuit; + device->AllocHWSurface = PG_AllocHWSurface; + device->CheckHWBlit = NULL; + device->FillHWRect = NULL; + device->SetHWColorKey = NULL; + device->SetHWAlpha = NULL; + device->LockHWSurface = PG_LockHWSurface; + device->UnlockHWSurface = PG_UnlockHWSurface; + device->FlipHWSurface = NULL; + device->FreeHWSurface = PG_FreeHWSurface; + device->SetCaption = PG_SetCaption; + device->SetIcon = NULL; + device->IconifyWindow = NULL; + device->GrabInput = NULL; + + device->PumpEvents = PG_PumpEvents; + device->InitOSKeymap = PG_InitOSKeymap; + + device->ShowWMCursor = PG_ShowWMCursor; + device->CreateWMCursor = PG_CreateWMCursor; + device->FreeWMCursor = PG_FreeWMCursor; + device->WarpWMCursor = PG_WarpWMCursor; + + device->free = PG_DeleteDevice; + + return device; +} + +VideoBootStrap PG_bootstrap = { + PGVID_DRIVER_NAME, "PicoGUI SDL driver", + PG_Available, PG_CreateDevice +}; + + +int PG_VideoInit(_THIS, SDL_PixelFormat *vformat) +{ + /* Connect to the PicoGUI server. No way to process command line args yet, + * but since this is based on SHM it's not important to be able to specify + * a remote PicoGUI server. + * + * FIXME: Another nitpick about the current client lib is there's no + * clean way to indicate that command line args are not available. + */ + pgInit(0,(char**)""); + this->hidden->mi = *pgGetVideoMode(); + + /* Create a picogui application and canvas. We'll populate the canvas later. */ + this->hidden->wApp = pgRegisterApp(PG_APP_NORMAL,"SDL",0); + this->hidden->wCanvas = pgNewWidget(PG_WIDGET_CANVAS,0,0); + pgSetWidget(PGDEFAULT, + PG_WP_SIDE, PG_S_ALL, + 0); + + PG_InitEvents(this); + + /* Determine the current screen size */ + this->info.current_w = this->hidden->mi.lxres; + this->info.current_h = this->hidden->mi.lyres; + + /* Determine the screen depth. + * We change this during the SDL_SetVideoMode implementation... + * Round up to the nearest Bytes per pixel + */ + vformat->BitsPerPixel = this->hidden->mi.bpp; + vformat->BytesPerPixel = this->hidden->mi.bpp >> 3; + if (this->hidden->mi.bpp & 7) + vformat->BytesPerPixel++; + + /* We're done! */ + return(0); +} + +SDL_Rect **PG_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags) +{ + return (SDL_Rect **) -1; +} + +SDL_Surface *PG_SetVideoMode(_THIS, SDL_Surface *current, + int width, int height, int bpp, Uint32 flags) +{ + if ( this->hidden->bitmap ) { + /* Free old bitmap */ + if (current->pixels) { + shmdt(current->pixels); + current->pixels = NULL; + } + pgDelete(this->hidden->bitmap); + } + + /* Allocate the new pixel format for the screen */ + if ( ! SDL_ReallocFormat(current, bpp, 0, 0, 0, 0) ) { + SDL_SetError("Couldn't allocate new pixel format for requested mode"); + return(NULL); + } + + /* Create a new picogui bitmap */ + this->hidden->bitmap = pgCreateBitmap(width,height); + this->hidden->shm = *pgMakeSHMBitmap(this->hidden->bitmap); + current->pixels = shmat(shmget(this->hidden->shm.shm_key, + this->hidden->shm.shm_length,0),NULL,0); + + /* Reset the canvas, and draw persistent and incremental grops. + * Use mapping and offsets to center it. + */ + + pgWriteCmd(this->hidden->wCanvas, PGCANVAS_NUKE, 0); + + /* 0. Set the source position during incremental rendering + */ + pgWriteCmd(this->hidden->wCanvas, PGCANVAS_GROP, 5, PG_GROP_SETSRC,0,0,0,0); + pgWriteCmd(this->hidden->wCanvas, PGCANVAS_GROPFLAGS, 1, PG_GROPF_INCREMENTAL); + + /* 1. Incremental bitmap rendering + */ + pgWriteCmd(this->hidden->wCanvas, PGCANVAS_GROP, 6, PG_GROP_BITMAP, + 0,0,0,0,this->hidden->bitmap); + pgWriteCmd(this->hidden->wCanvas, PGCANVAS_GROPFLAGS, 1, PG_GROPF_INCREMENTAL); + + /* 2. Normal bitmap rendering + */ + pgWriteCmd(this->hidden->wCanvas, PGCANVAS_GROP, 6, PG_GROP_BITMAP, + 0,0,this->hidden->shm.width,this->hidden->shm.height,this->hidden->bitmap); + + /* Set up the new mode framebuffer */ + current->flags = 0; + current->w = this->hidden->shm.width; + current->h = this->hidden->shm.height; + current->pitch = this->hidden->shm.pitch; + + /* Set up pixel format */ + current->format->BitsPerPixel = this->hidden->shm.bpp; + current->format->BytesPerPixel = this->hidden->shm.bpp >> 3; + if (this->hidden->shm.bpp & 7) + current->format->BytesPerPixel++; + current->format->palette = NULL; + current->format->Rmask = this->hidden->shm.red_mask; + current->format->Gmask = this->hidden->shm.green_mask; + current->format->Bmask = this->hidden->shm.blue_mask; + current->format->Amask = this->hidden->shm.alpha_mask; + current->format->Rshift = this->hidden->shm.red_shift; + current->format->Gshift = this->hidden->shm.green_shift; + current->format->Bshift = this->hidden->shm.blue_shift; + current->format->Ashift = this->hidden->shm.alpha_shift; + current->format->Rloss = 8 - this->hidden->shm.red_length; + current->format->Gloss = 8 - this->hidden->shm.green_length; + current->format->Bloss = 8 - this->hidden->shm.blue_length; + current->format->Aloss = 8 - this->hidden->shm.alpha_length; + + /* Draw the app */ + pgUpdate(); + + /* We're done */ + return(current); +} + +/* We don't actually allow hardware surfaces other than the main one */ +static int PG_AllocHWSurface(_THIS, SDL_Surface *surface) +{ + return(-1); +} +static void PG_FreeHWSurface(_THIS, SDL_Surface *surface) +{ + return; +} + +/* We need to wait for vertical retrace on page flipped displays */ +static int PG_LockHWSurface(_THIS, SDL_Surface *surface) +{ + return(0); +} + +static void PG_UnlockHWSurface(_THIS, SDL_Surface *surface) +{ + return; +} + +static void PG_UpdateRects(_THIS, int numrects, SDL_Rect *rects) +{ + int i; + + for (i = 0; i < numrects; i++) { + if (rects[i].w <= 0 || rects[i].h <= 0) + continue; + + /* Schedule an incremental update for this rectangle, using + * the canvas gropnodes we've loaded beforehand. + */ + pgWriteCmd(this->hidden->wCanvas, PGCANVAS_FINDGROP, 1, 0); + pgWriteCmd(this->hidden->wCanvas, PGCANVAS_MOVEGROP, 4, + rects[i].x, rects[i].y, + rects[i].w, rects[i].h); + pgWriteCmd(this->hidden->wCanvas, PGCANVAS_FINDGROP, 1, 1); + pgWriteCmd(this->hidden->wCanvas, PGCANVAS_MOVEGROP, 4, + rects[i].x, rects[i].y, + rects[i].w, rects[i].h); + + /* Go perform the update */ + pgWriteCmd(this->hidden->wCanvas, PGCANVAS_INCREMENTAL, 0); + pgSubUpdate(this->hidden->wCanvas); + } +} + +int PG_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors) +{ + /* do nothing of note. */ + return(1); +} + +/* Note: If we are terminated, this could be called in the middle of + another SDL video routine -- notably UpdateRects. +*/ +void PG_VideoQuit(_THIS) +{ + if (this->screen->pixels != NULL) + { + shmdt(this->screen->pixels); + this->screen->pixels = NULL; + pgDelete(this->hidden->bitmap); + } + pgDelete(this->hidden->wCanvas); + pgDelete(this->hidden->wApp); +} + +void PG_SetCaption(_THIS, const char *title, const char *icon) +{ + if (title != NULL) + pgReplaceText(this->hidden->wApp, title); + pgUpdate(); +} + +/* FIXME: The cursor stuff isn't implemented yet! */ + +WMcursor * PG_CreateWMCursor (_THIS,Uint8 * data, Uint8 * mask, + int w, int h, int hot_x, int hot_y) +{ + static WMcursor dummy; + return &dummy; +} + +void PG_FreeWMCursor (_THIS, WMcursor * cursor) +{ +} + +void PG_WarpWMCursor(_THIS, Uint16 x, Uint16 y) +{ +} + +int PG_ShowWMCursor (_THIS, WMcursor * cursor) +{ + return 1; +} diff --git a/3rdparty/SDL/src/video/picogui/SDL_pgvideo.h b/3rdparty/SDL/src/video/picogui/SDL_pgvideo.h new file mode 100644 index 0000000..155f86b --- /dev/null +++ b/3rdparty/SDL/src/video/picogui/SDL_pgvideo.h @@ -0,0 +1,50 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org + + Micah Dowty + micahjd@users.sourceforge.net +*/ +#include "SDL_config.h" + +#ifndef _SDL_pgvideo_h +#define _SDL_pgvideo_h + +#include "SDL_mouse.h" +#include "SDL_mutex.h" +#include "../SDL_sysvideo.h" + +#include <picogui.h> +#include <sys/shm.h> + +/* Hidden "this" pointer for the video functions */ +#define _THIS SDL_VideoDevice *this + + +/* Private display data */ + +struct SDL_PrivateVideoData { + pghandle wApp, wCanvas; /* PicoGUI widgets */ + pghandle bitmap; + struct pgshmbitmap shm; /* shared memory info */ + struct pgmodeinfo mi; /* PicoGUI video mode info structure */ +}; + +#endif /* _SDL_pgvideo_h */ diff --git a/3rdparty/SDL/src/video/ps2gs/SDL_gsevents.c b/3rdparty/SDL/src/video/ps2gs/SDL_gsevents.c new file mode 100644 index 0000000..1b842af --- /dev/null +++ b/3rdparty/SDL/src/video/ps2gs/SDL_gsevents.c @@ -0,0 +1,977 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* Handle the event stream, converting console events into SDL events */ + +#include <sys/types.h> +#include <sys/time.h> +#include <sys/ioctl.h> +#include <unistd.h> +#include <fcntl.h> +#include <errno.h> +#include <limits.h> + +/* For parsing /proc */ +#include <dirent.h> +#include <ctype.h> + +#include <linux/vt.h> +#include <linux/kd.h> +#include <linux/keyboard.h> + +#include "SDL_mutex.h" +#include "../SDL_sysvideo.h" +#include "../../events/SDL_sysevents.h" +#include "../../events/SDL_events_c.h" +#include "SDL_gsvideo.h" +#include "SDL_gsevents_c.h" +#include "SDL_gskeys.h" + +#ifndef GPM_NODE_FIFO +#define GPM_NODE_FIFO "/dev/gpmdata" +#endif + +/* The translation tables from a console scancode to a SDL keysym */ +#define NUM_VGAKEYMAPS (1<<KG_CAPSSHIFT) +static Uint16 vga_keymap[NUM_VGAKEYMAPS][NR_KEYS]; +static SDLKey keymap[128]; +static Uint16 keymap_temp[128]; /* only used at startup */ +static SDL_keysym *TranslateKey(int scancode, SDL_keysym *keysym); + +/* Ugh, we have to duplicate the kernel's keysym mapping code... + Oh, it's not so bad. :-) + + FIXME: Add keyboard LED handling code + */ +static void GS_vgainitkeymaps(int fd) +{ + struct kbentry entry; + int map, i; + + /* Don't do anything if we are passed a closed keyboard */ + if ( fd < 0 ) { + return; + } + + /* Load all the keysym mappings */ + for ( map=0; map<NUM_VGAKEYMAPS; ++map ) { + SDL_memset(vga_keymap[map], 0, NR_KEYS*sizeof(Uint16)); + for ( i=0; i<NR_KEYS; ++i ) { + entry.kb_table = map; + entry.kb_index = i; + if ( ioctl(fd, KDGKBENT, &entry) == 0 ) { + /* fill keytemp. This replaces SDL_fbkeys.h */ + if ( (map == 0) && (i<128) ) { + keymap_temp[i] = entry.kb_value; + } + /* The "Enter" key is a special case */ + if ( entry.kb_value == K_ENTER ) { + entry.kb_value = K(KT_ASCII,13); + } + /* Handle numpad specially as well */ + if ( KTYP(entry.kb_value) == KT_PAD ) { + switch ( entry.kb_value ) { + case K_P0: + case K_P1: + case K_P2: + case K_P3: + case K_P4: + case K_P5: + case K_P6: + case K_P7: + case K_P8: + case K_P9: + vga_keymap[map][i]=entry.kb_value; + vga_keymap[map][i]+= '0'; + break; + case K_PPLUS: + vga_keymap[map][i]=K(KT_ASCII,'+'); + break; + case K_PMINUS: + vga_keymap[map][i]=K(KT_ASCII,'-'); + break; + case K_PSTAR: + vga_keymap[map][i]=K(KT_ASCII,'*'); + break; + case K_PSLASH: + vga_keymap[map][i]=K(KT_ASCII,'/'); + break; + case K_PENTER: + vga_keymap[map][i]=K(KT_ASCII,'\r'); + break; + case K_PCOMMA: + vga_keymap[map][i]=K(KT_ASCII,','); + break; + case K_PDOT: + vga_keymap[map][i]=K(KT_ASCII,'.'); + break; + default: + break; + } + } + /* Do the normal key translation */ + if ( (KTYP(entry.kb_value) == KT_LATIN) || + (KTYP(entry.kb_value) == KT_ASCII) || + (KTYP(entry.kb_value) == KT_LETTER) ) { + vga_keymap[map][i] = entry.kb_value; + } + } + } + } +} + +int GS_InGraphicsMode(_THIS) +{ + return((keyboard_fd >= 0) && (saved_kbd_mode >= 0)); +} + +int GS_EnterGraphicsMode(_THIS) +{ + struct termios keyboard_termios; + + /* Set medium-raw keyboard mode */ + if ( (keyboard_fd >= 0) && !GS_InGraphicsMode(this) ) { + + /* Switch to the correct virtual terminal */ + if ( current_vt > 0 ) { + struct vt_stat vtstate; + + if ( ioctl(keyboard_fd, VT_GETSTATE, &vtstate) == 0 ) { + saved_vt = vtstate.v_active; + } + if ( ioctl(keyboard_fd, VT_ACTIVATE, current_vt) == 0 ) { + ioctl(keyboard_fd, VT_WAITACTIVE, current_vt); + } + } + + /* Set the terminal input mode */ + if ( tcgetattr(keyboard_fd, &saved_kbd_termios) < 0 ) { + SDL_SetError("Unable to get terminal attributes"); + if ( keyboard_fd > 0 ) { + close(keyboard_fd); + } + keyboard_fd = -1; + return(-1); + } + if ( ioctl(keyboard_fd, KDGKBMODE, &saved_kbd_mode) < 0 ) { + SDL_SetError("Unable to get current keyboard mode"); + if ( keyboard_fd > 0 ) { + close(keyboard_fd); + } + keyboard_fd = -1; + return(-1); + } + keyboard_termios = saved_kbd_termios; + keyboard_termios.c_lflag &= ~(ICANON | ECHO | ISIG); + keyboard_termios.c_iflag &= ~(ISTRIP | IGNCR | ICRNL | INLCR | IXOFF | IXON); + keyboard_termios.c_cc[VMIN] = 0; + keyboard_termios.c_cc[VTIME] = 0; + if (tcsetattr(keyboard_fd, TCSAFLUSH, &keyboard_termios) < 0) { + GS_CloseKeyboard(this); + SDL_SetError("Unable to set terminal attributes"); + return(-1); + } + /* This will fail if we aren't root or this isn't our tty */ + if ( ioctl(keyboard_fd, KDSKBMODE, K_MEDIUMRAW) < 0 ) { + GS_CloseKeyboard(this); + SDL_SetError("Unable to set keyboard in raw mode"); + return(-1); + } + if ( ioctl(keyboard_fd, KDSETMODE, KD_GRAPHICS) < 0 ) { + GS_CloseKeyboard(this); + SDL_SetError("Unable to set keyboard in graphics mode"); + return(-1); + } + } + return(keyboard_fd); +} + +void GS_LeaveGraphicsMode(_THIS) +{ + if ( GS_InGraphicsMode(this) ) { + ioctl(keyboard_fd, KDSETMODE, KD_TEXT); + ioctl(keyboard_fd, KDSKBMODE, saved_kbd_mode); + tcsetattr(keyboard_fd, TCSAFLUSH, &saved_kbd_termios); + saved_kbd_mode = -1; + + /* Head back over to the original virtual terminal */ + if ( saved_vt > 0 ) { + ioctl(keyboard_fd, VT_ACTIVATE, saved_vt); + } + } +} + +void GS_CloseKeyboard(_THIS) +{ + if ( keyboard_fd >= 0 ) { + GS_LeaveGraphicsMode(this); + if ( keyboard_fd > 0 ) { + close(keyboard_fd); + } + } + keyboard_fd = -1; +} + +int GS_OpenKeyboard(_THIS) +{ + /* Open only if not already opened */ + if ( keyboard_fd < 0 ) { + char *tty0[] = { "/dev/tty0", "/dev/vc/0", NULL }; + char *vcs[] = { "/dev/vc/%d", "/dev/tty%d", NULL }; + int i, tty0_fd; + + /* Try to query for a free virtual terminal */ + tty0_fd = -1; + for ( i=0; tty0[i] && (tty0_fd < 0); ++i ) { + tty0_fd = open(tty0[i], O_WRONLY, 0); + } + if ( tty0_fd < 0 ) { + tty0_fd = dup(0); /* Maybe stdin is a VT? */ + } + ioctl(tty0_fd, VT_OPENQRY, ¤t_vt); + close(tty0_fd); + if ( (geteuid() == 0) && (current_vt > 0) ) { + for ( i=0; vcs[i] && (keyboard_fd < 0); ++i ) { + char vtpath[12]; + + SDL_snprintf(vtpath, SDL_arraysize(vtpath), vcs[i], current_vt); + keyboard_fd = open(vtpath, O_RDWR, 0); +#ifdef DEBUG_KEYBOARD + fprintf(stderr, "vtpath = %s, fd = %d\n", + vtpath, keyboard_fd); +#endif /* DEBUG_KEYBOARD */ + + /* This needs to be our controlling tty + so that the kernel ioctl() calls work + */ + if ( keyboard_fd >= 0 ) { + tty0_fd = open("/dev/tty", O_RDWR, 0); + if ( tty0_fd >= 0 ) { + ioctl(tty0_fd, TIOCNOTTY, 0); + close(tty0_fd); + } + } + } + } + if ( keyboard_fd < 0 ) { + /* Last resort, maybe our tty is a usable VT */ + current_vt = 0; + keyboard_fd = open("/dev/tty", O_RDWR); + } +#ifdef DEBUG_KEYBOARD + fprintf(stderr, "Current VT: %d\n", current_vt); +#endif + saved_kbd_mode = -1; + + /* Make sure that our input is a console terminal */ + { int dummy; + if ( ioctl(keyboard_fd, KDGKBMODE, &dummy) < 0 ) { + close(keyboard_fd); + keyboard_fd = -1; + SDL_SetError("Unable to open a console terminal"); + } + } + + /* Set up keymap */ + GS_vgainitkeymaps(keyboard_fd); + } + return(keyboard_fd); +} + +static enum { + MOUSE_NONE = -1, + MOUSE_GPM, /* Note: GPM uses the MSC protocol */ + MOUSE_PS2, + MOUSE_IMPS2, + MOUSE_MS, + MOUSE_BM, + NUM_MOUSE_DRVS +} mouse_drv = MOUSE_NONE; + +void GS_CloseMouse(_THIS) +{ + if ( mouse_fd > 0 ) { + close(mouse_fd); + } + mouse_fd = -1; +} + +/* Returns processes listed in /proc with the desired name */ +static int find_pid(DIR *proc, const char *wanted_name) +{ + struct dirent *entry; + int pid; + + /* First scan proc for the gpm process */ + pid = 0; + while ( (pid == 0) && ((entry=readdir(proc)) != NULL) ) { + if ( isdigit(entry->d_name[0]) ) { + FILE *status; + char path[PATH_MAX]; + char name[PATH_MAX]; + + SDL_snprintf(path, SDL_arraysize(path), "/proc/%s/status", entry->d_name); + status=fopen(path, "r"); + if ( status ) { + name[0] = '\0'; + fscanf(status, "Name: %s", name); + if ( SDL_strcmp(name, wanted_name) == 0 ) { + pid = atoi(entry->d_name); + } + fclose(status); + } + } + } + return pid; +} + +/* Returns true if /dev/gpmdata is being written to by gpm */ +static int gpm_available(void) +{ + int available; + DIR *proc; + int pid; + int cmdline, len, arglen; + char path[PATH_MAX]; + char args[PATH_MAX], *arg; + + /* Don't bother looking if the fifo isn't there */ + if ( access(GPM_NODE_FIFO, F_OK) < 0 ) { + return(0); + } + + available = 0; + proc = opendir("/proc"); + if ( proc ) { + while ( (pid=find_pid(proc, "gpm")) > 0 ) { + SDL_snprintf(path, SDL_arraysize(path), "/proc/%d/cmdline", pid); + cmdline = open(path, O_RDONLY, 0); + if ( cmdline >= 0 ) { + len = read(cmdline, args, sizeof(args)); + arg = args; + while ( len > 0 ) { + if ( SDL_strcmp(arg, "-R") == 0 ) { + available = 1; + } + arglen = SDL_strlen(arg)+1; + len -= arglen; + arg += arglen; + } + close(cmdline); + } + } + closedir(proc); + } + return available; +} + + +/* rcg06112001 Set up IMPS/2 mode, if possible. This gives + * us access to the mousewheel, etc. Returns zero if + * writes to device failed, but you still need to query the + * device to see which mode it's actually in. + */ +static int set_imps2_mode(int fd) +{ + /* If you wanted to control the mouse mode (and we do :) ) ... + Set IMPS/2 protocol: + {0xf3,200,0xf3,100,0xf3,80} + Reset mouse device: + {0xFF} + */ + Uint8 set_imps2[] = {0xf3, 200, 0xf3, 100, 0xf3, 80}; + Uint8 reset = 0xff; + fd_set fdset; + struct timeval tv; + int retval = 0; + + if ( write(fd, &set_imps2, sizeof(set_imps2)) == sizeof(set_imps2) ) { + if (write(fd, &reset, sizeof (reset)) == sizeof (reset) ) { + retval = 1; + } + } + + /* Get rid of any chatter from the above */ + FD_ZERO(&fdset); + FD_SET(fd, &fdset); + tv.tv_sec = 0; + tv.tv_usec = 0; + while ( select(fd+1, &fdset, 0, 0, &tv) > 0 ) { + char temp[32]; + read(fd, temp, sizeof(temp)); + } + + return retval; +} + + +/* Returns true if the mouse uses the IMPS/2 protocol */ +static int detect_imps2(int fd) +{ + int imps2; + + imps2 = 0; + + if ( SDL_getenv("SDL_MOUSEDEV_IMPS2") ) { + imps2 = 1; + } + if ( ! imps2 ) { + Uint8 query_ps2 = 0xF2; + fd_set fdset; + struct timeval tv; + + /* Get rid of any mouse motion noise */ + FD_ZERO(&fdset); + FD_SET(fd, &fdset); + tv.tv_sec = 0; + tv.tv_usec = 0; + while ( select(fd+1, &fdset, 0, 0, &tv) > 0 ) { + char temp[32]; + read(fd, temp, sizeof(temp)); + } + + /* Query for the type of mouse protocol */ + if ( write(fd, &query_ps2, sizeof (query_ps2)) == sizeof (query_ps2)) { + Uint8 ch = 0; + + /* Get the mouse protocol response */ + do { + FD_ZERO(&fdset); + FD_SET(fd, &fdset); + tv.tv_sec = 1; + tv.tv_usec = 0; + if ( select(fd+1, &fdset, 0, 0, &tv) < 1 ) { + break; + } + } while ( (read(fd, &ch, sizeof (ch)) == sizeof (ch)) && + ((ch == 0xFA) || (ch == 0xAA)) ); + + /* Experimental values (Logitech wheelmouse) */ +#ifdef DEBUG_MOUSE +fprintf(stderr, "Last mouse mode: 0x%x\n", ch); +#endif + if ( ch == 3 ) { + imps2 = 1; + } + } + } + return imps2; +} + +int GS_OpenMouse(_THIS) +{ + int i; + const char *mousedev; + const char *mousedrv; + + mousedrv = SDL_getenv("SDL_MOUSEDRV"); + mousedev = SDL_getenv("SDL_MOUSEDEV"); + mouse_fd = -1; + + /* STD MICE */ + + if ( mousedev == NULL ) { + /* FIXME someday... allow multiple mice in this driver */ + char *ps2mice[] = { + "/dev/input/mice", "/dev/usbmouse", "/dev/psaux", NULL + }; + /* First try to use GPM in repeater mode */ + if ( mouse_fd < 0 ) { + if ( gpm_available() ) { + mouse_fd = open(GPM_NODE_FIFO, O_RDONLY, 0); + if ( mouse_fd >= 0 ) { +#ifdef DEBUG_MOUSE +fprintf(stderr, "Using GPM mouse\n"); +#endif + mouse_drv = MOUSE_GPM; + } + } + } + /* Now try to use a modern PS/2 mouse */ + for ( i=0; (mouse_fd < 0) && ps2mice[i]; ++i ) { + mouse_fd = open(ps2mice[i], O_RDWR, 0); + if (mouse_fd < 0) { + mouse_fd = open(ps2mice[i], O_RDONLY, 0); + } + if (mouse_fd >= 0) { + /* rcg06112001 Attempt to set IMPS/2 mode */ + if ( i == 0 ) { + set_imps2_mode(mouse_fd); + } + if (detect_imps2(mouse_fd)) { +#ifdef DEBUG_MOUSE +fprintf(stderr, "Using IMPS2 mouse\n"); +#endif + mouse_drv = MOUSE_IMPS2; + } else { + mouse_drv = MOUSE_PS2; +#ifdef DEBUG_MOUSE +fprintf(stderr, "Using PS2 mouse\n"); +#endif + } + } + } + /* Next try to use a PPC ADB port mouse */ + if ( mouse_fd < 0 ) { + mouse_fd = open("/dev/adbmouse", O_RDONLY, 0); + if ( mouse_fd >= 0 ) { +#ifdef DEBUG_MOUSE +fprintf(stderr, "Using ADB mouse\n"); +#endif + mouse_drv = MOUSE_BM; + } + } + } + /* Default to a serial Microsoft mouse */ + if ( mouse_fd < 0 ) { + if ( mousedev == NULL ) { + mousedev = "/dev/mouse"; + } + mouse_fd = open(mousedev, O_RDONLY, 0); + if ( mouse_fd >= 0 ) { + struct termios mouse_termios; + + /* Set the sampling speed to 1200 baud */ + tcgetattr(mouse_fd, &mouse_termios); + mouse_termios.c_iflag = IGNBRK | IGNPAR; + mouse_termios.c_oflag = 0; + mouse_termios.c_lflag = 0; + mouse_termios.c_line = 0; + mouse_termios.c_cc[VTIME] = 0; + mouse_termios.c_cc[VMIN] = 1; + mouse_termios.c_cflag = CREAD | CLOCAL | HUPCL; + mouse_termios.c_cflag |= CS8; + mouse_termios.c_cflag |= B1200; + tcsetattr(mouse_fd, TCSAFLUSH, &mouse_termios); +#ifdef DEBUG_MOUSE +fprintf(stderr, "Using Microsoft mouse on %s\n", mousedev); +#endif + mouse_drv = MOUSE_MS; + } + } + if ( mouse_fd < 0 ) { + mouse_drv = MOUSE_NONE; + } + return(mouse_fd); +} + +static int posted = 0; + +void GS_vgamousecallback(int button, int dx, int dy) +{ + int button_1, button_3; + int button_state; + int state_changed; + int i; + Uint8 state; + + if ( dx || dy ) { + posted += SDL_PrivateMouseMotion(0, 1, dx, dy); + } + + /* Swap button 1 and 3 */ + button_1 = (button & 0x04) >> 2; + button_3 = (button & 0x01) << 2; + button &= ~0x05; + button |= (button_1|button_3); + + /* See what changed */ + button_state = SDL_GetMouseState(NULL, NULL); + state_changed = button_state ^ button; + for ( i=0; i<8; ++i ) { + if ( state_changed & (1<<i) ) { + if ( button & (1<<i) ) { + state = SDL_PRESSED; + } else { + state = SDL_RELEASED; + } + posted += SDL_PrivateMouseButton(state, i+1, 0, 0); + } + } +} + +/* For now, use GPM, PS/2, and MS protocols + Driver adapted from the SVGAlib mouse driver code (taken from gpm, etc.) + */ +static void handle_mouse(_THIS) +{ + static int start = 0; + static unsigned char mousebuf[BUFSIZ]; + int i, nread; + int button = 0; + int dx = 0, dy = 0; + int packetsize = 0; + + /* Figure out the mouse packet size */ + switch (mouse_drv) { + case MOUSE_NONE: + /* Ack! */ + read(mouse_fd, mousebuf, BUFSIZ); + return; + case MOUSE_GPM: + packetsize = 5; + break; + case MOUSE_IMPS2: + packetsize = 4; + break; + case MOUSE_PS2: + case MOUSE_MS: + case MOUSE_BM: + packetsize = 3; + break; + case NUM_MOUSE_DRVS: + /* Uh oh.. */ + packetsize = 0; + break; + } + + /* Read as many packets as possible */ + nread = read(mouse_fd, &mousebuf[start], BUFSIZ-start); + if ( nread < 0 ) { + return; + } + nread += start; +#ifdef DEBUG_MOUSE + fprintf(stderr, "Read %d bytes from mouse, start = %d\n", nread, start); +#endif + for ( i=0; i<(nread-(packetsize-1)); i += packetsize ) { + switch (mouse_drv) { + case MOUSE_NONE: + break; + case MOUSE_GPM: + /* GPM protocol has 0x80 in high byte */ + if ( (mousebuf[i] & 0xF8) != 0x80 ) { + /* Go to next byte */ + i -= (packetsize-1); + continue; + } + /* Get current mouse state */ + button = (~mousebuf[i]) & 0x07; + dx = (signed char)(mousebuf[i+1]) + + (signed char)(mousebuf[i+3]); + dy = -((signed char)(mousebuf[i+2]) + + (signed char)(mousebuf[i+4])); + break; + case MOUSE_PS2: + /* PS/2 protocol has nothing in high byte */ + if ( (mousebuf[i] & 0xC0) != 0 ) { + /* Go to next byte */ + i -= (packetsize-1); + continue; + } + /* Get current mouse state */ + button = (mousebuf[i] & 0x04) >> 1 | /*Middle*/ + (mousebuf[i] & 0x02) >> 1 | /*Right*/ + (mousebuf[i] & 0x01) << 2; /*Left*/ + dx = (mousebuf[i] & 0x10) ? + mousebuf[i+1] - 256 : mousebuf[i+1]; + dy = (mousebuf[i] & 0x20) ? + -(mousebuf[i+2] - 256) : -mousebuf[i+2]; + break; + case MOUSE_IMPS2: + /* Get current mouse state */ + button = (mousebuf[i] & 0x04) >> 1 | /*Middle*/ + (mousebuf[i] & 0x02) >> 1 | /*Right*/ + (mousebuf[i] & 0x01) << 2 | /*Left*/ + (mousebuf[i] & 0x40) >> 3 | /* 4 */ + (mousebuf[i] & 0x80) >> 3; /* 5 */ + dx = (mousebuf[i] & 0x10) ? + mousebuf[i+1] - 256 : mousebuf[i+1]; + dy = (mousebuf[i] & 0x20) ? + -(mousebuf[i+2] - 256) : -mousebuf[i+2]; + switch (mousebuf[i+3]&0x0F) { + case 0x0E: /* DX = +1 */ + case 0x02: /* DX = -1 */ + break; + case 0x0F: /* DY = +1 (map button 4) */ + FB_vgamousecallback(button | (1<<3), + 1, 0, 0); + break; + case 0x01: /* DY = -1 (map button 5) */ + FB_vgamousecallback(button | (1<<4), + 1, 0, 0); + break; + } + break; + case MOUSE_MS: + /* Microsoft protocol has 0x40 in high byte */ + if ( (mousebuf[i] & 0x40) != 0x40 ) { + /* Go to next byte */ + i -= (packetsize-1); + continue; + } + /* Get current mouse state */ + button = ((mousebuf[i] & 0x20) >> 3) | + ((mousebuf[i] & 0x10) >> 4); + dx = (signed char)(((mousebuf[i] & 0x03) << 6) | + (mousebuf[i + 1] & 0x3F)); + dy = (signed char)(((mousebuf[i] & 0x0C) << 4) | + (mousebuf[i + 2] & 0x3F)); + break; + case MOUSE_BM: + /* BusMouse protocol has 0xF8 in high byte */ + if ( (mousebuf[i] & 0xF8) != 0x80 ) { + /* Go to next byte */ + i -= (packetsize-1); + continue; + } + /* Get current mouse state */ + button = (~mousebuf[i]) & 0x07; + dx = (signed char)mousebuf[i+1]; + dy = -(signed char)mousebuf[i+2]; + break; + case NUM_MOUSE_DRVS: + /* Uh oh.. */ + dx = 0; + dy = 0; + break; + } + GS_vgamousecallback(button, dx, dy); + } + if ( i < nread ) { + SDL_memcpy(mousebuf, &mousebuf[i], (nread-i)); + start = (nread-i); + } else { + start = 0; + } + return; +} + +static void handle_keyboard(_THIS) +{ + unsigned char keybuf[BUFSIZ]; + int i, nread; + int pressed; + int scancode; + SDL_keysym keysym; + + nread = read(keyboard_fd, keybuf, BUFSIZ); + for ( i=0; i<nread; ++i ) { + scancode = keybuf[i] & 0x7F; + if ( keybuf[i] & 0x80 ) { + pressed = SDL_RELEASED; + } else { + pressed = SDL_PRESSED; + } + TranslateKey(scancode, &keysym); + posted += SDL_PrivateKeyboard(pressed, &keysym); + } +} + +void GS_PumpEvents(_THIS) +{ + fd_set fdset; + int max_fd; + static struct timeval zero; + + do { + posted = 0; + + FD_ZERO(&fdset); + max_fd = 0; + if ( keyboard_fd >= 0 ) { + FD_SET(keyboard_fd, &fdset); + if ( max_fd < keyboard_fd ) { + max_fd = keyboard_fd; + } + } + if ( mouse_fd >= 0 ) { + FD_SET(mouse_fd, &fdset); + if ( max_fd < mouse_fd ) { + max_fd = mouse_fd; + } + } + if ( select(max_fd+1, &fdset, NULL, NULL, &zero) > 0 ) { + if ( keyboard_fd >= 0 ) { + if ( FD_ISSET(keyboard_fd, &fdset) ) { + handle_keyboard(this); + } + } + if ( mouse_fd >= 0 ) { + if ( FD_ISSET(mouse_fd, &fdset) ) { + handle_mouse(this); + } + } + } + } while ( posted ); +} + +void GS_InitOSKeymap(_THIS) +{ + int i; + + /* Initialize the Linux key translation table */ + + /* First get the ascii keys and others not well handled */ + for (i=0; i<SDL_arraysize(keymap); ++i) { + switch(i) { + /* These aren't handled by the x86 kernel keymapping (?) */ + case SCANCODE_PRINTSCREEN: + keymap[i] = SDLK_PRINT; + break; + case SCANCODE_BREAK: + keymap[i] = SDLK_BREAK; + break; + case SCANCODE_BREAK_ALTERNATIVE: + keymap[i] = SDLK_PAUSE; + break; + case SCANCODE_LEFTSHIFT: + keymap[i] = SDLK_LSHIFT; + break; + case SCANCODE_RIGHTSHIFT: + keymap[i] = SDLK_RSHIFT; + break; + case SCANCODE_LEFTCONTROL: + keymap[i] = SDLK_LCTRL; + break; + case SCANCODE_RIGHTCONTROL: + keymap[i] = SDLK_RCTRL; + break; + case SCANCODE_RIGHTWIN: + keymap[i] = SDLK_RSUPER; + break; + case SCANCODE_LEFTWIN: + keymap[i] = SDLK_LSUPER; + break; + case 127: + keymap[i] = SDLK_MENU; + break; + /* this should take care of all standard ascii keys */ + default: + keymap[i] = KVAL(vga_keymap[0][i]); + break; + } + } + for (i=0; i<SDL_arraysize(keymap); ++i) { + switch(keymap_temp[i]) { + case K_F1: keymap[i] = SDLK_F1; break; + case K_F2: keymap[i] = SDLK_F2; break; + case K_F3: keymap[i] = SDLK_F3; break; + case K_F4: keymap[i] = SDLK_F4; break; + case K_F5: keymap[i] = SDLK_F5; break; + case K_F6: keymap[i] = SDLK_F6; break; + case K_F7: keymap[i] = SDLK_F7; break; + case K_F8: keymap[i] = SDLK_F8; break; + case K_F9: keymap[i] = SDLK_F9; break; + case K_F10: keymap[i] = SDLK_F10; break; + case K_F11: keymap[i] = SDLK_F11; break; + case K_F12: keymap[i] = SDLK_F12; break; + + case K_DOWN: keymap[i] = SDLK_DOWN; break; + case K_LEFT: keymap[i] = SDLK_LEFT; break; + case K_RIGHT: keymap[i] = SDLK_RIGHT; break; + case K_UP: keymap[i] = SDLK_UP; break; + + case K_P0: keymap[i] = SDLK_KP0; break; + case K_P1: keymap[i] = SDLK_KP1; break; + case K_P2: keymap[i] = SDLK_KP2; break; + case K_P3: keymap[i] = SDLK_KP3; break; + case K_P4: keymap[i] = SDLK_KP4; break; + case K_P5: keymap[i] = SDLK_KP5; break; + case K_P6: keymap[i] = SDLK_KP6; break; + case K_P7: keymap[i] = SDLK_KP7; break; + case K_P8: keymap[i] = SDLK_KP8; break; + case K_P9: keymap[i] = SDLK_KP9; break; + case K_PPLUS: keymap[i] = SDLK_KP_PLUS; break; + case K_PMINUS: keymap[i] = SDLK_KP_MINUS; break; + case K_PSTAR: keymap[i] = SDLK_KP_MULTIPLY; break; + case K_PSLASH: keymap[i] = SDLK_KP_DIVIDE; break; + case K_PENTER: keymap[i] = SDLK_KP_ENTER; break; + case K_PDOT: keymap[i] = SDLK_KP_PERIOD; break; + + case K_SHIFT: if ( keymap[i] != SDLK_RSHIFT ) + keymap[i] = SDLK_LSHIFT; + break; + case K_SHIFTL: keymap[i] = SDLK_LSHIFT; break; + case K_SHIFTR: keymap[i] = SDLK_RSHIFT; break; + case K_CTRL: if ( keymap[i] != SDLK_RCTRL ) + keymap[i] = SDLK_LCTRL; + break; + case K_CTRLL: keymap[i] = SDLK_LCTRL; break; + case K_CTRLR: keymap[i] = SDLK_RCTRL; break; + case K_ALT: keymap[i] = SDLK_LALT; break; + case K_ALTGR: keymap[i] = SDLK_RALT; break; + + case K_INSERT: keymap[i] = SDLK_INSERT; break; + case K_REMOVE: keymap[i] = SDLK_DELETE; break; + case K_PGUP: keymap[i] = SDLK_PAGEUP; break; + case K_PGDN: keymap[i] = SDLK_PAGEDOWN; break; + case K_FIND: keymap[i] = SDLK_HOME; break; + case K_SELECT: keymap[i] = SDLK_END; break; + + case K_NUM: keymap[i] = SDLK_NUMLOCK; break; + case K_CAPS: keymap[i] = SDLK_CAPSLOCK; break; + + case K_F13: keymap[i] = SDLK_PRINT; break; + case K_HOLD: keymap[i] = SDLK_SCROLLOCK; break; + case K_PAUSE: keymap[i] = SDLK_PAUSE; break; + + case 127: keymap[i] = SDLK_BACKSPACE; break; + + default: break; + } + } +} + +static SDL_keysym *TranslateKey(int scancode, SDL_keysym *keysym) +{ + /* Set the keysym information */ + keysym->scancode = scancode; + keysym->sym = keymap[scancode]; + keysym->mod = KMOD_NONE; + + /* If UNICODE is on, get the UNICODE value for the key */ + keysym->unicode = 0; + if ( SDL_TranslateUNICODE ) { + int map; + SDLMod modstate; + + modstate = SDL_GetModState(); + map = 0; + if ( modstate & KMOD_SHIFT ) { + map |= (1<<KG_SHIFT); + } + if ( modstate & KMOD_CTRL ) { + map |= (1<<KG_CTRL); + } + if ( modstate & KMOD_ALT ) { + map |= (1<<KG_ALT); + } + if ( modstate & KMOD_MODE ) { + map |= (1<<KG_ALTGR); + } + if ( KTYP(vga_keymap[map][scancode]) == KT_LETTER ) { + if ( modstate & KMOD_CAPS ) { + map ^= (1<<KG_SHIFT); + } + } + if ( KTYP(vga_keymap[map][scancode]) == KT_PAD ) { + if ( modstate & KMOD_NUM ) { + keysym->unicode=KVAL(vga_keymap[map][scancode]); + } + } else { + keysym->unicode = KVAL(vga_keymap[map][scancode]); + } + } + return(keysym); +} diff --git a/3rdparty/SDL/src/video/ps2gs/SDL_gsevents_c.h b/3rdparty/SDL/src/video/ps2gs/SDL_gsevents_c.h new file mode 100644 index 0000000..6758ab3 --- /dev/null +++ b/3rdparty/SDL/src/video/ps2gs/SDL_gsevents_c.h @@ -0,0 +1,38 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#include "SDL_gsvideo.h" + +/* Variables and functions exported by SDL_sysevents.c to other parts + of the native video subsystem (SDL_sysvideo.c) +*/ +extern int GS_OpenKeyboard(_THIS); +extern void GS_CloseKeyboard(_THIS); +extern int GS_OpenMouse(_THIS); +extern void GS_CloseMouse(_THIS); +extern int GS_EnterGraphicsMode(_THIS); +extern int GS_InGraphicsMode(_THIS); +extern void GS_LeaveGraphicsMode(_THIS); + +extern void GS_InitOSKeymap(_THIS); +extern void GS_PumpEvents(_THIS); diff --git a/3rdparty/SDL/src/video/ps2gs/SDL_gskeys.h b/3rdparty/SDL/src/video/ps2gs/SDL_gskeys.h new file mode 100644 index 0000000..2b01b6b --- /dev/null +++ b/3rdparty/SDL/src/video/ps2gs/SDL_gskeys.h @@ -0,0 +1,139 @@ + +/* Scancodes for the Linux framebuffer console + - Taken with thanks from SVGAlib 1.4.0 +*/ + +#define SCANCODE_ESCAPE 1 + +#define SCANCODE_1 2 +#define SCANCODE_2 3 +#define SCANCODE_3 4 +#define SCANCODE_4 5 +#define SCANCODE_5 6 +#define SCANCODE_6 7 +#define SCANCODE_7 8 +#define SCANCODE_8 9 +#define SCANCODE_9 10 +#define SCANCODE_0 11 + +#define SCANCODE_MINUS 12 +#define SCANCODE_EQUAL 13 + +#define SCANCODE_BACKSPACE 14 +#define SCANCODE_TAB 15 + +#define SCANCODE_Q 16 +#define SCANCODE_W 17 +#define SCANCODE_E 18 +#define SCANCODE_R 19 +#define SCANCODE_T 20 +#define SCANCODE_Y 21 +#define SCANCODE_U 22 +#define SCANCODE_I 23 +#define SCANCODE_O 24 +#define SCANCODE_P 25 +#define SCANCODE_BRACKET_LEFT 26 +#define SCANCODE_BRACKET_RIGHT 27 + +#define SCANCODE_ENTER 28 + +#define SCANCODE_LEFTCONTROL 29 + +#define SCANCODE_A 30 +#define SCANCODE_S 31 +#define SCANCODE_D 32 +#define SCANCODE_F 33 +#define SCANCODE_G 34 +#define SCANCODE_H 35 +#define SCANCODE_J 36 +#define SCANCODE_K 37 +#define SCANCODE_L 38 +#define SCANCODE_SEMICOLON 39 +#define SCANCODE_APOSTROPHE 40 +#define SCANCODE_GRAVE 41 + +#define SCANCODE_LEFTSHIFT 42 +#define SCANCODE_BACKSLASH 43 + +#define SCANCODE_Z 44 +#define SCANCODE_X 45 +#define SCANCODE_C 46 +#define SCANCODE_V 47 +#define SCANCODE_B 48 +#define SCANCODE_N 49 +#define SCANCODE_M 50 +#define SCANCODE_COMMA 51 +#define SCANCODE_PERIOD 52 +#define SCANCODE_SLASH 53 + +#define SCANCODE_RIGHTSHIFT 54 +#define SCANCODE_KEYPADMULTIPLY 55 + +#define SCANCODE_LEFTALT 56 +#define SCANCODE_SPACE 57 +#define SCANCODE_CAPSLOCK 58 + +#define SCANCODE_F1 59 +#define SCANCODE_F2 60 +#define SCANCODE_F3 61 +#define SCANCODE_F4 62 +#define SCANCODE_F5 63 +#define SCANCODE_F6 64 +#define SCANCODE_F7 65 +#define SCANCODE_F8 66 +#define SCANCODE_F9 67 +#define SCANCODE_F10 68 + +#define SCANCODE_NUMLOCK 69 +#define SCANCODE_SCROLLLOCK 70 + +#define SCANCODE_KEYPAD7 71 +#define SCANCODE_CURSORUPLEFT 71 +#define SCANCODE_KEYPAD8 72 +#define SCANCODE_CURSORUP 72 +#define SCANCODE_KEYPAD9 73 +#define SCANCODE_CURSORUPRIGHT 73 +#define SCANCODE_KEYPADMINUS 74 +#define SCANCODE_KEYPAD4 75 +#define SCANCODE_CURSORLEFT 75 +#define SCANCODE_KEYPAD5 76 +#define SCANCODE_KEYPAD6 77 +#define SCANCODE_CURSORRIGHT 77 +#define SCANCODE_KEYPADPLUS 78 +#define SCANCODE_KEYPAD1 79 +#define SCANCODE_CURSORDOWNLEFT 79 +#define SCANCODE_KEYPAD2 80 +#define SCANCODE_CURSORDOWN 80 +#define SCANCODE_KEYPAD3 81 +#define SCANCODE_CURSORDOWNRIGHT 81 +#define SCANCODE_KEYPAD0 82 +#define SCANCODE_KEYPADPERIOD 83 + +#define SCANCODE_LESS 86 + +#define SCANCODE_F11 87 +#define SCANCODE_F12 88 + +#define SCANCODE_KEYPADENTER 96 +#define SCANCODE_RIGHTCONTROL 97 +#define SCANCODE_CONTROL 97 +#define SCANCODE_KEYPADDIVIDE 98 +#define SCANCODE_PRINTSCREEN 99 +#define SCANCODE_RIGHTALT 100 +#define SCANCODE_BREAK 101 /* Beware: is 119 */ +#define SCANCODE_BREAK_ALTERNATIVE 119 /* on some keyboards! */ + +#define SCANCODE_HOME 102 +#define SCANCODE_CURSORBLOCKUP 103 /* Cursor key block */ +#define SCANCODE_PAGEUP 104 +#define SCANCODE_CURSORBLOCKLEFT 105 /* Cursor key block */ +#define SCANCODE_CURSORBLOCKRIGHT 106 /* Cursor key block */ +#define SCANCODE_END 107 +#define SCANCODE_CURSORBLOCKDOWN 108 /* Cursor key block */ +#define SCANCODE_PAGEDOWN 109 +#define SCANCODE_INSERT 110 +#define SCANCODE_REMOVE 111 + +#define SCANCODE_RIGHTWIN 126 +#define SCANCODE_LEFTWIN 125 + diff --git a/3rdparty/SDL/src/video/ps2gs/SDL_gsmouse.c b/3rdparty/SDL/src/video/ps2gs/SDL_gsmouse.c new file mode 100644 index 0000000..e0d320d --- /dev/null +++ b/3rdparty/SDL/src/video/ps2gs/SDL_gsmouse.c @@ -0,0 +1,146 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#include <sys/ioctl.h> + +#include "SDL_mouse.h" +#include "../../events/SDL_events_c.h" +#include "../SDL_cursor_c.h" +#include "SDL_gsvideo.h" +#include "SDL_gsmouse_c.h" + + +/* The implementation dependent data for the window manager cursor */ +struct WMcursor { + int unused; +}; + +/* There isn't any implementation dependent data */ +void GS_FreeWMCursor(_THIS, WMcursor *cursor) +{ + return; +} + +/* There isn't any implementation dependent data */ +WMcursor *GS_CreateWMCursor(_THIS, + Uint8 *data, Uint8 *mask, int w, int h, int hot_x, int hot_y) +{ + return((WMcursor *)0x01); +} + +static void GS_MoveCursor(_THIS, SDL_Cursor *cursor, int x, int y) +{ + SDL_Surface *screen; + struct ps2_image image; + SDL_Rect area; + int mouse_y1, mouse_y2; + void *saved_pixels; + int screen_updated; + + /* Lock so we don't interrupt an update with mouse motion */ + SDL_LockCursor(); + + /* Make sure any pending DMA has completed */ + if ( dma_pending ) { + ioctl(console_fd, PS2IOC_SENDQCT, 1); + dma_pending = 0; + } + + /* Remove the cursor image from the DMA area */ + screen = this->screen; + saved_pixels = screen->pixels; + screen->pixels = mapped_mem + screen->offset; + screen_updated = 0; + if ( cursor_drawn ) { + SDL_EraseCursorNoLock(screen); + cursor_drawn = 0; + screen_updated = 1; + } + + /* Save the current mouse area */ + SDL_MouseRect(&area); + mouse_y1 = area.y; + mouse_y2 = area.y+area.h; + + /* Only draw the new cursor if there was one passed in */ + if ( cursor ) { + /* Set the new location */ + cursor->area.x = (x - cursor->hot_x); + cursor->area.y = (y - cursor->hot_y); + + /* Draw the cursor at the new location */ + if ( (SDL_cursorstate & CURSOR_VISIBLE) && screen->pixels ) { + SDL_DrawCursorNoLock(screen); + cursor_drawn = 1; + screen_updated = 1; + } + } + screen->pixels = saved_pixels; + + /* Update the affected area of the screen */ + if ( screen_updated ) { + SDL_MouseRect(&area); + if ( area.y < mouse_y1 ) { + mouse_y1 = area.y; + } + if ( (area.y+area.h) > mouse_y2 ) { + mouse_y2 = area.y+area.h; + } + image = screen_image; + image.y += screen->offset / screen->pitch + mouse_y1; + image.h = mouse_y2 - mouse_y1; + image.ptr = mapped_mem + + (image.y - screen_image.y) * screen->pitch; + ioctl(console_fd, PS2IOC_LOADIMAGE, &image); + + /* Need to scale offscreen image to TV output */ + if ( image.y > 0 ) { + scaleimage_nonblock(console_fd, + tex_tags_mem, scale_tags_mem); + } + } + + /* We're finished */ + SDL_UnlockCursor(); +} + +void GS_MoveWMCursor(_THIS, int x, int y) +{ + GS_MoveCursor(this, SDL_cursor, x, y); +} + +int GS_ShowWMCursor(_THIS, WMcursor *wmcursor) +{ + SDL_Cursor *cursor; + int x, y; + + /* Draw the cursor at the appropriate location */ + SDL_GetMouseState(&x, &y); + if ( wmcursor ) { + cursor = SDL_cursor; + } else { + cursor = NULL; + } + GS_MoveCursor(this, cursor, x, y); + return(1); +} diff --git a/3rdparty/SDL/src/video/ps2gs/SDL_gsmouse_c.h b/3rdparty/SDL/src/video/ps2gs/SDL_gsmouse_c.h new file mode 100644 index 0000000..c507ed4 --- /dev/null +++ b/3rdparty/SDL/src/video/ps2gs/SDL_gsmouse_c.h @@ -0,0 +1,37 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#include "SDL_gsvideo.h" + +/* This is the maximum size of the cursor sprite */ +#define CURSOR_W 32 +#define CURSOR_H 32 +#define CURSOR_W_POW 5 /* 32 = 2^5 */ +#define CURSOR_H_POW 5 /* 32 = 2^5 */ + +/* Functions to be exported */ +extern void GS_FreeWMCursor(_THIS, WMcursor *cursor); +extern WMcursor *GS_CreateWMCursor(_THIS, + Uint8 *data, Uint8 *mask, int w, int h, int hot_x, int hot_y); +extern void GS_MoveWMCursor(_THIS, int x, int y); +extern int GS_ShowWMCursor(_THIS, WMcursor *cursor); diff --git a/3rdparty/SDL/src/video/ps2gs/SDL_gsvideo.c b/3rdparty/SDL/src/video/ps2gs/SDL_gsvideo.c new file mode 100644 index 0000000..e172c60 --- /dev/null +++ b/3rdparty/SDL/src/video/ps2gs/SDL_gsvideo.c @@ -0,0 +1,689 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* Framebuffer console based SDL video driver implementation. +*/ + +#include <fcntl.h> +#include <unistd.h> +#include <sys/ioctl.h> +#include <sys/mman.h> + +#include "SDL_video.h" +#include "SDL_mouse.h" +#include "../SDL_sysvideo.h" +#include "../SDL_pixels_c.h" +#include "../../events/SDL_events_c.h" +#include "../SDL_cursor_c.h" +#include "SDL_gsvideo.h" +#include "SDL_gsmouse_c.h" +#include "SDL_gsevents_c.h" +#include "SDL_gsyuv_c.h" + + +/* Initialization/Query functions */ +static int GS_VideoInit(_THIS, SDL_PixelFormat *vformat); +static SDL_Rect **GS_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags); +static SDL_Surface *GS_SetVideoMode(_THIS, SDL_Surface *current, int width, int height, int bpp, Uint32 flags); +static int GS_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors); +static void GS_VideoQuit(_THIS); + +/* Hardware surface functions */ +static int GS_AllocHWSurface(_THIS, SDL_Surface *surface); +static int GS_LockHWSurface(_THIS, SDL_Surface *surface); +static void GS_UnlockHWSurface(_THIS, SDL_Surface *surface); +static void GS_FreeHWSurface(_THIS, SDL_Surface *surface); + +/* GS driver bootstrap functions */ + +static int GS_Available(void) +{ + int console, memory; + + console = open(PS2_DEV_GS, O_RDWR, 0); + if ( console >= 0 ) { + close(console); + } + memory = open(PS2_DEV_MEM, O_RDWR, 0); + if ( memory >= 0 ) { + close(memory); + } + return((console >= 0) && (memory >= 0)); +} + +static void GS_DeleteDevice(SDL_VideoDevice *device) +{ + SDL_free(device->hidden); + SDL_free(device); +} + +static SDL_VideoDevice *GS_CreateDevice(int devindex) +{ + SDL_VideoDevice *this; + + /* Initialize all variables that we clean on shutdown */ + this = (SDL_VideoDevice *)SDL_malloc(sizeof(SDL_VideoDevice)); + if ( this ) { + SDL_memset(this, 0, (sizeof *this)); + this->hidden = (struct SDL_PrivateVideoData *) + SDL_malloc((sizeof *this->hidden)); + } + if ( (this == NULL) || (this->hidden == NULL) ) { + SDL_OutOfMemory(); + if ( this ) { + SDL_free(this); + } + return(0); + } + SDL_memset(this->hidden, 0, (sizeof *this->hidden)); + mouse_fd = -1; + keyboard_fd = -1; + + /* Set the function pointers */ + this->VideoInit = GS_VideoInit; + this->ListModes = GS_ListModes; + this->SetVideoMode = GS_SetVideoMode; + this->CreateYUVOverlay = GS_CreateYUVOverlay; + this->SetColors = GS_SetColors; + this->UpdateRects = NULL; + this->VideoQuit = GS_VideoQuit; + this->AllocHWSurface = GS_AllocHWSurface; + this->CheckHWBlit = NULL; + this->FillHWRect = NULL; + this->SetHWColorKey = NULL; + this->SetHWAlpha = NULL; + this->LockHWSurface = GS_LockHWSurface; + this->UnlockHWSurface = GS_UnlockHWSurface; + this->FlipHWSurface = NULL; + this->FreeHWSurface = GS_FreeHWSurface; + this->SetIcon = NULL; + this->SetCaption = NULL; + this->GetWMInfo = NULL; + this->FreeWMCursor = GS_FreeWMCursor; + this->CreateWMCursor = GS_CreateWMCursor; + this->ShowWMCursor = GS_ShowWMCursor; + this->MoveWMCursor = GS_MoveWMCursor; + this->InitOSKeymap = GS_InitOSKeymap; + this->PumpEvents = GS_PumpEvents; + + this->free = GS_DeleteDevice; + + return this; +} + +VideoBootStrap PS2GS_bootstrap = { + "ps2gs", "PlayStation 2 Graphics Synthesizer", + GS_Available, GS_CreateDevice +}; + +/* These are the pixel formats for the 32, 24, and 16 bit video modes */ +static struct { + int bpp; + Uint32 r; + Uint32 g; + Uint32 b; +} GS_pixelmasks[] = { + { 32, 0x000000FF, /* RGB little-endian */ + 0x0000FF00, + 0x00FF0000 }, + { 24, 0x000000FF, /* RGB little-endian */ + 0x0000FF00, + 0x00FF0000 }, + { 16, 0x0000001f, /* RGB little-endian */ + 0x000003e0, + 0x00007c00 }, +}; +/* This is a mapping from SDL bytes-per-pixel to GS pixel format */ +static int GS_formatmap[] = { + -1, /* 0 bpp, not a legal value */ + -1, /* 8 bpp, not supported (yet?) */ + PS2_GS_PSMCT16, /* 16 bpp */ + PS2_GS_PSMCT24, /* 24 bpp */ + PS2_GS_PSMCT32 /* 32 bpp */ +}; + +static unsigned long long head_tags[] __attribute__((aligned(16))) = { + 4 | (1LL << 60), /* GIFtag */ + 0x0e, /* A+D */ + 0, /* 2 */ + PS2_GS_BITBLTBUF, + 0, /* 4 */ + PS2_GS_TRXPOS, + 0, /* 6 */ + PS2_GS_TRXREG, + 0, /* 8 */ + PS2_GS_TRXDIR +}; + +#define MAXIMG (32767 * 16) +#define MAXTAGS 8 + +static inline int loadimage_nonblock(int fd, struct ps2_image *image, int size, + unsigned long long *hm, + unsigned long long *im) +{ + struct ps2_plist plist; + struct ps2_packet packet[1 + MAXTAGS * 2]; + int isize; + int pnum, it, eop; + char *data; + + /* initialize the variables */ + data = (char *)image->ptr; + pnum = it = eop = 0; + plist.packet = packet; + + /* make BITBLT packet */ + packet[pnum].ptr = hm; + packet[pnum].len = sizeof(head_tags); + pnum++; + hm[2] = ((unsigned long long)image->fbp << 32) | + ((unsigned long long)image->fbw << 48) | + ((unsigned long long)image->psm << 56); + hm[4] = ((unsigned long long)image->x << 32) | + ((unsigned long long)image->y << 48); + hm[6] = (unsigned long long)image->w | + ((unsigned long long)image->h << 32); + + /* make image mode tags */ + while (!eop) { + isize = size > MAXIMG ? MAXIMG : size; + size -= isize; + eop = (size == 0); + + packet[pnum].ptr = &im[it]; + packet[pnum].len = sizeof(unsigned long long) * 2; + pnum++; + im[it++] = (isize >> 4) | (eop ? (1 << 15) : 0) | (2LL << 58); + im[it++] = 0; + + packet[pnum].ptr = (void *)data; + packet[pnum].len = isize; + pnum++; + data += isize; + } + plist.num = pnum; + + return ioctl(fd, PS2IOC_SENDL, &plist); +} + +static unsigned long long tex_tags[] __attribute__((aligned(16))) = { + 3 | (1LL << 60), /* GIFtag */ + 0x0e, /* A+D */ + 0, /* 2 */ + PS2_GS_TEX0_1, + (1 << 5) + (1 << 6), + PS2_GS_TEX1_1, + 0, + PS2_GS_TEXFLUSH +}; +static unsigned long long scale_tags[] __attribute__((aligned(16))) = { + 5 | (1LL << 60), /* GIFtag */ + 0x0e, /* A+D */ + 6 + (1 << 4) + (1 << 8), + PS2_GS_PRIM, + ((unsigned long long)0 * 16) + (((unsigned long long)0 * 16) << 16), + PS2_GS_UV, + ((unsigned long long)0 * 16) + (((unsigned long long)0 * 16) << 16), + PS2_GS_XYZ2, + 0, /* 8 */ + PS2_GS_UV, + 0, /* 10 */ + PS2_GS_XYZ2 +}; + + +int scaleimage_nonblock(int fd, unsigned long long *tm, unsigned long long *sm) +{ + struct ps2_plist plist; + struct ps2_packet packet[2]; + + /* initialize the variables */ + plist.num = 2; + plist.packet = packet; + + packet[0].ptr = tm; + packet[0].len = sizeof(tex_tags); + packet[1].ptr = sm; + packet[1].len = sizeof(scale_tags); + + return ioctl(fd, PS2IOC_SENDL, &plist); +} + +static int power_of_2(int value) +{ + int shift; + + for ( shift = 0; (1<<shift) < value; ++shift ) { + /* Keep looking */ ; + } + return(shift); +} + +static int GS_VideoInit(_THIS, SDL_PixelFormat *vformat) +{ + struct ps2_screeninfo vinfo; + + /* Initialize the library */ + console_fd = open(PS2_DEV_GS, O_RDWR, 0); + if ( console_fd < 0 ) { + SDL_SetError("Unable to open %s", PS2_DEV_GS); + return(-1); + } + memory_fd = open(PS2_DEV_MEM, O_RDWR, 0); + if ( memory_fd < 0 ) { + close(console_fd); + console_fd = -1; + SDL_SetError("Unable to open %s", PS2_DEV_MEM); + return(-1); + } + + if ( ioctl(console_fd, PS2IOC_GSCREENINFO, &vinfo) < 0 ) { + close(memory_fd); + close(console_fd); + console_fd = -1; + SDL_SetError("Couldn't get console pixel format"); + return(-1); + } + + /* Determine the current screen size */ + this->info.current_w = vinfo.w; + this->info.current_h = vinfo.h; + + /* Determine the current screen depth */ + switch (vinfo.psm) { + /* Supported pixel formats */ + case PS2_GS_PSMCT32: + case PS2_GS_PSMCT24: + case PS2_GS_PSMCT16: + break; + default: + GS_VideoQuit(this); + SDL_SetError("Unknown console pixel format: %d", vinfo.psm); + return(-1); + } + vformat->BitsPerPixel = GS_pixelmasks[vinfo.psm].bpp; + vformat->Rmask = GS_pixelmasks[vinfo.psm].r; + vformat->Gmask = GS_pixelmasks[vinfo.psm].g; + vformat->Bmask = GS_pixelmasks[vinfo.psm].b; + saved_vinfo = vinfo; + + /* Enable mouse and keyboard support */ + if ( GS_OpenKeyboard(this) < 0 ) { + GS_VideoQuit(this); + SDL_SetError("Unable to open keyboard"); + return(-1); + } + if ( GS_OpenMouse(this) < 0 ) { + const char *sdl_nomouse; + + sdl_nomouse = SDL_getenv("SDL_NOMOUSE"); + if ( ! sdl_nomouse ) { + GS_VideoQuit(this); + SDL_SetError("Unable to open mouse"); + return(-1); + } + } + + /* We're done! */ + return(0); +} + +static SDL_Rect **GS_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags) +{ + static SDL_Rect GS_vesa_mode_list[] = { + { 0, 0, 1280, 1024 }, + { 0, 0, 1024, 768 }, + { 0, 0, 800, 600 }, + { 0, 0, 640, 480 } + }; + static SDL_Rect *GS_vesa_modes[] = { + &GS_vesa_mode_list[0], + &GS_vesa_mode_list[1], + &GS_vesa_mode_list[2], + &GS_vesa_mode_list[3], + NULL + }; + static SDL_Rect GS_tvout_stretch; + static SDL_Rect GS_tvout_mode; + static SDL_Rect *GS_tvout_modes[3]; + SDL_Rect **modes = NULL; + + switch (format->BitsPerPixel) { + case 16: + case 24: + case 32: + if ( saved_vinfo.mode == PS2_GS_VESA ) { + modes = GS_vesa_modes; + } else { + int i, j = 0; + +// FIXME - what's wrong with the stretch code at 16 bpp? +if ( format->BitsPerPixel != 32 ) break; + /* Add a mode that we could possibly stretch to */ + for ( i=0; GS_vesa_modes[i]; ++i ) { + if ( (GS_vesa_modes[i]->w == saved_vinfo.w) && + (GS_vesa_modes[i]->h != saved_vinfo.h) ) { + GS_tvout_stretch.w=GS_vesa_modes[i]->w; + GS_tvout_stretch.h=GS_vesa_modes[i]->h; + GS_tvout_modes[j++] = &GS_tvout_stretch; + break; + } + } + /* Add the current TV video mode */ + GS_tvout_mode.w = saved_vinfo.w; + GS_tvout_mode.h = saved_vinfo.h; + GS_tvout_modes[j++] = &GS_tvout_mode; + GS_tvout_modes[j++] = NULL; + + /* Return the created list of modes */ + modes = GS_tvout_modes; + } + break; + default: + break; + } + return(modes); +} + +/* Various screen update functions available */ +static void GS_DMAFullUpdate(_THIS, int numrects, SDL_Rect *rects); + +static SDL_Surface *GS_SetVideoMode(_THIS, SDL_Surface *current, + int width, int height, int bpp, Uint32 flags) +{ + struct ps2_screeninfo vinfo; + + /* Set the terminal into graphics mode */ + if ( GS_EnterGraphicsMode(this) < 0 ) { + return(NULL); + } + + /* Set the video mode and get the final screen format */ + if ( ioctl(console_fd, PS2IOC_GSCREENINFO, &vinfo) < 0 ) { + SDL_SetError("Couldn't get console screen info"); + return(NULL); + } + if ( (vinfo.w != width) || (vinfo.h != height) || + (GS_pixelmasks[vinfo.psm].bpp != bpp) ) { + /* If we're not in VESA mode, we have to scale resolution */ + if ( saved_vinfo.mode == PS2_GS_VESA ) { + switch (width) { + case 640: + vinfo.res = PS2_GS_640x480; + break; + case 800: + vinfo.res = PS2_GS_800x600; + break; + case 1024: + vinfo.res = PS2_GS_1024x768; + break; + case 1280: + vinfo.res = PS2_GS_1280x1024; + break; + default: + SDL_SetError("Unsupported resolution: %dx%d\n", + width, height); + return(NULL); + } + vinfo.res |= (PS2_GS_75Hz << 8); + vinfo.w = width; + vinfo.h = height; + } + vinfo.fbp = 0; + vinfo.psm = GS_formatmap[bpp/8]; + if ( vinfo.psm < 0 ) { + SDL_SetError("Unsupported depth: %d bpp\n", bpp); + return(NULL); + } + if ( ioctl(console_fd, PS2IOC_SSCREENINFO, &vinfo) < 0 ) { + SDL_SetError("Couldn't set console screen info"); + return(NULL); + } + + /* Unmap the previous DMA buffer */ + if ( mapped_mem ) { + munmap(mapped_mem, mapped_len); + mapped_mem = NULL; + } + } + if ( ! SDL_ReallocFormat(current, GS_pixelmasks[vinfo.psm].bpp, + GS_pixelmasks[vinfo.psm].r, + GS_pixelmasks[vinfo.psm].g, + GS_pixelmasks[vinfo.psm].b, 0) ) { + return(NULL); + } + + /* Set up the new mode framebuffer */ + current->flags = SDL_FULLSCREEN; + current->w = width; + current->h = height; + current->pitch = SDL_CalculatePitch(current); + + /* Memory map the DMA area for block memory transfer */ + if ( ! mapped_mem ) { + pixels_len = height * current->pitch; + mapped_len = pixels_len + + /* Screen update DMA command area */ + sizeof(head_tags) + ((2 * MAXTAGS) * 16); + if ( saved_vinfo.mode != PS2_GS_VESA ) { + mapped_len += sizeof(tex_tags) + sizeof(scale_tags); + } + mapped_mem = mmap(0, mapped_len, PROT_READ|PROT_WRITE, + MAP_SHARED, memory_fd, 0); + if ( mapped_mem == MAP_FAILED ) { + SDL_SetError("Unable to map %d bytes for DMA", + mapped_len); + mapped_mem = NULL; + return(NULL); + } + + /* Set up the entire screen for DMA transfer */ + screen_image.ptr = mapped_mem; + screen_image.fbp = 0; + screen_image.fbw = (vinfo.w + 63) / 64; + screen_image.psm = vinfo.psm; + screen_image.x = 0; + if ( vinfo.h == height ) { + screen_image.y = 0; + } else { + /* Put image offscreen and scale to screen height */ + screen_image.y = vinfo.h; + } + screen_image.w = current->w; + screen_image.h = current->h; + + /* get screen image data size (qword aligned) */ + screen_image_size = (screen_image.w * screen_image.h); + switch (screen_image.psm) { + case PS2_GS_PSMCT32: + screen_image_size *= 4; + break; + case PS2_GS_PSMCT24: + screen_image_size *= 3; + break; + case PS2_GS_PSMCT16: + screen_image_size *= 2; + break; + } + screen_image_size = (screen_image_size + 15) & ~15; + + /* Set up the memory for screen update DMA commands */ + head_tags_mem = (unsigned long long *) + (mapped_mem + pixels_len); + image_tags_mem = (unsigned long long *) + ((caddr_t)head_tags_mem + sizeof(head_tags)); + SDL_memcpy(head_tags_mem, head_tags, sizeof(head_tags)); + if ( saved_vinfo.mode != PS2_GS_VESA ) { + tex_tags_mem = (unsigned long long *) + ((caddr_t)image_tags_mem + ((2*MAXTAGS)*16)); + scale_tags_mem = (unsigned long long *) + ((caddr_t)tex_tags_mem + sizeof(tex_tags)); + SDL_memcpy(tex_tags_mem, tex_tags, sizeof(tex_tags)); + tex_tags_mem[2] = + (vinfo.h * vinfo.w) / 64 + + ((unsigned long long)screen_image.fbw << 14) + + ((unsigned long long)screen_image.psm << 20) + + ((unsigned long long)power_of_2(screen_image.w) << 26) + + ((unsigned long long)power_of_2(screen_image.h) << 30) + + ((unsigned long long)1 << 34) + + ((unsigned long long)1 << 35); + SDL_memcpy(scale_tags_mem, scale_tags, sizeof(scale_tags)); + scale_tags_mem[8] = + ((unsigned long long)screen_image.w * 16) + + (((unsigned long long)screen_image.h * 16) << 16); + scale_tags_mem[10] = + ((unsigned long long)vinfo.w * 16) + + (((unsigned long long)vinfo.h * 16) << 16); + } + } + current->pixels = NULL; + if ( SDL_getenv("SDL_FULLSCREEN_UPDATE") ) { + /* Correct semantics */ + current->flags |= SDL_ASYNCBLIT; + } else { + /* We lie here - the screen memory isn't really the visible + display memory and still requires an update, but this + has the desired effect for most applications. + */ + current->flags |= SDL_HWSURFACE; + } + + /* Set the update rectangle function */ + this->UpdateRects = GS_DMAFullUpdate; + + /* We're done */ + return(current); +} + +/* We don't support hardware surfaces yet */ +static int GS_AllocHWSurface(_THIS, SDL_Surface *surface) +{ + return(-1); +} +static void GS_FreeHWSurface(_THIS, SDL_Surface *surface) +{ + return; +} +static int GS_LockHWSurface(_THIS, SDL_Surface *surface) +{ + if ( surface == this->screen ) { + /* Since mouse motion affects 'pixels', lock it */ + SDL_LockCursor(); + + /* Make sure any pending DMA has completed */ + if ( dma_pending ) { + ioctl(console_fd, PS2IOC_SENDQCT, 1); + dma_pending = 0; + } + + /* If the cursor is drawn on the DMA area, remove it */ + if ( cursor_drawn ) { + surface->pixels = mapped_mem + surface->offset; + SDL_EraseCursorNoLock(this->screen); + cursor_drawn = 0; + } + + /* Set the surface pixels to the base of the DMA area */ + surface->pixels = mapped_mem; + + /* We're finished! */ + SDL_UnlockCursor(); + } + return(0); +} +static void GS_UnlockHWSurface(_THIS, SDL_Surface *surface) +{ + if ( surface == this->screen ) { + /* Since mouse motion affects 'pixels', lock it */ + SDL_LockCursor(); + surface->pixels = NULL; + SDL_UnlockCursor(); + } +} + +static void GS_DMAFullUpdate(_THIS, int numrects, SDL_Rect *rects) +{ + /* Lock so we aren't interrupted by a mouse update */ + SDL_LockCursor(); + + /* Make sure any pending DMA has completed */ + if ( dma_pending ) { + ioctl(console_fd, PS2IOC_SENDQCT, 1); + dma_pending = 0; + } + + /* If the mouse is visible, draw it on the DMA area */ + if ( (SDL_cursorstate & CURSOR_VISIBLE) && !cursor_drawn ) { + this->screen->pixels = mapped_mem + this->screen->offset; + SDL_DrawCursorNoLock(this->screen); + this->screen->pixels = NULL; + cursor_drawn = 1; + } + + /* Put the image onto the screen */ + loadimage_nonblock(console_fd, + &screen_image, screen_image_size, + head_tags_mem, image_tags_mem); + if ( screen_image.y > 0 ) { + /* Need to scale offscreen image to TV output */ + ioctl(console_fd, PS2IOC_SENDQCT, 1); + dma_pending = 0; + scaleimage_nonblock(console_fd, tex_tags_mem, scale_tags_mem); + } else { + dma_pending = 1; + } + + /* We're finished! */ + SDL_UnlockCursor(); +} + +static int GS_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors) +{ + return(0); +} + +static void GS_VideoQuit(_THIS) +{ + /* Close console and input file descriptors */ + if ( console_fd > 0 ) { + /* Unmap the video framebuffer */ + if ( mapped_mem ) { + /* Unmap the video framebuffer */ + munmap(mapped_mem, mapped_len); + mapped_mem = NULL; + } + close(memory_fd); + + /* Restore the original video mode */ + if ( GS_InGraphicsMode(this) ) { + ioctl(console_fd, PS2IOC_SSCREENINFO, &saved_vinfo); + } + + /* We're all done with the graphics device */ + close(console_fd); + console_fd = -1; + } + GS_CloseMouse(this); + GS_CloseKeyboard(this); +} diff --git a/3rdparty/SDL/src/video/ps2gs/SDL_gsvideo.h b/3rdparty/SDL/src/video/ps2gs/SDL_gsvideo.h new file mode 100644 index 0000000..8972d70 --- /dev/null +++ b/3rdparty/SDL/src/video/ps2gs/SDL_gsvideo.h @@ -0,0 +1,95 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#ifndef _SDL_gsvideo_h +#define _SDL_gsvideo_h + +#include <sys/types.h> +#include <termios.h> +#include <linux/ps2/dev.h> +#include <linux/ps2/gs.h> + +#include "SDL_mouse.h" +#include "SDL_mutex.h" +#include "../SDL_sysvideo.h" + +/* Hidden "this" pointer for the video functions */ +#define _THIS SDL_VideoDevice *this + + +/* Private display data */ +struct SDL_PrivateVideoData { + /* Gotta love that simple PS2 graphics interface. :) */ + int console_fd; + int memory_fd; + struct ps2_screeninfo saved_vinfo; + + /* Ye olde linux keyboard code */ + int current_vt; + int saved_vt; + int keyboard_fd; + int saved_kbd_mode; + struct termios saved_kbd_termios; + + /* Ye olde linux mouse code */ + int mouse_fd; + int cursor_drawn; + + /* The memory mapped DMA area and associated variables */ + caddr_t mapped_mem; + int pixels_len; + int mapped_len; + struct ps2_image screen_image; + int screen_image_size; + unsigned long long *head_tags_mem; + unsigned long long *image_tags_mem; + unsigned long long *tex_tags_mem; + unsigned long long *scale_tags_mem; + int dma_pending; +}; +/* Old variable names */ +#define console_fd (this->hidden->console_fd) +#define memory_fd (this->hidden->memory_fd) +#define saved_vinfo (this->hidden->saved_vinfo) +#define current_vt (this->hidden->current_vt) +#define saved_vt (this->hidden->saved_vt) +#define keyboard_fd (this->hidden->keyboard_fd) +#define saved_kbd_mode (this->hidden->saved_kbd_mode) +#define saved_kbd_termios (this->hidden->saved_kbd_termios) +#define mouse_fd (this->hidden->mouse_fd) +#define cursor_drawn (this->hidden->cursor_drawn) +#define mapped_mem (this->hidden->mapped_mem) +#define pixels_len (this->hidden->pixels_len) +#define mapped_len (this->hidden->mapped_len) +#define screen_image (this->hidden->screen_image) +#define screen_image_size (this->hidden->screen_image_size) +#define head_tags_mem (this->hidden->head_tags_mem) +#define image_tags_mem (this->hidden->image_tags_mem) +#define tex_tags_mem (this->hidden->tex_tags_mem) +#define scale_tags_mem (this->hidden->scale_tags_mem) +#define dma_pending (this->hidden->dma_pending) + +/* Shared between the mouse and video code for screen update scaling */ +extern int scaleimage_nonblock(int fd, + unsigned long long *tm, unsigned long long *sm); +#endif /* _SDL_gsvideo_h */ diff --git a/3rdparty/SDL/src/video/ps2gs/SDL_gsyuv.c b/3rdparty/SDL/src/video/ps2gs/SDL_gsyuv.c new file mode 100644 index 0000000..ec52a69 --- /dev/null +++ b/3rdparty/SDL/src/video/ps2gs/SDL_gsyuv.c @@ -0,0 +1,461 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* This is the Playstation 2 implementation of YUV video overlays */ + +#include <fcntl.h> +#include <unistd.h> +#include <sys/ioctl.h> +#include <sys/mman.h> +#include <asm/page.h> /* For definition of PAGE_SIZE */ + +#include "SDL_video.h" +#include "SDL_gsyuv_c.h" +#include "../SDL_yuvfuncs.h" + +/* The maximum number of 16x16 pixel block converted at once */ +#define MAX_MACROBLOCKS 1024 /* 2^10 macroblocks at once */ + +/* The functions used to manipulate video overlays */ +static struct private_yuvhwfuncs gs_yuvfuncs = { + GS_LockYUVOverlay, + GS_UnlockYUVOverlay, + GS_DisplayYUVOverlay, + GS_FreeYUVOverlay +}; + +struct private_yuvhwdata { + int ipu_fd; + Uint8 *pixels; + int macroblocks; + int dma_len; + caddr_t dma_mem; + caddr_t ipu_imem; + caddr_t ipu_omem; + caddr_t dma_tags; + unsigned long long *stretch_x1y1; + unsigned long long *stretch_x2y2; + struct ps2_plist plist; + + /* These are just so we don't have to allocate them separately */ + Uint16 pitches[3]; + Uint8 *planes[3]; +}; + +static int power_of_2(int value) +{ + int shift; + + for ( shift = 0; (1<<shift) < value; ++shift ) { + /* Keep looking */ ; + } + return(shift); +} + +SDL_Overlay *GS_CreateYUVOverlay(_THIS, int width, int height, Uint32 format, SDL_Surface *display) +{ + SDL_Overlay *overlay; + struct private_yuvhwdata *hwdata; + int map_offset; + unsigned long long *tags; + caddr_t base; + int bpp; + int fbp, fbw, psm; + int x, y, w, h; + int pnum; + struct ps2_packet *packet; + struct ps2_packet tex_packet; + + /* We can only decode blocks of 16x16 pixels */ + if ( (width & 15) || (height & 15) ) { + SDL_SetError("Overlay width/height must be multiples of 16"); + return(NULL); + } + /* Make sure the image isn't too large for a single DMA transfer */ + if ( ((width/16) * (height/16)) > MAX_MACROBLOCKS ) { + SDL_SetError("Overlay too large (maximum size: %d pixels)", + MAX_MACROBLOCKS * 16 * 16); + return(NULL); + } + + /* Double-check the requested format. For simplicity, we'll only + support planar YUV formats. + */ + switch (format) { + case SDL_YV12_OVERLAY: + case SDL_IYUV_OVERLAY: + /* Supported planar YUV format */ + break; + default: + SDL_SetError("Unsupported YUV format"); + return(NULL); + } + + /* Create the overlay structure */ + overlay = (SDL_Overlay *)SDL_malloc(sizeof *overlay); + if ( overlay == NULL ) { + SDL_OutOfMemory(); + return(NULL); + } + SDL_memset(overlay, 0, (sizeof *overlay)); + + /* Fill in the basic members */ + overlay->format = format; + overlay->w = width; + overlay->h = height; + + /* Set up the YUV surface function structure */ + overlay->hwfuncs = &gs_yuvfuncs; + overlay->hw_overlay = 1; + + /* Create the pixel data */ + hwdata = (struct private_yuvhwdata *)SDL_malloc(sizeof *hwdata); + overlay->hwdata = hwdata; + if ( hwdata == NULL ) { + SDL_FreeYUVOverlay(overlay); + SDL_OutOfMemory(); + return(NULL); + } + hwdata->ipu_fd = -1; + hwdata->pixels = (Uint8 *)SDL_malloc(width*height*2); + if ( hwdata->pixels == NULL ) { + SDL_FreeYUVOverlay(overlay); + SDL_OutOfMemory(); + return(NULL); + } + hwdata->macroblocks = (width/16) * (height/16); + + /* Find the pitch and offset values for the overlay */ + overlay->pitches = hwdata->pitches; + overlay->pixels = hwdata->planes; + switch (format) { + case SDL_YV12_OVERLAY: + case SDL_IYUV_OVERLAY: + overlay->pitches[0] = overlay->w; + overlay->pitches[1] = overlay->pitches[0] / 2; + overlay->pitches[2] = overlay->pitches[0] / 2; + overlay->pixels[0] = hwdata->pixels; + overlay->pixels[1] = overlay->pixels[0] + + overlay->pitches[0] * overlay->h; + overlay->pixels[2] = overlay->pixels[1] + + overlay->pitches[1] * overlay->h / 2; + overlay->planes = 3; + break; + default: + /* We should never get here (caught above) */ + break; + } + + /* Theoretically we could support several concurrent decode + streams queueing up on the same file descriptor, but for + simplicity we'll support only one. Opening the IPU more + than once will fail with EBUSY. + */ + hwdata->ipu_fd = open("/dev/ps2ipu", O_RDWR); + if ( hwdata->ipu_fd < 0 ) { + SDL_FreeYUVOverlay(overlay); + SDL_SetError("Playstation 2 IPU busy"); + return(NULL); + } + + /* Allocate a DMA area for pixel conversion */ + bpp = this->screen->format->BytesPerPixel; + map_offset = (mapped_len + (sysconf(_SC_PAGESIZE) - 1)) & ~(sysconf(_SC_PAGESIZE) - 1); + hwdata->dma_len = hwdata->macroblocks * (16 * 16 + 8 * 8 + 8 * 8) + + width * height * bpp + + hwdata->macroblocks * (16 * sizeof(long long)) + + 12 * sizeof(long long); + hwdata->dma_mem = mmap(0, hwdata->dma_len, PROT_READ|PROT_WRITE, + MAP_SHARED, memory_fd, map_offset); + if ( hwdata->dma_mem == MAP_FAILED ) { + hwdata->ipu_imem = (caddr_t)0; + SDL_FreeYUVOverlay(overlay); + SDL_SetError("Unable to map %d bytes for DMA", hwdata->dma_len); + return(NULL); + } + hwdata->ipu_imem = hwdata->dma_mem; + hwdata->ipu_omem = hwdata->ipu_imem + + hwdata->macroblocks * (16 * 16 + 8 * 8 + 8 * 8); + hwdata->dma_tags = hwdata->ipu_omem + width * height * bpp; + + /* Allocate memory for the DMA packets */ + hwdata->plist.num = hwdata->macroblocks * 4 + 1; + hwdata->plist.packet = (struct ps2_packet *)SDL_malloc( + hwdata->plist.num*sizeof(struct ps2_packet)); + if ( ! hwdata->plist.packet ) { + SDL_FreeYUVOverlay(overlay); + SDL_OutOfMemory(); + return(NULL); + } + pnum = 0; + packet = hwdata->plist.packet; + + /* Set up the tags to send the image to the screen */ + tags = (unsigned long long *)hwdata->dma_tags; + base = hwdata->ipu_omem; + fbp = screen_image.fbp; + fbw = screen_image.fbw; + psm = screen_image.psm; + y = screen_image.y + screen_image.h; /* Offscreen video memory */ + for ( h=height/16; h; --h ) { + x = 0; /* Visible video memory */ + for ( w=width/16; w; --w ) { + /* The head tag */ + packet[pnum].ptr = &tags[0]; + packet[pnum].len = 10 * sizeof(*tags); + ++pnum; + tags[0] = 4 | (1LL << 60); /* GIFtag */ + tags[1] = 0x0e; /* A+D */ + tags[2] = ((unsigned long long)fbp << 32) | + ((unsigned long long)fbw << 48) | + ((unsigned long long)psm << 56); + tags[3] = PS2_GS_BITBLTBUF; + tags[4] = ((unsigned long long)x << 32) | + ((unsigned long long)y << 48); + tags[5] = PS2_GS_TRXPOS; + tags[6] = (unsigned long long)16 | + ((unsigned long long)16 << 32); + tags[7] = PS2_GS_TRXREG; + tags[8] = 0; + tags[9] = PS2_GS_TRXDIR; + /* Now the actual image data */ + packet[pnum].ptr = &tags[10]; + packet[pnum].len = 2 * sizeof(*tags); + ++pnum; + tags[10] = ((16*16*bpp) >> 4) | (2LL << 58); + tags[11] = 0; + packet[pnum].ptr = (void *)base; + packet[pnum].len = 16 * 16 * bpp; + ++pnum; + packet[pnum].ptr = &tags[12]; + packet[pnum].len = 2 * sizeof(*tags); + ++pnum; + tags[12] = (0 >> 4) | (1 << 15) | (2LL << 58); + tags[13] = 0; + + tags += 16; + base += 16 * 16 * bpp; + + x += 16; + } + y += 16; + } + + /* Set up the texture memory area for the video */ + tex_packet.ptr = tags; + tex_packet.len = 8 * sizeof(*tags); + tags[0] = 3 | (1LL << 60); /* GIFtag */ + tags[1] = 0x0e; /* A+D */ + tags[2] = ((screen_image.y + screen_image.h) * screen_image.w) / 64 + + ((unsigned long long)fbw << 14) + + ((unsigned long long)psm << 20) + + ((unsigned long long)power_of_2(width) << 26) + + ((unsigned long long)power_of_2(height) << 30) + + ((unsigned long long)1 << 34) + + ((unsigned long long)1 << 35); + tags[3] = PS2_GS_TEX0_1; + tags[4] = (1 << 5) + (1 << 6); + tags[5] = PS2_GS_TEX1_1; + tags[6] = 0; + tags[7] = PS2_GS_TEXFLUSH; + ioctl(console_fd, PS2IOC_SEND, &tex_packet); + + /* Set up the tags for scaling the image */ + packet[pnum].ptr = tags; + packet[pnum].len = 12 * sizeof(*tags); + ++pnum; + tags[0] = 5 | (1LL << 60); /* GIFtag */ + tags[1] = 0x0e; /* A+D */ + tags[2] = 6 + (1 << 4) + (1 << 8); + tags[3] = PS2_GS_PRIM; + tags[4] = ((unsigned long long)0 * 16) + + (((unsigned long long)0 * 16) << 16); + tags[5] = PS2_GS_UV; + tags[6] = 0; /* X1, Y1 */ + tags[7] = PS2_GS_XYZ2; + hwdata->stretch_x1y1 = &tags[6]; + tags[8] = ((unsigned long long)overlay->w * 16) + + (((unsigned long long)overlay->h * 16) << 16); + tags[9] = PS2_GS_UV; + tags[10] = 0; /* X2, Y2 */ + tags[11] = PS2_GS_XYZ2; + hwdata->stretch_x2y2 = &tags[10]; + + /* We're all done.. */ + return(overlay); +} + +int GS_LockYUVOverlay(_THIS, SDL_Overlay *overlay) +{ + return(0); +} + +void GS_UnlockYUVOverlay(_THIS, SDL_Overlay *overlay) +{ + return; +} + +int GS_DisplayYUVOverlay(_THIS, SDL_Overlay *overlay, SDL_Rect *src, SDL_Rect *dst) +{ + struct private_yuvhwdata *hwdata; + __u32 cmd; + struct ps2_packet packet; + int h, w, i; + Uint32 *lum, *Cr, *Cb; + int lum_pitch; + int crb_pitch; + Uint32 *lum_src, *Cr_src, *Cb_src; + Uint32 *srcp, *dstp; + unsigned int x, y; + SDL_Surface *screen; + + /* Find out where the various portions of the image are */ + hwdata = overlay->hwdata; + switch (overlay->format) { + case SDL_YV12_OVERLAY: + lum = (Uint32 *)overlay->pixels[0]; + Cr = (Uint32 *)overlay->pixels[1]; + Cb = (Uint32 *)overlay->pixels[2]; + break; + case SDL_IYUV_OVERLAY: + lum = (Uint32 *)overlay->pixels[0]; + Cr = (Uint32 *)overlay->pixels[2]; + Cb = (Uint32 *)overlay->pixels[1]; + default: + SDL_SetError("Unsupported YUV format in blit (?)"); + return(-1); + } + dstp = (Uint32 *)hwdata->ipu_imem; + lum_pitch = overlay->w/4; + crb_pitch = (overlay->w/2)/4; + + /* Copy blocks of 16x16 pixels to the DMA area */ + for ( h=overlay->h/16; h; --h ) { + lum_src = lum; + Cr_src = Cr; + Cb_src = Cb; + for ( w=overlay->w/16; w; --w ) { + srcp = lum_src; + for ( i=0; i<16; ++i ) { + dstp[0] = srcp[0]; + dstp[1] = srcp[1]; + dstp[2] = srcp[2]; + dstp[3] = srcp[3]; + srcp += lum_pitch; + dstp += 4; + } + srcp = Cb_src; + for ( i=0; i<8; ++i ) { + dstp[0] = srcp[0]; + dstp[1] = srcp[1]; + srcp += crb_pitch; + dstp += 2; + } + srcp = Cr_src; + for ( i=0; i<8; ++i ) { + dstp[0] = srcp[0]; + dstp[1] = srcp[1]; + srcp += crb_pitch; + dstp += 2; + } + lum_src += 16 / 4; + Cb_src += 8 / 4; + Cr_src += 8 / 4; + } + lum += lum_pitch * 16; + Cr += crb_pitch * 8; + Cb += crb_pitch * 8; + } + + /* Send the macroblock data to the IPU */ +#ifdef DEBUG_YUV + fprintf(stderr, "Sending data to IPU..\n"); +#endif + packet.ptr = hwdata->ipu_imem; + packet.len = hwdata->macroblocks * (16 * 16 + 8 * 8 + 8 * 8); + ioctl(hwdata->ipu_fd, PS2IOC_SENDA, &packet); + + /* Trigger the DMA to the IPU for conversion */ +#ifdef DEBUG_YUV + fprintf(stderr, "Trigging conversion command\n"); +#endif + cmd = (7 << 28) + hwdata->macroblocks; + if ( screen_image.psm == PS2_GS_PSMCT16 ) { + cmd += (1 << 27) + /* Output RGB 555 */ + (1 << 26); /* Dither output */ + } + ioctl(hwdata->ipu_fd, PS2IOC_SIPUCMD, &cmd); + + /* Retrieve the converted image from the IPU */ +#ifdef DEBUG_YUV + fprintf(stderr, "Retrieving data from IPU..\n"); +#endif + packet.ptr = hwdata->ipu_omem; + packet.len = overlay->w * overlay->h * + this->screen->format->BytesPerPixel; + ioctl(hwdata->ipu_fd, PS2IOC_RECV, &packet); + +#ifdef DEBUG_YUV + fprintf(stderr, "Copying image to screen..\n"); +#endif + /* Wait for previous DMA to complete */ + ioctl(console_fd, PS2IOC_SENDQCT, 1); + + /* Send the current image to the screen and scale it */ + screen = this->screen; + x = (unsigned int)dst->x; + y = (unsigned int)dst->y; + if ( screen->offset ) { + x += (screen->offset % screen->pitch) / + screen->format->BytesPerPixel; + y += (screen->offset / screen->pitch); + } + y += screen_image.y; + *hwdata->stretch_x1y1 = (x * 16) + ((y * 16) << 16); + x += (unsigned int)dst->w; + y += (unsigned int)dst->h; + *hwdata->stretch_x2y2 = (x * 16) + ((y * 16) << 16); + return ioctl(console_fd, PS2IOC_SENDL, &hwdata->plist); +} + +void GS_FreeYUVOverlay(_THIS, SDL_Overlay *overlay) +{ + struct private_yuvhwdata *hwdata; + + hwdata = overlay->hwdata; + if ( hwdata ) { + if ( hwdata->ipu_fd >= 0 ) { + close(hwdata->ipu_fd); + } + if ( hwdata->dma_mem ) { + munmap(hwdata->dma_mem, hwdata->dma_len); + } + if ( hwdata->plist.packet ) { + SDL_free(hwdata->plist.packet); + } + if ( hwdata->pixels ) { + SDL_free(hwdata->pixels); + } + SDL_free(hwdata); + } +} diff --git a/3rdparty/SDL/src/video/ps2gs/SDL_gsyuv_c.h b/3rdparty/SDL/src/video/ps2gs/SDL_gsyuv_c.h new file mode 100644 index 0000000..d9ffad6 --- /dev/null +++ b/3rdparty/SDL/src/video/ps2gs/SDL_gsyuv_c.h @@ -0,0 +1,37 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* This is the Playstation 2 implementation of YUV video overlays */ + +#include "SDL_video.h" +#include "SDL_gsvideo.h" + +extern SDL_Overlay *GS_CreateYUVOverlay(_THIS, int width, int height, Uint32 format, SDL_Surface *display); + +extern int GS_LockYUVOverlay(_THIS, SDL_Overlay *overlay); + +extern void GS_UnlockYUVOverlay(_THIS, SDL_Overlay *overlay); + +extern int GS_DisplayYUVOverlay(_THIS, SDL_Overlay *overlay, SDL_Rect *src, SDL_Rect *dst); + +extern void GS_FreeYUVOverlay(_THIS, SDL_Overlay *overlay); diff --git a/3rdparty/SDL/src/video/ps3/SDL_ps3events.c b/3rdparty/SDL/src/video/ps3/SDL_ps3events.c new file mode 100644 index 0000000..e39efcc --- /dev/null +++ b/3rdparty/SDL/src/video/ps3/SDL_ps3events.c @@ -0,0 +1,44 @@ +/* + * SDL - Simple DirectMedia Layer + * CELL BE Support for PS3 Framebuffer + * Copyright (C) 2008, 2009 International Business Machines Corporation + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 + * USA + * + * Martin Lowinski <lowinski [at] de [dot] ibm [ibm] com> + * Dirk Herrendoerfer <d.herrendoerfer [at] de [dot] ibm [dot] com> + * SPE code based on research by: + * Rene Becker + * Thimo Emmerich + */ + +#include "SDL_config.h" + +#include "../../events/SDL_sysevents.h" +#include "../../events/SDL_events_c.h" +#include "SDL_ps3video.h" +#include "SDL_ps3events_c.h" + +void PS3_PumpEvents(_THIS) +{ + return; +} + +void PS3_InitOSKeymap(_THIS) +{ + return; +} + diff --git a/3rdparty/SDL/src/video/ps3/SDL_ps3events_c.h b/3rdparty/SDL/src/video/ps3/SDL_ps3events_c.h new file mode 100644 index 0000000..fd11209 --- /dev/null +++ b/3rdparty/SDL/src/video/ps3/SDL_ps3events_c.h @@ -0,0 +1,41 @@ +/* + * SDL - Simple DirectMedia Layer + * CELL BE Support for PS3 Framebuffer + * Copyright (C) 2008, 2009 International Business Machines Corporation + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 + * USA + * + * Martin Lowinski <lowinski [at] de [dot] ibm [ibm] com> + * Dirk Herrendoerfer <d.herrendoerfer [at] de [dot] ibm [dot] com> + * SPE code based on research by: + * Rene Becker + * Thimo Emmerich + */ + +#include "SDL_config.h" + +#ifndef _SDL_ps3events_h +#define _SDL_ps3events_h + +#include "SDL_ps3video.h" + +extern void PS3_InitOSKeymap(_THIS); +extern void PS3_PumpEvents(_THIS); + +extern void enable_cursor(int enable); + +#endif /* _SDL_ps3events_h */ + diff --git a/3rdparty/SDL/src/video/ps3/SDL_ps3video.c b/3rdparty/SDL/src/video/ps3/SDL_ps3video.c new file mode 100644 index 0000000..d5519e0 --- /dev/null +++ b/3rdparty/SDL/src/video/ps3/SDL_ps3video.c @@ -0,0 +1,621 @@ +/* + * SDL - Simple DirectMedia Layer + * CELL BE Support for PS3 Framebuffer + * Copyright (C) 2008, 2009 International Business Machines Corporation + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 + * USA + * + * Martin Lowinski <lowinski [at] de [dot] ibm [ibm] com> + * Dirk Herrendoerfer <d.herrendoerfer [at] de [dot] ibm [dot] com> + * SPE code based on research by: + * Rene Becker + * Thimo Emmerich + */ + +#include "SDL_config.h" + +#include "SDL_video.h" +#include "../SDL_sysvideo.h" +#include "SDL_ps3events_c.h" +#include "SDL_ps3video.h" +#include "SDL_ps3yuv_c.h" +#include "spulibs/spu_common.h" + +#include <fcntl.h> +#include <stdlib.h> +#include <sys/ioctl.h> +#include <linux/kd.h> +#include <sys/mman.h> + +#include <linux/fb.h> +#include <asm/ps3fb.h> +#include <libspe2.h> +#include <malloc.h> + +/* SDL_VideoDevice functions */ +static int PS3_Available(); +static SDL_VideoDevice *PS3_CreateDevice(int devindex); +static int PS3_VideoInit(_THIS, SDL_PixelFormat * vformat); +static void PS3_VideoQuit(_THIS); +static void PS3_DeleteDevice(SDL_VideoDevice * device); +static SDL_Surface *PS3_SetVideoMode(_THIS, SDL_Surface * current, int width, int height, int bpp, Uint32 flags); +static SDL_Rect **PS3_ListModes(_THIS, SDL_PixelFormat * format, Uint32 flags); + +/* Hardware surface functions */ +static int PS3_AllocHWSurface(_THIS, SDL_Surface * surface); +static void PS3_FreeHWSurface(_THIS, SDL_Surface * surface); +static int PS3_LockHWSurface(_THIS, SDL_Surface * surface); +static void PS3_UnlockHWSurface(_THIS, SDL_Surface * surface); +static int PS3_FlipDoubleBuffer(_THIS, SDL_Surface * surface); +static void PS3_DoubleBufferUpdate(_THIS, int numrects, SDL_Rect * rects); + +/* SPU specific functions */ +int SPE_Start(_THIS, spu_data_t * spe_data); +int SPE_Stop(_THIS, spu_data_t * spe_data); +int SPE_Boot(_THIS, spu_data_t * spe_data); +int SPE_Shutdown(_THIS, spu_data_t * spe_data); +int SPE_SendMsg(_THIS, spu_data_t * spe_data, unsigned int msg); +int SPE_WaitForMsg(_THIS, spu_data_t * spe_data, unsigned int msg); +void SPE_RunContext(void *thread_argp); + +/* Helpers */ +void enable_cursor(int enable); + +/* Stores the SPE executable name of fb_writer_spu */ +extern spe_program_handle_t fb_writer_spu; + +/* SDL PS3 bootstrap function for checking availability */ +static int PS3_Available() +{ + return 1; +} + +/* SDL PS3 bootstrap function for creating the device */ +static SDL_VideoDevice *PS3_CreateDevice(int devindex) +{ + SDL_VideoDevice *this; + + /* Initialise SDL_VideoDevice */ + this = (SDL_VideoDevice *) SDL_malloc(sizeof(SDL_VideoDevice)); + if (this) { + memset(this, 0, sizeof *this); + this->hidden = (struct SDL_PrivateVideoData *) + SDL_malloc(sizeof(struct SDL_PrivateVideoData)); + } + /* Error handling */ + if ((this == NULL) || (this->hidden == NULL)) { + SDL_OutOfMemory(); + if (this) + SDL_free(this); + return 0; + } + memset(this->hidden, 0, sizeof(struct SDL_PrivateVideoData)); + + /* Set the function pointers */ + this->VideoInit = PS3_VideoInit; + this->ListModes = PS3_ListModes; + this->SetVideoMode = PS3_SetVideoMode; + this->SetColors = 0; + this->CreateYUVOverlay = PS3_CreateYUVOverlay; + this->UpdateRects = 0; + this->VideoQuit = PS3_VideoQuit; + this->AllocHWSurface = PS3_AllocHWSurface; + this->CheckHWBlit = 0; + this->FillHWRect = 0; + this->SetHWColorKey = 0; + this->SetHWAlpha = 0; + this->LockHWSurface = PS3_LockHWSurface; + this->UnlockHWSurface = PS3_UnlockHWSurface; + this->FlipHWSurface = PS3_FlipDoubleBuffer; + this->FreeHWSurface = PS3_FreeHWSurface; + this->SetCaption = 0; + this->SetIcon = 0; + this->IconifyWindow = 0; + this->GrabInput = 0; + this->GetWMInfo = 0; + this->InitOSKeymap = PS3_InitOSKeymap; + this->PumpEvents = PS3_PumpEvents; + + this->free = PS3_DeleteDevice; + + return this; +} + + +/* Bootstraping (see SDL_sysvideo.h) */ +VideoBootStrap PS3_bootstrap = { + "ps3", "PS3 Cell SPU Driver", + PS3_Available, PS3_CreateDevice +}; + + +/* Delete the device */ +static void PS3_DeleteDevice(SDL_VideoDevice * device) +{ + free(device->hidden); + free(device); +} + + +/* Initialise the PS3 video device */ +static int PS3_VideoInit(_THIS, SDL_PixelFormat * vformat) +{ + /* Hide the cursor */ + enable_cursor(0); + + /* Create SPU fb_parms and thread structure */ + fb_parms = (struct fb_writer_parms_t *) + memalign(16, sizeof(struct fb_writer_parms_t)); + fb_thread_data = (spu_data_t *) malloc(sizeof(spu_data_t)); + if (fb_parms == NULL || fb_thread_data == NULL) { + SDL_OutOfMemory(); + return -1; + } + fb_thread_data->program = fb_writer_spu; + fb_thread_data->program_name = "fb_writer_spu"; + fb_thread_data->argp = (void *)fb_parms; + fb_thread_data->keepalive = 1; + fb_thread_data->booted = 0; + + SPE_Start(this, fb_thread_data); + + /* Open the device */ + fb_dev_fd = open(PS3_DEV_FB, O_RDWR); + if (fb_dev_fd < 0) { + SDL_SetError("[PS3] Unable to open device %s", PS3_DEV_FB); + return -1; + } + + /* Get vscreeninfo */ + if (ioctl(fb_dev_fd, FBIOGET_VSCREENINFO, &fb_vinfo)) { + SDL_SetError("[PS3] Can't get VSCREENINFO"); + if (fb_dev_fd >= 0) + close(fb_dev_fd); + fb_dev_fd = -1; + return -1; + } + + /* Fill in our hardware acceleration capabilities */ + this->info.current_w = fb_vinfo.xres; + this->info.current_h = fb_vinfo.yres; + this->info.wm_available = 0; + this->info.hw_available = 1; + + /* Backup the original vinfo to restore later */ + fb_orig_vinfo = fb_vinfo; + + /* 16 and 15 bpp is reported as 16 bpp */ + fb_bits_per_pixel = fb_vinfo.bits_per_pixel; + if (fb_bits_per_pixel == 16) + fb_bits_per_pixel = + fb_vinfo.red.length + fb_vinfo.green.length + + fb_vinfo.blue.length; + + /* Set SDL_PixelFormat */ + vformat->BitsPerPixel = fb_vinfo.bits_per_pixel; + + fb_vinfo.xres_virtual = fb_vinfo.xres; + fb_vinfo.yres_virtual = fb_vinfo.yres; + + /* Put vscreeninfo */ + if (ioctl(fb_dev_fd, FBIOPUT_VSCREENINFO, &fb_vinfo)) { + SDL_SetError("[PS3] Can't put VSCREENINFO"); + if (fb_dev_fd >= 0) + close(fb_dev_fd); + fb_dev_fd = -1; + return -1; + } + + s_fb_pixel_size = fb_vinfo.bits_per_pixel / 8; + + s_writeable_width = fb_vinfo.xres; + s_writeable_height = fb_vinfo.yres; + + /* Get ps3 screeninfo */ + if (ioctl(fb_dev_fd, PS3FB_IOCTL_SCREENINFO, (unsigned long)&res) < 0) { + SDL_SetError("[PS3] PS3FB_IOCTL_SCREENINFO failed"); + } + deprintf(1, "[PS3] xres:%d yres:%d xoff:%d yoff:%d\n", res.xres, res.yres, res.xoff, res.yoff); + + /* Only use double buffering if enough fb memory is available */ + if (res.num_frames < 2) { + double_buffering = 0; + } else { + double_buffering = 1; + } + + real_width = res.xres; + real_height = res.yres; + + /* + * Take control of frame buffer from kernel, for details see + * http://felter.org/wesley/files/ps3/linux-20061110-docs/ApplicationProgrammingEnvironment.html + * kernel will no longer flip the screen itself + */ + ioctl(fb_dev_fd, PS3FB_IOCTL_ON, 0); + + /* Unblank screen */ + ioctl(fb_dev_fd, FBIOBLANK, 0); + + return 0; +} + + +/* List available PS3 resolutions */ +static SDL_Rect **PS3_ListModes(_THIS, SDL_PixelFormat * format, Uint32 flags) +{ + /* A list of video resolutions that we query for (sorted largest to + * smallest) + */ + static SDL_Rect PS3_resolutions[] = { + {0, 0, 1920, 1080}, // 1080p 16:9 HD + {0, 0, 1600, 1200}, // WUXGA + {0, 0, 1280, 1024}, // SXGA + {0, 0, 1280, 720}, // 720p 16:9 HD + {0, 0, 1024, 768}, // WXGA + {0, 0, 1024, 576}, // 576p 16:9 + {0, 0, 853, 480}, // 480p 16:9 + {0, 0, 720, 576}, // 576p 4:3 (PAL) + {0, 0, 720, 480}, // 480p 16:9 (NTSC) + }; + static SDL_Rect *PS3_modes[] = { + &PS3_resolutions[0], + &PS3_resolutions[1], + &PS3_resolutions[2], + &PS3_resolutions[3], + &PS3_resolutions[4], + &PS3_resolutions[5], + &PS3_resolutions[6], + &PS3_resolutions[7], + &PS3_resolutions[8], + NULL + }; + SDL_Rect **modes = PS3_modes; + + return modes; +} + + +/* Get a list of the available display modes */ +static SDL_Surface *PS3_SetVideoMode(_THIS, SDL_Surface * current, int width, int height, int bpp, Uint32 flags) +{ + s_bounded_input_width = width < s_writeable_width ? width : s_writeable_width; + s_bounded_input_height = height < s_writeable_height ? height : s_writeable_height; + s_bounded_input_width_offset = (s_writeable_width - s_bounded_input_width) >> 1; + s_bounded_input_height_offset = (s_writeable_height - s_bounded_input_height) >> 1; + s_input_line_length = width * s_fb_pixel_size; + + current->flags |= flags; + + if (ioctl(fb_dev_fd, FBIOGET_FSCREENINFO, &fb_finfo)) { + SDL_SetError("[PS3] Can't get fixed screeninfo"); + return NULL; + } + + if (fb_finfo.type != FB_TYPE_PACKED_PIXELS) { + SDL_SetError("[PS3] type %s not supported", + fb_finfo.type); + return NULL; + } + + /* Note: on PS3, fb_finfo.smem_len is enough for double buffering */ + if ((frame_buffer = + (uint8_t *) mmap(0, fb_finfo.smem_len, + PROT_READ | PROT_WRITE, MAP_SHARED, + fb_dev_fd, 0)) == (uint8_t *) - 1) { + SDL_SetError("[PS3] Can't mmap for %s", PS3_DEV_FB); + return NULL; + } else { + current->flags |= SDL_DOUBLEBUF; + } + if (!SDL_ReallocFormat(current, fb_bits_per_pixel, 0, 0, 0, 0)) { + return (NULL); + } + + /* Blank screen */ + memset(frame_buffer, 0x00, fb_finfo.smem_len); + + /* Centering */ + s_center[0] = + frame_buffer + s_bounded_input_width_offset * s_fb_pixel_size + + s_bounded_input_height_offset * fb_finfo.line_length; + s_center[1] = s_center[0] + real_height * fb_finfo.line_length; + s_center_index = 0; + + current->flags |= SDL_FULLSCREEN; + current->w = width; + current->h = height; + current->pitch = SDL_CalculatePitch(current); + + /* Alloc aligned mem for current->pixels */ + s_pixels = memalign(16, current->h * current->pitch); + current->pixels = (void *)s_pixels; + if (!current->pixels) { + SDL_OutOfMemory(); + return NULL; + } + + /* Set the update rectangle function */ + this->UpdateRects = PS3_DoubleBufferUpdate; + + return current; +} + + +/* Copy screen to framebuffer and flip */ +void PS3_DoubleBufferUpdate(_THIS, int numrects, SDL_Rect * rects) +{ + if (converter_thread_data && converter_thread_data->booted) + SPE_WaitForMsg(this, converter_thread_data, SPU_FIN); + + /* Adjust centering */ + s_bounded_input_width_offset = (s_writeable_width - s_bounded_input_width) >> 1; + s_bounded_input_height_offset = (s_writeable_height - s_bounded_input_height) >> 1; + s_center[0] = frame_buffer + s_bounded_input_width_offset * s_fb_pixel_size + + s_bounded_input_height_offset * fb_finfo.line_length; + s_center[1] = s_center[0] + real_height * fb_finfo.line_length; + + /* Set SPU parms for copying the surface to framebuffer */ + fb_parms->data = (unsigned char *)s_pixels; + fb_parms->center = s_center[s_center_index]; + fb_parms->out_line_stride = fb_finfo.line_length; + fb_parms->in_line_stride = s_input_line_length; + fb_parms->bounded_input_height = s_bounded_input_height; + fb_parms->bounded_input_width = s_bounded_input_width; + fb_parms->fb_pixel_size = s_fb_pixel_size; + + deprintf(3, "[PS3->SPU] fb_thread_data->argp = 0x%x\n", fb_thread_data->argp); + + /* Copying.. */ + SPE_SendMsg(this, fb_thread_data, SPU_START); + SPE_SendMsg(this, fb_thread_data, (unsigned int)fb_thread_data->argp); + + SPE_WaitForMsg(this, fb_thread_data, SPU_FIN); + + /* Flip the pages */ + if (double_buffering) + s_center_index = s_center_index ^ 0x01; + PS3_FlipDoubleBuffer(this, this->screen); +} + + +/* Enable/Disable cursor */ +void enable_cursor(int enable) +{ + int fd = open("/dev/console", O_RDWR | O_NONBLOCK); + if (fd >= 0) { + ioctl(fd, KDSETMODE, enable ? KD_TEXT : KD_GRAPHICS); + close(fd); + } +} + + +static int PS3_AllocHWSurface(_THIS, SDL_Surface * surface) +{ + return -1; +} + + +static void PS3_FreeHWSurface(_THIS, SDL_Surface * surface) +{ + return; +} + + +static int PS3_LockHWSurface(_THIS, SDL_Surface * surface) +{ + return 0; +} + + +static void PS3_UnlockHWSurface(_THIS, SDL_Surface * surface) +{ + return; +} + + +/* Blit/Flip buffer to the screen. Must be called after each frame! */ +int PS3_FlipDoubleBuffer(_THIS, SDL_Surface * surface) +{ + unsigned long crt = 0; + /* Wait for vsync */ + deprintf(1, "[PS3] Wait for vsync\n"); + ioctl(fb_dev_fd, FBIO_WAITFORVSYNC, &crt); + /* Page flip */ + deprintf(1, "[PS3] Page flip to buffer #%u 0x%x\n", s_center_index, s_center[s_center_index]); + ioctl(fb_dev_fd, PS3FB_IOCTL_FSEL, (unsigned long)&s_center_index); + return 1; +} + + +/* Start the SPE thread */ +int SPE_Start(_THIS, spu_data_t * spe_data) +{ + deprintf(2, "[PS3->SPU] Start SPE: %s\n", spe_data->program_name); + if (!(spe_data->booted)) + SPE_Boot(this, spe_data); + + /* To allow re-running of context, spe_ctx_entry has to be set before each call */ + spe_data->entry = SPE_DEFAULT_ENTRY; + spe_data->error_code = 0; + + /* Create SPE thread and run */ + deprintf(2, "[PS3->SPU] Create Thread: %s\n", spe_data->program_name); + if (pthread_create + (&spe_data->thread, NULL, (void *)&SPE_RunContext, (void *)spe_data)) { + deprintf(2, "[PS3->SPU] Could not create pthread for spe: %s\n", spe_data->program_name); + SDL_SetError("[PS3->SPU] Could not create pthread for spe"); + return -1; + } + + if (spe_data->keepalive) + SPE_WaitForMsg(this, spe_data, SPU_READY); +} + + +/* Stop the SPE thread */ +int SPE_Stop(_THIS, spu_data_t * spe_data) +{ + deprintf(2, "[PS3->SPU] Stop SPE: %s\n", spe_data->program_name); + /* Wait for SPE thread to complete */ + deprintf(2, "[PS3->SPU] Wait for SPE thread to complete: %s\n", spe_data->program_name); + if (pthread_join(spe_data->thread, NULL)) { + deprintf(2, "[PS3->SPU] Failed joining the thread: %s\n", spe_data->program_name); + SDL_SetError("[PS3->SPU] Failed joining the thread"); + return -1; + } + + return 0; +} + + +/* Create SPE context and load program */ +int SPE_Boot(_THIS, spu_data_t * spe_data) +{ + /* Create SPE context */ + deprintf(2, "[PS3->SPU] Create SPE Context: %s\n", spe_data->program_name); + spe_data->ctx = spe_context_create(0, NULL); + if (spe_data->ctx == NULL) { + deprintf(2, "[PS3->SPU] Failed creating SPE context: %s\n", spe_data->program_name); + SDL_SetError("[PS3->SPU] Failed creating SPE context"); + return -1; + } + + /* Load SPE object into SPE local store */ + deprintf(2, "[PS3->SPU] Load Program into SPE: %s\n", spe_data->program_name); + if (spe_program_load(spe_data->ctx, &spe_data->program)) { + deprintf(2, "[PS3->SPU] Failed loading program into SPE context: %s\n", spe_data->program_name); + SDL_SetError + ("[PS3->SPU] Failed loading program into SPE context"); + return -1; + } + spe_data->booted = 1; + deprintf(2, "[PS3->SPU] SPE boot successful\n"); + + return 0; +} + +/* (Stop and) shutdown the SPE */ +int SPE_Shutdown(_THIS, spu_data_t * spe_data) +{ + if (spe_data->keepalive && spe_data->booted) { + SPE_SendMsg(this, spe_data, SPU_EXIT); + SPE_Stop(this, spe_data); + } + + /* Destroy SPE context */ + deprintf(2, "[PS3->SPU] Destroy SPE context: %s\n", spe_data->program_name); + if (spe_context_destroy(spe_data->ctx)) { + deprintf(2, "[PS3->SPU] Failed destroying context: %s\n", spe_data->program_name); + SDL_SetError("[PS3->SPU] Failed destroying context"); + return -1; + } + deprintf(2, "[PS3->SPU] SPE shutdown successful: %s\n", spe_data->program_name); + return 0; +} + + +/* Send message to the SPE via mailboxe */ +int SPE_SendMsg(_THIS, spu_data_t * spe_data, unsigned int msg) +{ + deprintf(2, "[PS3->SPU] Sending message %u to %s\n", msg, spe_data->program_name); + /* Send one message, block until message was sent */ + unsigned int spe_in_mbox_msgs[1]; + spe_in_mbox_msgs[0] = msg; + int in_mbox_write = spe_in_mbox_write(spe_data->ctx, spe_in_mbox_msgs, 1, SPE_MBOX_ALL_BLOCKING); + + if (1 > in_mbox_write) { + deprintf(2, "[PS3->SPU] No message could be written to %s\n", spe_data->program_name); + SDL_SetError("[PS3->SPU] No message could be written"); + return -1; + } + return 0; +} + + +/* Read 1 message from SPE, block until at least 1 message was received */ +int SPE_WaitForMsg(_THIS, spu_data_t * spe_data, unsigned int msg) +{ + deprintf(2, "[PS3->SPU] Waiting for message from %s\n", spe_data->program_name); + unsigned int out_messages[1]; + while (!spe_out_mbox_status(spe_data->ctx)); + int mbox_read = spe_out_mbox_read(spe_data->ctx, out_messages, 1); + deprintf(2, "[PS3->SPU] Got message from %s, message was %u\n", spe_data->program_name, out_messages[0]); + if (out_messages[0] == msg) + return 0; + else + return -1; +} + + +/* Re-runnable invocation of the spe_context_run call */ +void SPE_RunContext(void *thread_argp) +{ + /* argp is the pointer to argument to be passed to the SPE program */ + spu_data_t *args = (spu_data_t *) thread_argp; + deprintf(3, "[PS3->SPU] void* argp=0x%x\n", (unsigned int)args->argp); + + /* Run it.. */ + deprintf(2, "[PS3->SPU] Run SPE program: %s\n", args->program_name); + if (spe_context_run + (args->ctx, &args->entry, 0, (void *)args->argp, NULL, + NULL) < 0) { + deprintf(2, "[PS3->SPU] Failed running SPE context: %s\n", args->program_name); + SDL_SetError("[PS3->SPU] Failed running SPE context: %s", args->program_name); + exit(1); + } + + pthread_exit(NULL); +} + + +/* Quits the video driver */ +static void PS3_VideoQuit(_THIS) +{ + if (fb_dev_fd > 0) { + /* Restore the original video mode */ + if (ioctl(fb_dev_fd, FBIOPUT_VSCREENINFO, &fb_orig_vinfo)) + SDL_SetError("[PS3] Can't restore original fb_var_screeninfo"); + + /* Give control of frame buffer to kernel */ + ioctl(fb_dev_fd, PS3FB_IOCTL_OFF, 0); + close(fb_dev_fd); + fb_dev_fd = -1; + } + + if (frame_buffer) { + munmap(frame_buffer, fb_finfo.smem_len); + frame_buffer = 0; + } + + if (fb_parms) + free((void *)fb_parms); + if (fb_thread_data) { + SPE_Shutdown(this, fb_thread_data); + free((void *)fb_thread_data); + } + + if (this->screen) { + if (double_buffering && this->screen->pixels) { + free(this->screen->pixels); + } + this->screen->pixels = NULL; + } + + enable_cursor(1); + deprintf(1, "[PS3] VideoQuit\n"); +} + diff --git a/3rdparty/SDL/src/video/ps3/SDL_ps3video.h b/3rdparty/SDL/src/video/ps3/SDL_ps3video.h new file mode 100644 index 0000000..4fe5a2b --- /dev/null +++ b/3rdparty/SDL/src/video/ps3/SDL_ps3video.h @@ -0,0 +1,165 @@ +/* + * SDL - Simple DirectMedia Layer + * CELL BE Support for PS3 Framebuffer + * Copyright (C) 2008, 2009 International Business Machines Corporation + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 + * USA + * + * Martin Lowinski <lowinski [at] de [dot] ibm [ibm] com> + * Dirk Herrendoerfer <d.herrendoerfer [at] de [dot] ibm [dot] com> + * SPE code based on research by: + * Rene Becker + * Thimo Emmerich + */ + +#include "SDL_config.h" +#include "../SDL_sysvideo.h" +#include "SDL_mouse.h" +#include "SDL_mutex.h" +#include "spulibs/spu_common.h" + +#include <libspe2.h> +#include <pthread.h> +#include <linux/types.h> +#include <linux/fb.h> +#include <asm/ps3fb.h> +#include <linux/vt.h> +#include <termios.h> + +#ifndef _SDL_ps3video_h +#define _SDL_ps3video_h + +/* Debugging + * 0: No debug messages + * 1: Video debug messages + * 2: SPE debug messages + * 3: Memory adresses + */ +#define DEBUG_LEVEL 0 + +#ifdef DEBUG_LEVEL +#define deprintf( level, fmt, args... ) \ + do \ +{ \ + if ( (unsigned)(level) <= DEBUG_LEVEL ) \ + { \ + fprintf( stdout, fmt, ##args ); \ + fflush( stdout ); \ + } \ +} while ( 0 ) +#else +#define deprintf( level, fmt, args... ) +#endif + +/* Framebuffer device */ +#define PS3_DEV_FB "/dev/fb0" + +/* Hidden "this" pointer for the video functions */ +#define _THIS SDL_VideoDevice * this + +/* SPU thread data */ +typedef struct spu_data { + spe_context_ptr_t ctx; + pthread_t thread; + spe_program_handle_t program; + char * program_name; + unsigned int booted; + unsigned int keepalive; + unsigned int entry; + int error_code; + void * argp; +} spu_data_t; + +/* Private video driver data needed for Cell support */ +struct SDL_PrivateVideoData +{ + const char * const fb_dev_name; /* FB-device name */ + int fb_dev_fd; /* Descriptor-handle for fb_dev_name */ + uint8_t * frame_buffer; /* mmap'd access to fbdev */ + + /* SPE threading stuff */ + spu_data_t * fb_thread_data; + spu_data_t * scaler_thread_data; + spu_data_t * converter_thread_data; + + /* screeninfo (from linux/fb.h) */ + struct fb_fix_screeninfo fb_finfo; + struct fb_var_screeninfo fb_vinfo; + struct fb_var_screeninfo fb_orig_vinfo; + + /* screeninfo (from asm/ps3fb.h) */ + struct ps3fb_ioctl_res res; + + unsigned int double_buffering; + uint32_t real_width; // real width of screen + uint32_t real_height; // real height of screen + + uint32_t s_fb_pixel_size; // 32: 4 24: 3 16: 2 15: 2 + uint32_t fb_bits_per_pixel; // 32: 32 24: 24 16: 16 15: 15 + + uint32_t config_count; + + uint32_t s_input_line_length; // precalculated: input_width * fb_pixel_size + uint32_t s_bounded_input_width; // width of input (bounded by writeable width) + uint32_t s_bounded_input_height;// height of input (bounded by writeable height) + uint32_t s_bounded_input_width_offset; // offset from the left side (used for centering) + uint32_t s_bounded_input_height_offset; // offset from the upper side (used for centering) + uint32_t s_writeable_width; // width of screen which is writeable + uint32_t s_writeable_height; // height of screen which is writeable + + uint8_t * s_center[2]; // where to begin writing our image (centered?) + uint32_t s_center_index; + + volatile void * s_pixels __attribute__((aligned(128))); + + /* Framebuffer data */ + volatile struct fb_writer_parms_t * fb_parms __attribute__((aligned(128))); +}; + +#define fb_dev_name (this->hidden->fb_dev_name) +#define fb_dev_fd (this->hidden->fb_dev_fd) +#define frame_buffer (this->hidden->frame_buffer) +#define fb_thread_data (this->hidden->fb_thread_data) +#define scaler_thread_data (this->hidden->scaler_thread_data) +#define converter_thread_data (this->hidden->converter_thread_data) +#define fb_parms (this->hidden->fb_parms) +#define SDL_nummodes (this->hidden->SDL_nummodes) +#define SDL_modelist (this->hidden->SDL_modelist) +#define SDL_videomode (this->hidden->SDL_videomode) +#define fb_finfo (this->hidden->fb_finfo) +#define fb_vinfo (this->hidden->fb_vinfo) +#define fb_orig_vinfo (this->hidden->fb_orig_vinfo) +#define res (this->hidden->res) +#define double_buffering (this->hidden->double_buffering) +#define real_width (this->hidden->real_width) +#define real_height (this->hidden->real_height) +#define s_fb_pixel_size (this->hidden->s_fb_pixel_size) +#define fb_bits_per_pixel (this->hidden->fb_bits_per_pixel) +#define config_count (this->hidden->config_count) +#define s_input_line_length (this->hidden->s_input_line_length) +#define s_bounded_input_width (this->hidden->s_bounded_input_width) +#define s_bounded_input_height (this->hidden->s_bounded_input_height) +#define s_bounded_input_width_offset (this->hidden->s_bounded_input_width_offset) +#define s_bounded_input_height_offset (this->hidden->s_bounded_input_height_offset) +#define s_writeable_width (this->hidden->s_writeable_width) +#define s_writeable_height (this->hidden->s_writeable_height) +#define s_center (this->hidden->s_center) +#define s_center_index (this->hidden->s_center_index) +#define s_pixels (this->hidden->s_pixels) + +#endif /* _SDL_ps3video_h */ + + diff --git a/3rdparty/SDL/src/video/ps3/SDL_ps3yuv.c b/3rdparty/SDL/src/video/ps3/SDL_ps3yuv.c new file mode 100644 index 0000000..b1e17da --- /dev/null +++ b/3rdparty/SDL/src/video/ps3/SDL_ps3yuv.c @@ -0,0 +1,340 @@ +/* + * SDL - Simple DirectMedia Layer + * CELL BE Support for PS3 Framebuffer + * Copyright (C) 2008, 2009 International Business Machines Corporation + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 + * USA + * + * Martin Lowinski <lowinski [at] de [dot] ibm [ibm] com> + * Dirk Herrendoerfer <d.herrendoerfer [at] de [dot] ibm [dot] com> + * SPE code based on research by: + * Rene Becker + * Thimo Emmerich + */ + +#include "SDL_config.h" + +#include "SDL_video.h" +#include "SDL_ps3video.h" +#include "SDL_ps3yuv_c.h" +#include "../SDL_yuvfuncs.h" +#include "spulibs/spu_common.h" + +/* Stores the executable name */ +extern spe_program_handle_t yuv2rgb_spu; +extern spe_program_handle_t bilin_scaler_spu; + +int SPE_Start(_THIS, spu_data_t * spe_data); +int SPE_Stop(_THIS, spu_data_t * spe_data); +int SPE_Boot(_THIS, spu_data_t * spe_data); +int SPE_Shutdown(_THIS, spu_data_t * spe_data); +int SPE_SendMsg(_THIS, spu_data_t * spe_data, unsigned int msg); +int SPE_WaitForMsg(_THIS, spu_data_t * spe_data, unsigned int msg); +void SPE_RunContext(void *thread_argp); + + +/* The functions used to manipulate software video overlays */ +static struct private_yuvhwfuncs ps3_yuvfuncs = { + PS3_LockYUVOverlay, + PS3_UnlockYUVOverlay, + PS3_DisplayYUVOverlay, + PS3_FreeYUVOverlay +}; + + +struct private_yuvhwdata { + SDL_Surface *display; + SDL_Surface *stretch; + volatile void * pixels __attribute__((aligned(128))); + + /* These are just so we don't have to allocate them separately */ + Uint16 pitches[3]; + Uint8 * planes[3]; + + unsigned int scale; + + /* Scaled YUV picture */ + Uint8 * scaler_out __attribute__((aligned(128))); + + /* YUV2RGB converter data */ + volatile struct yuv2rgb_parms_t * converter_parms __attribute__((aligned(128))); + + /* Scaler data */ + volatile struct scale_parms_t * scaler_parms __attribute__((aligned(128))); + + Uint8 locked; +}; + + +SDL_Overlay *PS3_CreateYUVOverlay(_THIS, int width, int height, Uint32 format, SDL_Surface *display) { + /* Only RGB packed pixel conversion supported */ + if ((display->format->BytesPerPixel != 2) && + (display->format->BytesPerPixel != 3) && + (display->format->BytesPerPixel != 4)) + { + SDL_SetError ("Can't use YUV data on non 16/24/32 bit surfaces"); + return NULL; + } + + /* Double-check the requested format. We'll only support YV12 */ + switch (format) { + case SDL_IYUV_OVERLAY: + case SDL_YV12_OVERLAY: + /* Supported YUV format */ + break; + default: + SDL_SetError("Unsupported YUV format"); + return NULL; + } + + SDL_Overlay* overlay; + struct private_yuvhwdata* hwdata; + + /* Create the overlay structure */ + overlay = (SDL_Overlay *) SDL_calloc(1, sizeof(SDL_Overlay)); + if (overlay == NULL) { + SDL_OutOfMemory(); + return NULL; + } + SDL_memset(overlay, 0, (sizeof *overlay)); + + /* Set the basic attributes */ + overlay->format = format; + overlay->w = width; + overlay->h = height; + overlay->hwdata = NULL; + + /* Set up the PS3 YUV surface function structure */ + overlay->hwfuncs = &ps3_yuvfuncs; + + /* Create the pixel data and lookup tables */ + hwdata = (struct private_yuvhwdata *) SDL_calloc(1, sizeof(struct private_yuvhwdata)); + if (hwdata == NULL) { + SDL_OutOfMemory(); + SDL_FreeYUVOverlay(overlay); + return NULL; + } + overlay->hwdata = hwdata; + + hwdata->stretch = NULL; + hwdata->display = display; + + /* Create SPU parms structure */ + hwdata->converter_parms = (struct yuv2rgb_parms_t *) memalign(16, sizeof(struct yuv2rgb_parms_t)); + hwdata->scaler_parms = (struct scale_parms_t *) memalign(16, sizeof(struct scale_parms_t)); + if (hwdata->converter_parms == NULL || hwdata->scaler_parms == NULL) { + SDL_FreeYUVOverlay(overlay); + SDL_OutOfMemory(); + return(NULL); + } + + /* Set up the SPEs */ + scaler_thread_data = (spu_data_t *) malloc(sizeof(spu_data_t)); + converter_thread_data = (spu_data_t *) malloc(sizeof(spu_data_t)); + if (converter_thread_data == NULL || scaler_thread_data == NULL) { + SDL_FreeYUVOverlay(overlay); + SDL_OutOfMemory(); + return(NULL); + } + + scaler_thread_data->program = bilin_scaler_spu; + scaler_thread_data->program_name = "bilin_scaler_spu"; + scaler_thread_data->keepalive = 0; + scaler_thread_data->booted = 0; + + converter_thread_data->program = yuv2rgb_spu; + converter_thread_data->program_name = "yuv2rgb_spu"; + converter_thread_data->keepalive = 1; + converter_thread_data->booted = 0; + + SPE_Start(this, converter_thread_data); + + hwdata->pixels = (Uint8 *) memalign(16, width * height + ((width * height) >> 1)); + if (hwdata->pixels == NULL) { + SDL_FreeYUVOverlay(overlay); + SDL_OutOfMemory(); + return(NULL); + } + + /* Find the pitch and offset values for the overlay */ + overlay->pitches = hwdata->pitches; + overlay->pixels = hwdata->planes; + switch (format) { + case SDL_YV12_OVERLAY: + case SDL_IYUV_OVERLAY: + overlay->pitches[0] = overlay->w; + overlay->pitches[1] = overlay->pitches[0] / 2; + overlay->pitches[2] = overlay->pitches[0] / 2; + overlay->pixels[0] = (Uint8 *)hwdata->pixels; + overlay->pixels[1] = overlay->pixels[0] + + overlay->pitches[0] * overlay->h; + overlay->pixels[2] = overlay->pixels[1] + + overlay->pitches[1] * overlay->h / 2; + overlay->planes = 3; + break; + default: + /* We should never get here (caught above) */ + break; + } + + /* We're all done.. */ + return overlay; +} + + +int PS3_LockYUVOverlay(_THIS, SDL_Overlay *overlay) { + if (overlay == NULL) { + return -1; + } + overlay->hwdata->locked = 1; + + return 0; +} + + +void PS3_UnlockYUVOverlay(_THIS, SDL_Overlay *overlay) { + if (overlay == NULL) { + return; + } + overlay->hwdata->locked = 0; + + return; +} + + +int PS3_DisplayYUVOverlay(_THIS, SDL_Overlay *overlay, SDL_Rect *src, SDL_Rect *dst) { + if ((overlay == NULL) || (overlay->hwdata == NULL)) { + return -1; + } + + Uint8 *lum, *Cr, *Cb; + struct private_yuvhwdata *hwdata; + SDL_Surface *display; + + hwdata = overlay->hwdata; + display = hwdata->display; + + /* Do we have to scale? */ + if ((src->w != dst->w) || (src->h != dst->h) ) { + hwdata->scale = 1; + deprintf(1, "[PS3] We need to scale\n"); + } else { + hwdata->scale = 0; + deprintf(1, "[PS3] No scaling\n"); + } + + /* Find out where the various portions of the image are */ + switch (overlay->format) { + case SDL_YV12_OVERLAY: + lum = (Uint8 *)overlay->pixels[0]; + Cr = (Uint8 *)overlay->pixels[1]; + Cb = (Uint8 *)overlay->pixels[2]; + break; + case SDL_IYUV_OVERLAY: + lum = (Uint8 *)overlay->pixels[0]; + Cr = (Uint8 *)overlay->pixels[2]; + Cb = (Uint8 *)overlay->pixels[1]; + break; + default: + SDL_SetError("Unsupported YUV format in blit"); + return -1; + } + + if (hwdata->scale) { + /* Alloc mem for scaled YUV picture */ + hwdata->scaler_out = (Uint8 *) memalign(16, dst->w * dst->h + ((dst->w * dst->h) >> 1)); + if (hwdata->scaler_out == NULL) { + SDL_FreeYUVOverlay(overlay); + SDL_OutOfMemory(); + return -1; + } + + /* Set parms for scaling */ + hwdata->scaler_parms->src_pixel_width = src->w; + hwdata->scaler_parms->src_pixel_height = src->h; + hwdata->scaler_parms->dst_pixel_width = dst->w; + hwdata->scaler_parms->dst_pixel_height = dst->h; + hwdata->scaler_parms->y_plane = lum; + hwdata->scaler_parms->v_plane = Cr; + hwdata->scaler_parms->u_plane = Cb; + hwdata->scaler_parms->dstBuffer = hwdata->scaler_out; + scaler_thread_data->argp = (void *)hwdata->scaler_parms; + + /* Scale the YUV overlay to given size */ + SPE_Start(this, scaler_thread_data); + SPE_Stop(this, scaler_thread_data); + + /* Set parms for converting after scaling */ + hwdata->converter_parms->y_plane = hwdata->scaler_out; + hwdata->converter_parms->v_plane = hwdata->scaler_out + dst->w * dst->h; + hwdata->converter_parms->u_plane = hwdata->scaler_out + dst->w * dst->h + ((dst->w * dst->h) >> 2); + } else { + /* Set parms for converting */ + hwdata->converter_parms->y_plane = lum; + hwdata->converter_parms->v_plane = Cr; + hwdata->converter_parms->u_plane = Cb; + } + + hwdata->converter_parms->src_pixel_width = dst->w; + hwdata->converter_parms->src_pixel_height = dst->h; + hwdata->converter_parms->dstBuffer = (Uint8 *) s_pixels; + converter_thread_data->argp = (void *)hwdata->converter_parms; + + /* Convert YUV overlay to RGB */ + SPE_SendMsg(this, converter_thread_data, SPU_START); + SPE_SendMsg(this, converter_thread_data, (unsigned int)converter_thread_data->argp); + + /* Centering */ + s_bounded_input_width = dst->w; + s_bounded_input_height = dst->h; + + /* UpdateRects() will do the rest.. */ + SDL_UpdateRects(display, 1, dst); + + if (hwdata->scale) + SDL_free((void *)hwdata->scaler_out); + + return 0; +} + + +void PS3_FreeYUVOverlay(_THIS, SDL_Overlay *overlay) { + if (overlay == NULL) { + return; + } + + if (overlay->hwdata == NULL) { + return; + } + + struct private_yuvhwdata * hwdata; + hwdata = overlay->hwdata; + + if (scaler_thread_data) + SDL_free(scaler_thread_data); + if (converter_thread_data) { + SPE_Shutdown(this, converter_thread_data); + SDL_free(converter_thread_data); + } + + if (hwdata) { + if (hwdata->pixels) + SDL_free((void *)hwdata->pixels); + SDL_free(hwdata); + } + return; +} + diff --git a/3rdparty/SDL/src/video/ps3/SDL_ps3yuv_c.h b/3rdparty/SDL/src/video/ps3/SDL_ps3yuv_c.h new file mode 100644 index 0000000..49f9d70 --- /dev/null +++ b/3rdparty/SDL/src/video/ps3/SDL_ps3yuv_c.h @@ -0,0 +1,44 @@ +/* + * SDL - Simple DirectMedia Layer + * CELL BE Support for PS3 Framebuffer + * Copyright (C) 2008, 2009 International Business Machines Corporation + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 + * USA + * + * Martin Lowinski <lowinski [at] de [dot] ibm [ibm] com> + * Dirk Herrendoerfer <d.herrendoerfer [at] de [dot] ibm [dot] com> + * SPE code based on research by: + * Rene Becker + * Thimo Emmerich + */ + +#include "SDL_config.h" + +#ifndef _SDL_ps3yuv_h +#define _SDL_ps3yuv_h + +/* This is the PS3 implementation of YUV video overlays */ + +#include "SDL_video.h" + +extern SDL_Overlay *PS3_CreateYUVOverlay(_THIS, int width, int height, Uint32 format, SDL_Surface *display); +extern int PS3_DisplayYUVOverlay(_THIS, SDL_Overlay *overlay, SDL_Rect *src, SDL_Rect *dst); +extern int PS3_LockYUVOverlay(_THIS, SDL_Overlay *overlay); +extern void PS3_UnlockYUVOverlay(_THIS, SDL_Overlay *overlay); +extern void PS3_FreeYUVOverlay(_THIS, SDL_Overlay *overlay); + +#endif /* _SDL_ps3yuv_h */ + diff --git a/3rdparty/SDL/src/video/ps3/spulibs/Makefile b/3rdparty/SDL/src/video/ps3/spulibs/Makefile new file mode 100644 index 0000000..dc580d9 --- /dev/null +++ b/3rdparty/SDL/src/video/ps3/spulibs/Makefile @@ -0,0 +1,83 @@ +# This Makefile is for building the CELL BE SPU libs +# libfb_writer_spu.so, libyuv2rgb_spu.so, libbilin_scaler_spu.so + +# Toolchain +SPU_GCC=/usr/bin/spu-gcc +PPU_GCC=/usr/bin/gcc +PPU_EMBEDSPU=/usr/bin/embedspu +PPU_AR=/usr/bin/ar +PPU_LD=/usr/bin/ld +INSTALL=/usr/bin/install + +SPU_CFLAGS=-W -Wall -Winline -Wno-main -I. -I /usr/spu/include -I /opt/cell/sdk/usr/spu/include -finline-limit=10000 -Winline -ftree-vectorize -funroll-loops -fmodulo-sched -ffast-math -fPIC -O2 + +# Usually /usr/lib, depending on your distribution +PREFIX=/usr/lib + + +all: libfb_writer_spu.a libfb_writer_spu.so \ + libyuv2rgb_spu.so libyuv2rgb_spu.a \ + libbilin_scaler_spu.so libbilin_scaler_spu.a + + +# fb_writer +fb_writer_spu-embed.o: fb_writer.c spu_common.h + $(SPU_GCC) $(SPU_CFLAGS) -o fb_writer_spu fb_writer.c -lm + $(PPU_EMBEDSPU) -m32 fb_writer_spu fb_writer_spu fb_writer_spu-embed.o + +libfb_writer_spu.so: fb_writer_spu-embed.o + $(PPU_LD) -o libfb_writer_spu.so -shared -soname=libfb_writer_spu.so fb_writer_spu-embed.o + +libfb_writer_spu.a: fb_writer_spu-embed.o + $(PPU_AR) -qcs libfb_writer_spu.a fb_writer_spu-embed.o + + +# yuv2rgb_converter +yuv2rgb_spu-embed.o: yuv2rgb_converter.c spu_common.h + $(SPU_GCC) $(SPU_CFLAGS) -o yuv2rgb_spu yuv2rgb_converter.c -lm + $(PPU_EMBEDSPU) -m32 yuv2rgb_spu yuv2rgb_spu yuv2rgb_spu-embed.o + +libyuv2rgb_spu.a: yuv2rgb_spu-embed.o + $(PPU_AR) -qcs libyuv2rgb_spu.a yuv2rgb_spu-embed.o + +libyuv2rgb_spu.so: yuv2rgb_spu-embed.o + $(PPU_LD) -o libyuv2rgb_spu.so -shared -soname=libyuv2rgb_spu.so yuv2rgb_spu-embed.o + + +# bilin_scaler +bilin_scaler_spu-embed.o: bilin_scaler.c spu_common.h + $(SPU_GCC) $(SPU_CFLAGS) -o bilin_scaler_spu bilin_scaler.c -lm + $(PPU_EMBEDSPU) -m32 bilin_scaler_spu bilin_scaler_spu bilin_scaler_spu-embed.o + +libbilin_scaler_spu.a: bilin_scaler_spu-embed.o + $(PPU_AR) -qcs libbilin_scaler_spu.a bilin_scaler_spu-embed.o + +libbilin_scaler_spu.so: bilin_scaler_spu-embed.o + $(PPU_LD) -o libbilin_scaler_spu.so -shared -soname=libbilin_scaler_spu.so bilin_scaler_spu-embed.o + +install: libfb_writer_spu.a libfb_writer_spu.so \ + libyuv2rgb_spu.so libyuv2rgb_spu.a \ + libbilin_scaler_spu.so libbilin_scaler_spu.a + $(INSTALL) -c -m 0755 libfb_writer_spu.so $(PREFIX)/. + $(INSTALL) -c -m 0655 libfb_writer_spu.a $(PREFIX)/. + $(INSTALL) -c -m 0755 libyuv2rgb_spu.so $(PREFIX)/. + $(INSTALL) -c -m 0655 libyuv2rgb_spu.a $(PREFIX)/. + $(INSTALL) -c -m 0755 libbilin_scaler_spu.so $(PREFIX)/. + $(INSTALL) -c -m 0655 libbilin_scaler_spu.a $(PREFIX)/. + + +uninstall: $(PREFIX)/libfb_writer_spu.so $(PREFIX)/libfb_writer_spu.a \ + $(PREFIX)/libyuv2rgb_spu.so $(PREFIX)/libyuv2rgb_spu.a \ + $(PREFIX)/libbilin_scaler_spu.so $(PREFIX)/libbilin_scaler_spu.a + rm -f $(PREFIX)/libfb_writer_spu.a + rm -f $(PREFIX)/libfb_writer_spu.so + rm -f $(PREFIX)/libyuv2rgb_spu.so + rm -f $(PREFIX)/libyuv2rgb_spu.a + rm -f $(PREFIX)/libbilin_scaler_spu.so + rm -f $(PREFIX)/libbilin_scaler_spu.a + + +clean: + rm -f bilin_scaler_spu-embed.o libbilin_scaler_spu.so libbilin_scaler_spu.a bilin_scaler_spu + rm -f yuv2rgb_spu-embed.o libyuv2rgb_spu.so libyuv2rgb_spu.a yuv2rgb_spu + rm -f fb_writer_spu-embed.o libfb_writer_spu.so libfb_writer_spu.a fb_writer_spu diff --git a/3rdparty/SDL/src/video/ps3/spulibs/bilin_scaler.c b/3rdparty/SDL/src/video/ps3/spulibs/bilin_scaler.c new file mode 100644 index 0000000..be9b5c6 --- /dev/null +++ b/3rdparty/SDL/src/video/ps3/spulibs/bilin_scaler.c @@ -0,0 +1,2050 @@ +/* + * SDL - Simple DirectMedia Layer + * CELL BE Support for PS3 Framebuffer + * Copyright (C) 2008, 2009 International Business Machines Corporation + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 + * USA + * + * Martin Lowinski <lowinski [at] de [dot] ibm [ibm] com> + * Dirk Herrendoerfer <d.herrendoerfer [at] de [dot] ibm [dot] com> + * SPE code based on research by: + * Rene Becker + * Thimo Emmerich + */ + +#include "spu_common.h" + +#include <spu_intrinsics.h> +#include <spu_mfcio.h> + +// Debugging +//#define DEBUG + +#ifdef DEBUG +#define deprintf(fmt, args... ) \ + fprintf( stdout, fmt, ##args ); \ + fflush( stdout ); +#else +#define deprintf( fmt, args... ) +#endif + +struct scale_parms_t parms __attribute__((aligned(128))); + +/* A maximum of 8 lines Y, therefore 4 lines V, 4 lines U are stored + * there might be the need to retrieve misaligned data, adjust + * incoming v and u plane to be able to handle this (add 128) + */ +unsigned char y_plane[2][(MAX_HDTV_WIDTH+128)*4] __attribute__((aligned(128))); +unsigned char v_plane[2][(MAX_HDTV_WIDTH+128)*2] __attribute__((aligned(128))); +unsigned char u_plane[2][(MAX_HDTV_WIDTH+128)*2] __attribute__((aligned(128))); + +/* temp-buffer for scaling: 4 lines Y, therefore 2 lines V, 2 lines U */ +unsigned char scaled_y_plane[2][MAX_HDTV_WIDTH*2] __attribute__((aligned(128))); +unsigned char scaled_v_plane[2][MAX_HDTV_WIDTH/2] __attribute__((aligned(128))); +unsigned char scaled_u_plane[2][MAX_HDTV_WIDTH/2] __attribute__((aligned(128))); + +/* some vectors needed by the float to int conversion */ +static const vector float vec_255 = { 255.0f, 255.0f, 255.0f, 255.0f }; +static const vector float vec_0_1 = { 0.1f, 0.1f, 0.1f, 0.1f }; + +void bilinear_scale_line_w8(unsigned char* src, unsigned char* dst_, unsigned int dst_width, vector float vf_x_scale, vector float vf_NSweight, unsigned int src_linestride); +void bilinear_scale_line_w16(unsigned char* src, unsigned char* dst_, unsigned int dst_width, vector float vf_x_scale, vector float vf_NSweight, unsigned int src_linestride); + +void scale_srcw16_dstw16(); +void scale_srcw16_dstw32(); +void scale_srcw32_dstw16(); +void scale_srcw32_dstw32(); + +int main( unsigned long long spe_id __attribute__((unused)), unsigned long long argp ) +{ + deprintf("[SPU] bilin_scaler_spu is up... (on SPE #%llu)\n", spe_id); + /* DMA transfer for the input parameters */ + spu_mfcdma32(&parms, (unsigned int)argp, sizeof(struct scale_parms_t), TAG_INIT, MFC_GET_CMD); + DMA_WAIT_TAG(TAG_INIT); + + deprintf("[SPU] Scale %ux%u to %ux%u\n", parms.src_pixel_width, parms.src_pixel_height, + parms.dst_pixel_width, parms.dst_pixel_height); + + if(parms.src_pixel_width & 0x1f) { + if(parms.dst_pixel_width & 0x1F) { + deprintf("[SPU] Using scale_srcw16_dstw16\n"); + scale_srcw16_dstw16(); + } else { + deprintf("[SPU] Using scale_srcw16_dstw32\n"); + scale_srcw16_dstw32(); + } + } else { + if(parms.dst_pixel_width & 0x1F) { + deprintf("[SPU] Using scale_srcw32_dstw16\n"); + scale_srcw32_dstw16(); + } else { + deprintf("[SPU] Using scale_srcw32_dstw32\n"); + scale_srcw32_dstw32(); + } + } + deprintf("[SPU] bilin_scaler_spu... done!\n"); + + return 0; +} + + +/* + * vfloat_to_vuint() + * + * converts a float vector to an unsinged int vector using saturated + * arithmetic + * + * @param vec_s float vector for conversion + * @returns converted unsigned int vector + */ +inline static vector unsigned int vfloat_to_vuint(vector float vec_s) { + vector unsigned int select_1 = spu_cmpgt(vec_0_1, vec_s); + vec_s = spu_sel(vec_s, vec_0_1, select_1); + + vector unsigned int select_2 = spu_cmpgt(vec_s, vec_255); + vec_s = spu_sel(vec_s, vec_255, select_2); + return spu_convtu(vec_s,0); +} + + +/* + * scale_srcw16_dstw16() + * + * processes an input image of width 16 + * scaling is done to a width 16 + * result stored in RAM + */ +void scale_srcw16_dstw16() { + // extract parameters + unsigned char* dst_addr = (unsigned char *)parms.dstBuffer; + + unsigned int src_width = parms.src_pixel_width; + unsigned int src_height = parms.src_pixel_height; + unsigned int dst_width = parms.dst_pixel_width; + unsigned int dst_height = parms.dst_pixel_height; + + // YVU + unsigned int src_linestride_y = src_width; + unsigned int src_dbl_linestride_y = src_width<<1; + unsigned int src_linestride_vu = src_width>>1; + unsigned int src_dbl_linestride_vu = src_width; + + // scaled YVU + unsigned int scaled_src_linestride_y = dst_width; + + // ram addresses + unsigned char* src_addr_y = parms.y_plane; + unsigned char* src_addr_v = parms.v_plane; + unsigned char* src_addr_u = parms.u_plane; + + // for handling misalignment, addresses are precalculated + unsigned char* precalc_src_addr_v = src_addr_v; + unsigned char* precalc_src_addr_u = src_addr_u; + + unsigned int dst_picture_size = dst_width*dst_height; + + // Sizes for destination + unsigned int dst_dbl_linestride_y = dst_width<<1; + unsigned int dst_dbl_linestride_vu = dst_width>>1; + + // Perform address calculation for Y, V and U in main memory with dst_addr as base + unsigned char* dst_addr_main_memory_y = dst_addr; + unsigned char* dst_addr_main_memory_v = dst_addr + dst_picture_size; + unsigned char* dst_addr_main_memory_u = dst_addr_main_memory_v +(dst_picture_size>>2); + + // calculate scale factors + vector float vf_x_scale = spu_splats( (float)src_width/(float)dst_width ); + float y_scale = (float)src_height/(float)dst_height; + + // double buffered processing + // buffer switching + unsigned int curr_src_idx = 0; + unsigned int curr_dst_idx = 0; + unsigned int next_src_idx, next_dst_idx; + + // 2 lines y as output, upper and lowerline + unsigned int curr_interpl_y_upper = 0; + unsigned int next_interpl_y_upper; + unsigned int curr_interpl_y_lower, next_interpl_y_lower; + // only 1 line v/u output, both planes have the same dimension + unsigned int curr_interpl_vu = 0; + unsigned int next_interpl_vu; + + // weights, calculated in every loop iteration + vector float vf_curr_NSweight_y_upper = { 0.0f, 0.0f, 0.0f, 0.0f }; + vector float vf_next_NSweight_y_upper; + vector float vf_curr_NSweight_y_lower, vf_next_NSweight_y_lower; + vector float vf_curr_NSweight_vu = { 0.0f, 0.0f, 0.0f, 0.0f }; + vector float vf_next_NSweight_vu; + + // line indices for the src picture + float curr_src_y_upper = 0.0f, next_src_y_upper; + float curr_src_y_lower, next_src_y_lower; + float curr_src_vu = 0.0f, next_src_vu; + + // line indices for the dst picture + unsigned int dst_y=0, dst_vu=0; + + // offset for the v and u plane to handle misalignement + unsigned int curr_lsoff_v = 0, next_lsoff_v; + unsigned int curr_lsoff_u = 0, next_lsoff_u; + + // calculate lower line indices + curr_src_y_lower = ((float)curr_interpl_y_upper+1)*y_scale; + curr_interpl_y_lower = (unsigned int)curr_src_y_lower; + // lower line weight + vf_curr_NSweight_y_lower = spu_splats( curr_src_y_lower-(float)curr_interpl_y_lower ); + + + // start partially double buffered processing + // get initial data, 2 sets of y, 1 set v, 1 set u + mfc_get( y_plane[curr_src_idx], (unsigned int) src_addr_y, src_dbl_linestride_y, RETR_BUF, 0, 0 ); + mfc_get( y_plane[curr_src_idx]+src_dbl_linestride_y, + (unsigned int) src_addr_y+(curr_interpl_y_lower*src_linestride_y), + src_dbl_linestride_y, + RETR_BUF, + 0, 0 ); + mfc_get( v_plane[curr_src_idx], (unsigned int) src_addr_v, src_dbl_linestride_vu, RETR_BUF, 0, 0 ); + mfc_get( u_plane[curr_src_idx], (unsigned int) src_addr_u, src_dbl_linestride_vu, RETR_BUF, 0, 0 ); + + /* iteration loop + * within each iteration 4 lines y, 2 lines v, 2 lines u are retrieved + * the scaled output is 2 lines y, 1 line v, 1 line u + * the yuv2rgb-converted output is stored to RAM + */ + for( dst_vu=0; dst_vu<(dst_height>>1)-1; dst_vu++ ) { + dst_y = dst_vu<<1; + + // calculate next indices + next_src_vu = ((float)dst_vu+1)*y_scale; + next_src_y_upper = ((float)dst_y+2)*y_scale; + next_src_y_lower = ((float)dst_y+3)*y_scale; + + next_interpl_vu = (unsigned int) next_src_vu; + next_interpl_y_upper = (unsigned int) next_src_y_upper; + next_interpl_y_lower = (unsigned int) next_src_y_lower; + + // calculate weight NORTH-SOUTH + vf_next_NSweight_vu = spu_splats( next_src_vu-(float)next_interpl_vu ); + vf_next_NSweight_y_upper = spu_splats( next_src_y_upper-(float)next_interpl_y_upper ); + vf_next_NSweight_y_lower = spu_splats( next_src_y_lower-(float)next_interpl_y_lower ); + + // get next lines + next_src_idx = curr_src_idx^1; + next_dst_idx = curr_dst_idx^1; + + // 4 lines y + mfc_get( y_plane[next_src_idx], + (unsigned int) src_addr_y+(next_interpl_y_upper*src_linestride_y), + src_dbl_linestride_y, + RETR_BUF+next_src_idx, + 0, 0 ); + mfc_get( y_plane[next_src_idx]+src_dbl_linestride_y, + (unsigned int) src_addr_y+(next_interpl_y_lower*src_linestride_y), + src_dbl_linestride_y, + RETR_BUF+next_src_idx, + 0, 0 ); + + // 2 lines v + precalc_src_addr_v = src_addr_v+(next_interpl_vu*src_linestride_vu); + next_lsoff_v = ((unsigned int)precalc_src_addr_v)&0x0F; + mfc_get( v_plane[next_src_idx], + ((unsigned int) precalc_src_addr_v)&0xFFFFFFF0, + src_dbl_linestride_vu+(next_lsoff_v<<1), + RETR_BUF+next_src_idx, + 0, 0 ); + // 2 lines u + precalc_src_addr_u = src_addr_u+(next_interpl_vu*src_linestride_vu); + next_lsoff_u = ((unsigned int)precalc_src_addr_u)&0x0F; + mfc_get( u_plane[next_src_idx], + ((unsigned int) precalc_src_addr_u)&0xFFFFFFF0, + src_dbl_linestride_vu+(next_lsoff_v<<1), + RETR_BUF+next_src_idx, + 0, 0 ); + + DMA_WAIT_TAG( (RETR_BUF+curr_src_idx) ); + + // scaling + // work line y_upper + bilinear_scale_line_w16( y_plane[curr_src_idx], + scaled_y_plane[curr_src_idx], + dst_width, + vf_x_scale, + vf_curr_NSweight_y_upper, + src_linestride_y ); + // work line y_lower + bilinear_scale_line_w16( y_plane[curr_src_idx]+src_dbl_linestride_y, + scaled_y_plane[curr_src_idx]+scaled_src_linestride_y, + dst_width, + vf_x_scale, + vf_curr_NSweight_y_lower, + src_linestride_y ); + // work line v + bilinear_scale_line_w8( v_plane[curr_src_idx]+curr_lsoff_v, + scaled_v_plane[curr_src_idx], + dst_width>>1, + vf_x_scale, + vf_curr_NSweight_vu, + src_linestride_vu ); + // work line u + bilinear_scale_line_w8( u_plane[curr_src_idx]+curr_lsoff_u, + scaled_u_plane[curr_src_idx], + dst_width>>1, + vf_x_scale, + vf_curr_NSweight_vu, + src_linestride_vu ); + + + // Store the result back to main memory into a destination buffer in YUV format + //--------------------------------------------------------------------------------------------- + DMA_WAIT_TAG( (STR_BUF+curr_dst_idx) ); + + // Perform three DMA transfers to 3 different locations in the main memory! + // dst_width: Pixel width of destination image + // dst_addr: Destination address in main memory + // dst_vu: Counter which is incremented one by one + // dst_y: Counter which is twice larger than dst_vu (dst_y = 2*dst_vu) + mfc_put( scaled_y_plane[curr_src_idx], // What from local store (addr) + (unsigned int)dst_addr_main_memory_y + (dst_vu*dst_dbl_linestride_y), // Destination in main memory (addr) + dst_dbl_linestride_y, // Two Y lines (depending on the widht of the destination resolution) + STR_BUF+curr_dst_idx, // Tag + 0, 0 ); + + mfc_put( scaled_v_plane[curr_src_idx], // What from local store (addr) + (unsigned int)dst_addr_main_memory_v + (dst_vu*dst_dbl_linestride_vu), // Destination in main memory (addr) + dst_dbl_linestride_vu, // Two V lines (depending on the widht of the destination resolution) + STR_BUF+curr_dst_idx, // Tag + 0, 0 ); + + mfc_put( scaled_u_plane[curr_src_idx], // What from local store (addr) + (unsigned int)dst_addr_main_memory_u + (dst_vu*dst_dbl_linestride_vu), // Destination in main memory (addr) + dst_dbl_linestride_vu, // Two U lines (depending on the widht of the destination resolution) + STR_BUF+curr_dst_idx, // Tag + 0, 0 ); + //--------------------------------------------------------------------------------------------- + + + // update for next cycle + curr_src_idx = next_src_idx; + curr_dst_idx = next_dst_idx; + + curr_interpl_y_upper = next_interpl_y_upper; + curr_interpl_y_lower = next_interpl_y_lower; + curr_interpl_vu = next_interpl_vu; + + vf_curr_NSweight_y_upper = vf_curr_NSweight_y_upper; + vf_curr_NSweight_y_lower = vf_curr_NSweight_y_lower; + vf_curr_NSweight_vu = vf_next_NSweight_vu; + + curr_src_y_upper = next_src_y_upper; + curr_src_y_lower = next_src_y_lower; + curr_src_vu = next_src_vu; + + curr_lsoff_v = next_lsoff_v; + curr_lsoff_u = next_lsoff_u; + } + + + + DMA_WAIT_TAG( (RETR_BUF+curr_src_idx) ); + + // scaling + // work line y_upper + bilinear_scale_line_w16( y_plane[curr_src_idx], + scaled_y_plane[curr_src_idx], + dst_width, + vf_x_scale, + vf_curr_NSweight_y_upper, + src_linestride_y ); + // work line y_lower + bilinear_scale_line_w16( y_plane[curr_src_idx]+src_dbl_linestride_y, + scaled_y_plane[curr_src_idx]+scaled_src_linestride_y, + dst_width, + vf_x_scale, + vf_curr_NSweight_y_lower, + src_linestride_y ); + // work line v + bilinear_scale_line_w8( v_plane[curr_src_idx]+curr_lsoff_v, + scaled_v_plane[curr_src_idx], + dst_width>>1, + vf_x_scale, + vf_curr_NSweight_vu, + src_linestride_vu ); + // work line u + bilinear_scale_line_w8( u_plane[curr_src_idx]+curr_lsoff_u, + scaled_u_plane[curr_src_idx], + dst_width>>1, + vf_x_scale, + vf_curr_NSweight_vu, + src_linestride_vu ); + + + // Store the result back to main memory into a destination buffer in YUV format + //--------------------------------------------------------------------------------------------- + DMA_WAIT_TAG( (STR_BUF+curr_dst_idx) ); + + // Perform three DMA transfers to 3 different locations in the main memory! + // dst_width: Pixel width of destination image + // dst_addr: Destination address in main memory + // dst_vu: Counter which is incremented one by one + // dst_y: Counter which is twice larger than dst_vu (dst_y = 2*dst_vu) + mfc_put( scaled_y_plane[curr_src_idx], // What from local store (addr) + (unsigned int)dst_addr_main_memory_y + (dst_vu*dst_dbl_linestride_y), // Destination in main memory (addr) + dst_dbl_linestride_y, // Two Y lines (depending on the widht of the destination resolution) + STR_BUF+curr_dst_idx, // Tag + 0, 0 ); + + mfc_put( scaled_v_plane[curr_src_idx], // What from local store (addr) + (unsigned int)dst_addr_main_memory_v + (dst_vu*dst_dbl_linestride_vu), // Destination in main memory (addr) + dst_dbl_linestride_vu, // Two V lines (depending on the widht of the destination resolution) + STR_BUF+curr_dst_idx, // Tag + 0, 0 ); + + mfc_put( scaled_u_plane[curr_src_idx], // What from local store (addr) + (unsigned int)dst_addr_main_memory_u + (dst_vu*dst_dbl_linestride_vu), // Destination in main memory (addr) + dst_dbl_linestride_vu, // Two U lines (depending on the widht of the destination resolution) + STR_BUF+curr_dst_idx, // Tag + 0, 0 ); + + // wait for completion + DMA_WAIT_TAG( (STR_BUF+curr_dst_idx) ); + //--------------------------------------------------------------------------------------------- +} + + +/* + * scale_srcw16_dstw32() + * + * processes an input image of width 16 + * scaling is done to a width 32 + * yuv2rgb conversion on a width of 32 + * result stored in RAM + */ +void scale_srcw16_dstw32() { + // extract parameters + unsigned char* dst_addr = (unsigned char *)parms.dstBuffer; + + unsigned int src_width = parms.src_pixel_width; + unsigned int src_height = parms.src_pixel_height; + unsigned int dst_width = parms.dst_pixel_width; + unsigned int dst_height = parms.dst_pixel_height; + + // YVU + unsigned int src_linestride_y = src_width; + unsigned int src_dbl_linestride_y = src_width<<1; + unsigned int src_linestride_vu = src_width>>1; + unsigned int src_dbl_linestride_vu = src_width; + // scaled YVU + unsigned int scaled_src_linestride_y = dst_width; + + // ram addresses + unsigned char* src_addr_y = parms.y_plane; + unsigned char* src_addr_v = parms.v_plane; + unsigned char* src_addr_u = parms.u_plane; + + unsigned int dst_picture_size = dst_width*dst_height; + + // Sizes for destination + unsigned int dst_dbl_linestride_y = dst_width<<1; + unsigned int dst_dbl_linestride_vu = dst_width>>1; + + // Perform address calculation for Y, V and U in main memory with dst_addr as base + unsigned char* dst_addr_main_memory_y = dst_addr; + unsigned char* dst_addr_main_memory_v = dst_addr + dst_picture_size; + unsigned char* dst_addr_main_memory_u = dst_addr_main_memory_v +(dst_picture_size>>2); + + + // for handling misalignment, addresses are precalculated + unsigned char* precalc_src_addr_v = src_addr_v; + unsigned char* precalc_src_addr_u = src_addr_u; + + // calculate scale factors + vector float vf_x_scale = spu_splats( (float)src_width/(float)dst_width ); + float y_scale = (float)src_height/(float)dst_height; + + // double buffered processing + // buffer switching + unsigned int curr_src_idx = 0; + unsigned int curr_dst_idx = 0; + unsigned int next_src_idx, next_dst_idx; + + // 2 lines y as output, upper and lowerline + unsigned int curr_interpl_y_upper = 0; + unsigned int next_interpl_y_upper; + unsigned int curr_interpl_y_lower, next_interpl_y_lower; + // only 1 line v/u output, both planes have the same dimension + unsigned int curr_interpl_vu = 0; + unsigned int next_interpl_vu; + + // weights, calculated in every loop iteration + vector float vf_curr_NSweight_y_upper = { 0.0f, 0.0f, 0.0f, 0.0f }; + vector float vf_next_NSweight_y_upper; + vector float vf_curr_NSweight_y_lower, vf_next_NSweight_y_lower; + vector float vf_curr_NSweight_vu = { 0.0f, 0.0f, 0.0f, 0.0f }; + vector float vf_next_NSweight_vu; + + // line indices for the src picture + float curr_src_y_upper = 0.0f, next_src_y_upper; + float curr_src_y_lower, next_src_y_lower; + float curr_src_vu = 0.0f, next_src_vu; + + // line indices for the dst picture + unsigned int dst_y=0, dst_vu=0; + + // offset for the v and u plane to handle misalignement + unsigned int curr_lsoff_v = 0, next_lsoff_v; + unsigned int curr_lsoff_u = 0, next_lsoff_u; + + // calculate lower line idices + curr_src_y_lower = ((float)curr_interpl_y_upper+1)*y_scale; + curr_interpl_y_lower = (unsigned int)curr_src_y_lower; + // lower line weight + vf_curr_NSweight_y_lower = spu_splats( curr_src_y_lower-(float)curr_interpl_y_lower ); + + + // start partially double buffered processing + // get initial data, 2 sets of y, 1 set v, 1 set u + mfc_get( y_plane[curr_src_idx], (unsigned int) src_addr_y, src_dbl_linestride_y, RETR_BUF, 0, 0 ); + mfc_get( y_plane[curr_src_idx]+src_dbl_linestride_y, + (unsigned int) src_addr_y+(curr_interpl_y_lower*src_linestride_y), + src_dbl_linestride_y, + RETR_BUF, + 0, 0 ); + mfc_get( v_plane[curr_src_idx], (unsigned int) src_addr_v, src_dbl_linestride_vu, RETR_BUF, 0, 0 ); + mfc_get( u_plane[curr_src_idx], (unsigned int) src_addr_u, src_dbl_linestride_vu, RETR_BUF, 0, 0 ); + + // iteration loop + // within each iteration 4 lines y, 2 lines v, 2 lines u are retrieved + // the scaled output is 2 lines y, 1 line v, 1 line u + // the yuv2rgb-converted output is stored to RAM + for( dst_vu=0; dst_vu<(dst_height>>1)-1; dst_vu++ ) { + dst_y = dst_vu<<1; + + // calculate next indices + next_src_vu = ((float)dst_vu+1)*y_scale; + next_src_y_upper = ((float)dst_y+2)*y_scale; + next_src_y_lower = ((float)dst_y+3)*y_scale; + + next_interpl_vu = (unsigned int) next_src_vu; + next_interpl_y_upper = (unsigned int) next_src_y_upper; + next_interpl_y_lower = (unsigned int) next_src_y_lower; + + // calculate weight NORTH-SOUTH + vf_next_NSweight_vu = spu_splats( next_src_vu-(float)next_interpl_vu ); + vf_next_NSweight_y_upper = spu_splats( next_src_y_upper-(float)next_interpl_y_upper ); + vf_next_NSweight_y_lower = spu_splats( next_src_y_lower-(float)next_interpl_y_lower ); + + // get next lines + next_src_idx = curr_src_idx^1; + next_dst_idx = curr_dst_idx^1; + + // 4 lines y + mfc_get( y_plane[next_src_idx], + (unsigned int) src_addr_y+(next_interpl_y_upper*src_linestride_y), + src_dbl_linestride_y, + RETR_BUF+next_src_idx, + 0, 0 ); + mfc_get( y_plane[next_src_idx]+src_dbl_linestride_y, + (unsigned int) src_addr_y+(next_interpl_y_lower*src_linestride_y), + src_dbl_linestride_y, + RETR_BUF+next_src_idx, + 0, 0 ); + + // 2 lines v + precalc_src_addr_v = src_addr_v+(next_interpl_vu*src_linestride_vu); + next_lsoff_v = ((unsigned int)precalc_src_addr_v)&0x0F; + mfc_get( v_plane[next_src_idx], + ((unsigned int) precalc_src_addr_v)&0xFFFFFFF0, + src_dbl_linestride_vu+(next_lsoff_v<<1), + RETR_BUF+next_src_idx, + 0, 0 ); + // 2 lines u + precalc_src_addr_u = src_addr_u+(next_interpl_vu*src_linestride_vu); + next_lsoff_u = ((unsigned int)precalc_src_addr_u)&0x0F; + mfc_get( u_plane[next_src_idx], + ((unsigned int) precalc_src_addr_u)&0xFFFFFFF0, + src_dbl_linestride_vu+(next_lsoff_v<<1), + RETR_BUF+next_src_idx, + 0, 0 ); + + DMA_WAIT_TAG( (RETR_BUF+curr_src_idx) ); + + // scaling + // work line y_upper + bilinear_scale_line_w16( y_plane[curr_src_idx], + scaled_y_plane[curr_src_idx], + dst_width, + vf_x_scale, + vf_curr_NSweight_y_upper, + src_linestride_y ); + // work line y_lower + bilinear_scale_line_w16( y_plane[curr_src_idx]+src_dbl_linestride_y, + scaled_y_plane[curr_src_idx]+scaled_src_linestride_y, + dst_width, + vf_x_scale, + vf_curr_NSweight_y_lower, + src_linestride_y ); + // work line v + bilinear_scale_line_w8( v_plane[curr_src_idx]+curr_lsoff_v, + scaled_v_plane[curr_src_idx], + dst_width>>1, + vf_x_scale, + vf_curr_NSweight_vu, + src_linestride_vu ); + // work line u + bilinear_scale_line_w8( u_plane[curr_src_idx]+curr_lsoff_u, + scaled_u_plane[curr_src_idx], + dst_width>>1, + vf_x_scale, + vf_curr_NSweight_vu, + src_linestride_vu ); + + //--------------------------------------------------------------------------------------------- + DMA_WAIT_TAG( (STR_BUF+curr_dst_idx) ); + + // Perform three DMA transfers to 3 different locations in the main memory! + // dst_width: Pixel width of destination image + // dst_addr: Destination address in main memory + // dst_vu: Counter which is incremented one by one + // dst_y: Counter which is twice larger than dst_vu (dst_y = 2*dst_vu) + + mfc_put( scaled_y_plane[curr_src_idx], // What from local store (addr) + (unsigned int) dst_addr_main_memory_y + (dst_vu*dst_dbl_linestride_y), // Destination in main memory (addr) + dst_dbl_linestride_y, // Two Y lines (depending on the widht of the destination resolution) + STR_BUF+curr_dst_idx, // Tag + 0, 0 ); + + mfc_put( scaled_v_plane[curr_src_idx], // What from local store (addr) + (unsigned int) dst_addr_main_memory_v + (dst_vu*dst_dbl_linestride_vu), // Destination in main memory (addr) + dst_dbl_linestride_vu, // Two V lines (depending on the widht of the destination resolution) + STR_BUF+curr_dst_idx, // Tag + 0, 0 ); + + mfc_put( scaled_u_plane[curr_src_idx], // What from local store (addr) + (unsigned int) dst_addr_main_memory_u + (dst_vu*dst_dbl_linestride_vu), // Destination in main memory (addr) + dst_dbl_linestride_vu, // Two U lines (depending on the widht of the destination resolution) + STR_BUF+curr_dst_idx, // Tag + 0, 0 ); + //--------------------------------------------------------------------------------------------- + + + // update for next cycle + curr_src_idx = next_src_idx; + curr_dst_idx = next_dst_idx; + + curr_interpl_y_upper = next_interpl_y_upper; + curr_interpl_y_lower = next_interpl_y_lower; + curr_interpl_vu = next_interpl_vu; + + vf_curr_NSweight_y_upper = vf_curr_NSweight_y_upper; + vf_curr_NSweight_y_lower = vf_curr_NSweight_y_lower; + vf_curr_NSweight_vu = vf_next_NSweight_vu; + + curr_src_y_upper = next_src_y_upper; + curr_src_y_lower = next_src_y_lower; + curr_src_vu = next_src_vu; + + curr_lsoff_v = next_lsoff_v; + curr_lsoff_u = next_lsoff_u; + } + + + + DMA_WAIT_TAG( (RETR_BUF+curr_src_idx) ); + + // scaling + // work line y_upper + bilinear_scale_line_w16( y_plane[curr_src_idx], + scaled_y_plane[curr_src_idx], + dst_width, + vf_x_scale, + vf_curr_NSweight_y_upper, + src_linestride_y ); + // work line y_lower + bilinear_scale_line_w16( y_plane[curr_src_idx]+src_dbl_linestride_y, + scaled_y_plane[curr_src_idx]+scaled_src_linestride_y, + dst_width, + vf_x_scale, + vf_curr_NSweight_y_lower, + src_linestride_y ); + // work line v + bilinear_scale_line_w8( v_plane[curr_src_idx]+curr_lsoff_v, + scaled_v_plane[curr_src_idx], + dst_width>>1, + vf_x_scale, + vf_curr_NSweight_vu, + src_linestride_vu ); + // work line u + bilinear_scale_line_w8( u_plane[curr_src_idx]+curr_lsoff_u, + scaled_u_plane[curr_src_idx], + dst_width>>1, + vf_x_scale, + vf_curr_NSweight_vu, + src_linestride_vu ); + + //--------------------------------------------------------------------------------------------- + DMA_WAIT_TAG( (STR_BUF+curr_dst_idx) ); + + // Perform three DMA transfers to 3 different locations in the main memory! + // dst_width: Pixel width of destination image + // dst_addr: Destination address in main memory + // dst_vu: Counter which is incremented one by one + // dst_y: Counter which is twice larger than dst_vu (dst_y = 2*dst_vu) + + mfc_put( scaled_y_plane[curr_src_idx], // What from local store (addr) + (unsigned int) dst_addr_main_memory_y + (dst_vu*dst_dbl_linestride_y), // Destination in main memory (addr) + dst_dbl_linestride_y, // Two Y lines (depending on the widht of the destination resolution) + STR_BUF+curr_dst_idx, // Tag + 0, 0 ); + + mfc_put( scaled_v_plane[curr_src_idx], // What from local store (addr) + (unsigned int) dst_addr_main_memory_v + (dst_vu*dst_dbl_linestride_vu), // Destination in main memory (addr) + dst_dbl_linestride_vu, // Two V lines (depending on the widht of the destination resolution) + STR_BUF+curr_dst_idx, // Tag + 0, 0 ); + + mfc_put( scaled_u_plane[curr_src_idx], // What from local store (addr) + (unsigned int) dst_addr_main_memory_u + (dst_vu*dst_dbl_linestride_vu), // Destination in main memory (addr) + dst_dbl_linestride_vu, // Two U lines (depending on the widht of the destination resolution) + STR_BUF+curr_dst_idx, // Tag + 0, 0 ); + + // wait for completion + DMA_WAIT_TAG( (STR_BUF+curr_dst_idx) ); + //--------------------------------------------------------------------------------------------- +} + + +/* + * scale_srcw32_dstw16() + * + * processes an input image of width 32 + * scaling is done to a width 16 + * yuv2rgb conversion on a width of 16 + * result stored in RAM + */ +void scale_srcw32_dstw16() { + // extract parameters + unsigned char* dst_addr = (unsigned char *)parms.dstBuffer; + + unsigned int src_width = parms.src_pixel_width; + unsigned int src_height = parms.src_pixel_height; + unsigned int dst_width = parms.dst_pixel_width; + unsigned int dst_height = parms.dst_pixel_height; + + // YVU + unsigned int src_linestride_y = src_width; + unsigned int src_dbl_linestride_y = src_width<<1; + unsigned int src_linestride_vu = src_width>>1; + unsigned int src_dbl_linestride_vu = src_width; + // scaled YVU + unsigned int scaled_src_linestride_y = dst_width; + + // ram addresses + unsigned char* src_addr_y = parms.y_plane; + unsigned char* src_addr_v = parms.v_plane; + unsigned char* src_addr_u = parms.u_plane; + + unsigned int dst_picture_size = dst_width*dst_height; + + // Sizes for destination + unsigned int dst_dbl_linestride_y = dst_width<<1; + unsigned int dst_dbl_linestride_vu = dst_width>>1; + + // Perform address calculation for Y, V and U in main memory with dst_addr as base + unsigned char* dst_addr_main_memory_y = dst_addr; + unsigned char* dst_addr_main_memory_v = dst_addr + dst_picture_size; + unsigned char* dst_addr_main_memory_u = dst_addr_main_memory_v +(dst_picture_size>>2); + + // calculate scale factors + vector float vf_x_scale = spu_splats( (float)src_width/(float)dst_width ); + float y_scale = (float)src_height/(float)dst_height; + + // double buffered processing + // buffer switching + unsigned int curr_src_idx = 0; + unsigned int curr_dst_idx = 0; + unsigned int next_src_idx, next_dst_idx; + + // 2 lines y as output, upper and lowerline + unsigned int curr_interpl_y_upper = 0; + unsigned int next_interpl_y_upper; + unsigned int curr_interpl_y_lower, next_interpl_y_lower; + // only 1 line v/u output, both planes have the same dimension + unsigned int curr_interpl_vu = 0; + unsigned int next_interpl_vu; + + // weights, calculated in every loop iteration + vector float vf_curr_NSweight_y_upper = { 0.0f, 0.0f, 0.0f, 0.0f }; + vector float vf_next_NSweight_y_upper; + vector float vf_curr_NSweight_y_lower, vf_next_NSweight_y_lower; + vector float vf_curr_NSweight_vu = { 0.0f, 0.0f, 0.0f, 0.0f }; + vector float vf_next_NSweight_vu; + + // line indices for the src picture + float curr_src_y_upper = 0.0f, next_src_y_upper; + float curr_src_y_lower, next_src_y_lower; + float curr_src_vu = 0.0f, next_src_vu; + + // line indices for the dst picture + unsigned int dst_y=0, dst_vu=0; + + // calculate lower line idices + curr_src_y_lower = ((float)curr_interpl_y_upper+1)*y_scale; + curr_interpl_y_lower = (unsigned int)curr_src_y_lower; + // lower line weight + vf_curr_NSweight_y_lower = spu_splats( curr_src_y_lower-(float)curr_interpl_y_lower ); + + + // start partially double buffered processing + // get initial data, 2 sets of y, 1 set v, 1 set u + mfc_get( y_plane[curr_src_idx], (unsigned int) src_addr_y, src_dbl_linestride_y, RETR_BUF, 0, 0 ); + mfc_get( y_plane[curr_src_idx]+src_dbl_linestride_y, + (unsigned int) src_addr_y+(curr_interpl_y_lower*src_linestride_y), + src_dbl_linestride_y, + RETR_BUF, + 0, 0 ); + mfc_get( v_plane[curr_src_idx], (unsigned int) src_addr_v, src_dbl_linestride_vu, RETR_BUF, 0, 0 ); + mfc_get( u_plane[curr_src_idx], (unsigned int) src_addr_u, src_dbl_linestride_vu, RETR_BUF, 0, 0 ); + + // iteration loop + // within each iteration 4 lines y, 2 lines v, 2 lines u are retrieved + // the scaled output is 2 lines y, 1 line v, 1 line u + // the yuv2rgb-converted output is stored to RAM + for( dst_vu=0; dst_vu<(dst_height>>1)-1; dst_vu++ ) { + dst_y = dst_vu<<1; + + // calculate next indices + next_src_vu = ((float)dst_vu+1)*y_scale; + next_src_y_upper = ((float)dst_y+2)*y_scale; + next_src_y_lower = ((float)dst_y+3)*y_scale; + + next_interpl_vu = (unsigned int) next_src_vu; + next_interpl_y_upper = (unsigned int) next_src_y_upper; + next_interpl_y_lower = (unsigned int) next_src_y_lower; + + // calculate weight NORTH-SOUTH + vf_next_NSweight_vu = spu_splats( next_src_vu-(float)next_interpl_vu ); + vf_next_NSweight_y_upper = spu_splats( next_src_y_upper-(float)next_interpl_y_upper ); + vf_next_NSweight_y_lower = spu_splats( next_src_y_lower-(float)next_interpl_y_lower ); + + // get next lines + next_src_idx = curr_src_idx^1; + next_dst_idx = curr_dst_idx^1; + + // 4 lines y + mfc_get( y_plane[next_src_idx], + (unsigned int) src_addr_y+(next_interpl_y_upper*src_linestride_y), + src_dbl_linestride_y, + RETR_BUF+next_src_idx, + 0, 0 ); + mfc_get( y_plane[next_src_idx]+src_dbl_linestride_y, + (unsigned int) src_addr_y+(next_interpl_y_lower*src_linestride_y), + src_dbl_linestride_y, + RETR_BUF+next_src_idx, + 0, 0 ); + + // 2 lines v + mfc_get( v_plane[next_src_idx], + (unsigned int) src_addr_v+(next_interpl_vu*src_linestride_vu), + src_dbl_linestride_vu, + RETR_BUF+next_src_idx, + 0, 0 ); + // 2 lines u + mfc_get( u_plane[next_src_idx], + (unsigned int) src_addr_u+(next_interpl_vu*src_linestride_vu), + src_dbl_linestride_vu, + RETR_BUF+next_src_idx, + 0, 0 ); + + DMA_WAIT_TAG( (RETR_BUF+curr_src_idx) ); + + // scaling + // work line y_upper + bilinear_scale_line_w16( y_plane[curr_src_idx], + scaled_y_plane[curr_src_idx], + dst_width, + vf_x_scale, + vf_curr_NSweight_y_upper, + src_linestride_y ); + // work line y_lower + bilinear_scale_line_w16( y_plane[curr_src_idx]+src_dbl_linestride_y, + scaled_y_plane[curr_src_idx]+scaled_src_linestride_y, + dst_width, + vf_x_scale, + vf_curr_NSweight_y_lower, + src_linestride_y ); + // work line v + bilinear_scale_line_w16( v_plane[curr_src_idx], + scaled_v_plane[curr_src_idx], + dst_width>>1, + vf_x_scale, + vf_curr_NSweight_vu, + src_linestride_vu ); + // work line u + bilinear_scale_line_w16( u_plane[curr_src_idx], + scaled_u_plane[curr_src_idx], + dst_width>>1, + vf_x_scale, + vf_curr_NSweight_vu, + src_linestride_vu ); + + //--------------------------------------------------------------------------------------------- + DMA_WAIT_TAG( (STR_BUF+curr_dst_idx) ); + + // Perform three DMA transfers to 3 different locations in the main memory! + // dst_width: Pixel width of destination image + // dst_addr: Destination address in main memory + // dst_vu: Counter which is incremented one by one + // dst_y: Counter which is twice larger than dst_vu (dst_y = 2*dst_vu) + + mfc_put( scaled_y_plane[curr_src_idx], // What from local store (addr) + (unsigned int) dst_addr_main_memory_y + (dst_vu*dst_dbl_linestride_y), // Destination in main memory (addr) + dst_dbl_linestride_y, // Two Y lines (depending on the widht of the destination resolution) + STR_BUF+curr_dst_idx, // Tag + 0, 0 ); + + mfc_put( scaled_v_plane[curr_src_idx], // What from local store (addr) + (unsigned int) dst_addr_main_memory_v + (dst_vu*dst_dbl_linestride_vu), // Destination in main memory (addr) + dst_dbl_linestride_vu, // Two V lines (depending on the widht of the destination resolution) + STR_BUF+curr_dst_idx, // Tag + 0, 0 ); + + mfc_put( scaled_u_plane[curr_src_idx], // What from local store (addr) + (unsigned int) dst_addr_main_memory_u + (dst_vu*dst_dbl_linestride_vu), // Destination in main memory (addr) + dst_dbl_linestride_vu, // Two U lines (depending on the widht of the destination resolution) + STR_BUF+curr_dst_idx, // Tag + 0, 0 ); + //--------------------------------------------------------------------------------------------- + + + // update for next cycle + curr_src_idx = next_src_idx; + curr_dst_idx = next_dst_idx; + + curr_interpl_y_upper = next_interpl_y_upper; + curr_interpl_y_lower = next_interpl_y_lower; + curr_interpl_vu = next_interpl_vu; + + vf_curr_NSweight_y_upper = vf_curr_NSweight_y_upper; + vf_curr_NSweight_y_lower = vf_curr_NSweight_y_lower; + vf_curr_NSweight_vu = vf_next_NSweight_vu; + + curr_src_y_upper = next_src_y_upper; + curr_src_y_lower = next_src_y_lower; + curr_src_vu = next_src_vu; + } + + + + DMA_WAIT_TAG( (RETR_BUF+curr_src_idx) ); + + // scaling + // work line y_upper + bilinear_scale_line_w16( y_plane[curr_src_idx], + scaled_y_plane[curr_src_idx], + dst_width, + vf_x_scale, + vf_curr_NSweight_y_upper, + src_linestride_y ); + // work line y_lower + bilinear_scale_line_w16( y_plane[curr_src_idx]+src_dbl_linestride_y, + scaled_y_plane[curr_src_idx]+scaled_src_linestride_y, + dst_width, + vf_x_scale, + vf_curr_NSweight_y_lower, + src_linestride_y ); + // work line v + bilinear_scale_line_w16( v_plane[curr_src_idx], + scaled_v_plane[curr_src_idx], + dst_width>>1, + vf_x_scale, + vf_curr_NSweight_vu, + src_linestride_vu ); + // work line u + bilinear_scale_line_w16( u_plane[curr_src_idx], + scaled_u_plane[curr_src_idx], + dst_width>>1, + vf_x_scale, + vf_curr_NSweight_vu, + src_linestride_vu ); + + + //--------------------------------------------------------------------------------------------- + DMA_WAIT_TAG( (STR_BUF+curr_dst_idx) ); + + // Perform three DMA transfers to 3 different locations in the main memory! + // dst_width: Pixel width of destination image + // dst_addr: Destination address in main memory + // dst_vu: Counter which is incremented one by one + // dst_y: Counter which is twice larger than dst_vu (dst_y = 2*dst_vu) + + mfc_put( scaled_y_plane[curr_src_idx], // What from local store (addr) + (unsigned int) dst_addr_main_memory_y + (dst_vu*dst_dbl_linestride_y), // Destination in main memory (addr) + dst_dbl_linestride_y, // Two Y lines (depending on the widht of the destination resolution) + STR_BUF+curr_dst_idx, // Tag + 0, 0 ); + + mfc_put( scaled_v_plane[curr_src_idx], // What from local store (addr) + (unsigned int) dst_addr_main_memory_v + (dst_vu*dst_dbl_linestride_vu), // Destination in main memory (addr) + dst_dbl_linestride_vu, // Two V lines (depending on the widht of the destination resolution) + STR_BUF+curr_dst_idx, // Tag + 0, 0 ); + + mfc_put( scaled_u_plane[curr_src_idx], // What from local store (addr) + (unsigned int) dst_addr_main_memory_u + (dst_vu*dst_dbl_linestride_vu), // Destination in main memory (addr) + dst_dbl_linestride_vu, // Two U lines (depending on the widht of the destination resolution) + STR_BUF+curr_dst_idx, // Tag + 0, 0 ); + + // wait for completion + DMA_WAIT_TAG( (STR_BUF+curr_dst_idx) ); + //--------------------------------------------------------------------------------------------- +} + + +/** + * scale_srcw32_dstw32() + * + * processes an input image of width 32 + * scaling is done to a width 32 + * yuv2rgb conversion on a width of 32 + * result stored in RAM + */ +void scale_srcw32_dstw32() { + // extract parameters + unsigned char* dst_addr = (unsigned char *)parms.dstBuffer; + + unsigned int src_width = parms.src_pixel_width; + unsigned int src_height = parms.src_pixel_height; + unsigned int dst_width = parms.dst_pixel_width; + unsigned int dst_height = parms.dst_pixel_height; + + // YVU + unsigned int src_linestride_y = src_width; + unsigned int src_dbl_linestride_y = src_width<<1; + unsigned int src_linestride_vu = src_width>>1; + unsigned int src_dbl_linestride_vu = src_width; + + // scaled YVU + unsigned int scaled_src_linestride_y = dst_width; + + // ram addresses + unsigned char* src_addr_y = parms.y_plane; + unsigned char* src_addr_v = parms.v_plane; + unsigned char* src_addr_u = parms.u_plane; + + unsigned int dst_picture_size = dst_width*dst_height; + + // Sizes for destination + unsigned int dst_dbl_linestride_y = dst_width<<1; + unsigned int dst_dbl_linestride_vu = dst_width>>1; + + // Perform address calculation for Y, V and U in main memory with dst_addr as base + unsigned char* dst_addr_main_memory_y = dst_addr; + unsigned char* dst_addr_main_memory_v = dst_addr + dst_picture_size; + unsigned char* dst_addr_main_memory_u = dst_addr_main_memory_v +(dst_picture_size>>2); + + // calculate scale factors + vector float vf_x_scale = spu_splats( (float)src_width/(float)dst_width ); + float y_scale = (float)src_height/(float)dst_height; + + // double buffered processing + // buffer switching + unsigned int curr_src_idx = 0; + unsigned int curr_dst_idx = 0; + unsigned int next_src_idx, next_dst_idx; + + // 2 lines y as output, upper and lowerline + unsigned int curr_interpl_y_upper = 0; + unsigned int next_interpl_y_upper; + unsigned int curr_interpl_y_lower, next_interpl_y_lower; + // only 1 line v/u output, both planes have the same dimension + unsigned int curr_interpl_vu = 0; + unsigned int next_interpl_vu; + + // weights, calculated in every loop iteration + vector float vf_curr_NSweight_y_upper = { 0.0f, 0.0f, 0.0f, 0.0f }; + vector float vf_next_NSweight_y_upper; + vector float vf_curr_NSweight_y_lower, vf_next_NSweight_y_lower; + vector float vf_curr_NSweight_vu = { 0.0f, 0.0f, 0.0f, 0.0f }; + vector float vf_next_NSweight_vu; + + // line indices for the src picture + float curr_src_y_upper = 0.0f, next_src_y_upper; + float curr_src_y_lower, next_src_y_lower; + float curr_src_vu = 0.0f, next_src_vu; + + // line indices for the dst picture + unsigned int dst_y=0, dst_vu=0; + + // calculate lower line idices + curr_src_y_lower = ((float)curr_interpl_y_upper+1)*y_scale; + curr_interpl_y_lower = (unsigned int)curr_src_y_lower; + // lower line weight + vf_curr_NSweight_y_lower = spu_splats( curr_src_y_lower-(float)curr_interpl_y_lower ); + + + // start partially double buffered processing + // get initial data, 2 sets of y, 1 set v, 1 set u + mfc_get( y_plane[curr_src_idx], (unsigned int) src_addr_y, src_dbl_linestride_y, RETR_BUF, 0, 0 ); + mfc_get( y_plane[curr_src_idx]+src_dbl_linestride_y, + (unsigned int) src_addr_y+(curr_interpl_y_lower*src_linestride_y), + src_dbl_linestride_y, + RETR_BUF, + 0, 0 ); + mfc_get( v_plane[curr_src_idx], (unsigned int) src_addr_v, src_dbl_linestride_vu, RETR_BUF, 0, 0 ); + mfc_get( u_plane[curr_src_idx], (unsigned int) src_addr_u, src_dbl_linestride_vu, RETR_BUF, 0, 0 ); + + // iteration loop + // within each iteration 4 lines y, 2 lines v, 2 lines u are retrieved + // the scaled output is 2 lines y, 1 line v, 1 line u + // the yuv2rgb-converted output is stored to RAM + for( dst_vu=0; dst_vu<(dst_height>>1)-1; dst_vu++ ) { + dst_y = dst_vu<<1; + + // calculate next indices + next_src_vu = ((float)dst_vu+1)*y_scale; + next_src_y_upper = ((float)dst_y+2)*y_scale; + next_src_y_lower = ((float)dst_y+3)*y_scale; + + next_interpl_vu = (unsigned int) next_src_vu; + next_interpl_y_upper = (unsigned int) next_src_y_upper; + next_interpl_y_lower = (unsigned int) next_src_y_lower; + + // calculate weight NORTH-SOUTH + vf_next_NSweight_vu = spu_splats( next_src_vu-(float)next_interpl_vu ); + vf_next_NSweight_y_upper = spu_splats( next_src_y_upper-(float)next_interpl_y_upper ); + vf_next_NSweight_y_lower = spu_splats( next_src_y_lower-(float)next_interpl_y_lower ); + + // get next lines + next_src_idx = curr_src_idx^1; + next_dst_idx = curr_dst_idx^1; + + // 4 lines y + mfc_get( y_plane[next_src_idx], + (unsigned int) src_addr_y+(next_interpl_y_upper*src_linestride_y), + src_dbl_linestride_y, + RETR_BUF+next_src_idx, + 0, 0 ); + mfc_get( y_plane[next_src_idx]+src_dbl_linestride_y, + (unsigned int) src_addr_y+(next_interpl_y_lower*src_linestride_y), + src_dbl_linestride_y, + RETR_BUF+next_src_idx, + 0, 0 ); + + // 2 lines v + mfc_get( v_plane[next_src_idx], + (unsigned int) src_addr_v+(next_interpl_vu*src_linestride_vu), + src_dbl_linestride_vu, + RETR_BUF+next_src_idx, + 0, 0 ); + // 2 lines u + mfc_get( u_plane[next_src_idx], + (unsigned int) src_addr_u+(next_interpl_vu*src_linestride_vu), + src_dbl_linestride_vu, + RETR_BUF+next_src_idx, + 0, 0 ); + + DMA_WAIT_TAG( (RETR_BUF+curr_src_idx) ); + + // scaling + // work line y_upper + bilinear_scale_line_w16( y_plane[curr_src_idx], + scaled_y_plane[curr_src_idx], + dst_width, + vf_x_scale, + vf_curr_NSweight_y_upper, + src_linestride_y ); + // work line y_lower + bilinear_scale_line_w16( y_plane[curr_src_idx]+src_dbl_linestride_y, + scaled_y_plane[curr_src_idx]+scaled_src_linestride_y, + dst_width, + vf_x_scale, + vf_curr_NSweight_y_lower, + src_linestride_y ); + // work line v + bilinear_scale_line_w16( v_plane[curr_src_idx], + scaled_v_plane[curr_src_idx], + dst_width>>1, + vf_x_scale, + vf_curr_NSweight_vu, + src_linestride_vu ); + // work line u + bilinear_scale_line_w16( u_plane[curr_src_idx], + scaled_u_plane[curr_src_idx], + dst_width>>1, + vf_x_scale, + vf_curr_NSweight_vu, + src_linestride_vu ); + + + + // Store the result back to main memory into a destination buffer in YUV format + //--------------------------------------------------------------------------------------------- + DMA_WAIT_TAG( (STR_BUF+curr_dst_idx) ); + + // Perform three DMA transfers to 3 different locations in the main memory! + // dst_width: Pixel width of destination image + // dst_addr: Destination address in main memory + // dst_vu: Counter which is incremented one by one + // dst_y: Counter which is twice larger than dst_vu (dst_y = 2*dst_vu) + + mfc_put( scaled_y_plane[curr_src_idx], // What from local store (addr) + (unsigned int) dst_addr_main_memory_y + (dst_vu*dst_dbl_linestride_y), // Destination in main memory (addr) + dst_dbl_linestride_y, // Two Y lines (depending on the widht of the destination resolution) + STR_BUF+curr_dst_idx, // Tag + 0, 0 ); + + mfc_put( scaled_v_plane[curr_src_idx], // What from local store (addr) + (unsigned int) dst_addr_main_memory_v + (dst_vu*dst_dbl_linestride_vu), // Destination in main memory (addr) + dst_dbl_linestride_vu, // Two V lines (depending on the widht of the destination resolution) + STR_BUF+curr_dst_idx, // Tag + 0, 0 ); + + mfc_put( scaled_u_plane[curr_src_idx], // What from local store (addr) + (unsigned int) dst_addr_main_memory_u + (dst_vu*dst_dbl_linestride_vu), // Destination in main memory (addr) + dst_dbl_linestride_vu, // Two U lines (depending on the widht of the destination resolution) + STR_BUF+curr_dst_idx, // Tag + 0, 0 ); + //--------------------------------------------------------------------------------------------- + + + // update for next cycle + curr_src_idx = next_src_idx; + curr_dst_idx = next_dst_idx; + + curr_interpl_y_upper = next_interpl_y_upper; + curr_interpl_y_lower = next_interpl_y_lower; + curr_interpl_vu = next_interpl_vu; + + vf_curr_NSweight_y_upper = vf_curr_NSweight_y_upper; + vf_curr_NSweight_y_lower = vf_curr_NSweight_y_lower; + vf_curr_NSweight_vu = vf_next_NSweight_vu; + + curr_src_y_upper = next_src_y_upper; + curr_src_y_lower = next_src_y_lower; + curr_src_vu = next_src_vu; + } + + + + DMA_WAIT_TAG( (RETR_BUF+curr_src_idx) ); + + // scaling + // work line y_upper + bilinear_scale_line_w16( y_plane[curr_src_idx], + scaled_y_plane[curr_src_idx], + dst_width, + vf_x_scale, + vf_curr_NSweight_y_upper, + src_linestride_y ); + // work line y_lower + bilinear_scale_line_w16( y_plane[curr_src_idx]+src_dbl_linestride_y, + scaled_y_plane[curr_src_idx]+scaled_src_linestride_y, + dst_width, + vf_x_scale, + vf_curr_NSweight_y_lower, + src_linestride_y ); + // work line v + bilinear_scale_line_w16( v_plane[curr_src_idx], + scaled_v_plane[curr_src_idx], + dst_width>>1, + vf_x_scale, + vf_curr_NSweight_vu, + src_linestride_vu ); + // work line u + bilinear_scale_line_w16( u_plane[curr_src_idx], + scaled_u_plane[curr_src_idx], + dst_width>>1, + vf_x_scale, + vf_curr_NSweight_vu, + src_linestride_vu ); + + + // Store the result back to main memory into a destination buffer in YUV format + //--------------------------------------------------------------------------------------------- + DMA_WAIT_TAG( (STR_BUF+curr_dst_idx) ); + + // Perform three DMA transfers to 3 different locations in the main memory! + // dst_width: Pixel width of destination image + // dst_addr: Destination address in main memory + // dst_vu: Counter which is incremented one by one + // dst_y: Counter which is twice larger than dst_vu (dst_y = 2*dst_vu) + + mfc_put( scaled_y_plane[curr_src_idx], // What from local store (addr) + (unsigned int) dst_addr_main_memory_y + (dst_vu*dst_dbl_linestride_y), // Destination in main memory (addr) + dst_dbl_linestride_y, // Two Y lines (depending on the widht of the destination resolution) + STR_BUF+curr_dst_idx, // Tag + 0, 0 ); + + mfc_put( scaled_v_plane[curr_src_idx], // What from local store (addr) + (unsigned int) dst_addr_main_memory_v + (dst_vu*dst_dbl_linestride_vu), // Destination in main memory (addr) + dst_dbl_linestride_vu, // Two V lines (depending on the widht of the destination resolution) + STR_BUF+curr_dst_idx, // Tag + 0, 0 ); + + mfc_put( scaled_u_plane[curr_src_idx], // What from local store (addr) + (unsigned int) dst_addr_main_memory_u + (dst_vu*dst_dbl_linestride_vu), // Destination in main memory (addr) + dst_dbl_linestride_vu, // Two U lines (depending on the widht of the destination resolution) + STR_BUF+curr_dst_idx, // Tag + 0, 0 ); + + // wait for completion + DMA_WAIT_TAG( (STR_BUF+curr_dst_idx) ); + //--------------------------------------------------------------------------------------------- +} + + +/* + * bilinear_scale_line_w8() + * + * processes a line of yuv-input, width has to be a multiple of 8 + * scaled yuv-output is written to local store buffer + * + * @param src buffer for 2 lines input + * @param dst_ buffer for 1 line output + * @param dst_width the width of the destination line + * @param vf_x_scale a float vector, at each entry is the x_scale-factor + * @param vf_NSweight a float vector, at each position is the weight NORTH/SOUTH for the current line + * @param src_linestride the stride of the srcline + */ +void bilinear_scale_line_w8( unsigned char* src, unsigned char* dst_, unsigned int dst_width, vector float vf_x_scale, vector float vf_NSweight, unsigned int src_linestride ) { + + unsigned char* dst = dst_; + + unsigned int dst_x; + for( dst_x=0; dst_x<dst_width; dst_x+=8) { + // address calculation for loading the 4 surrounding pixel of each calculated + // destination pixel + vector unsigned int vui_dst_x_tmp = spu_splats( dst_x ); + // lower range->first 4 pixel + // upper range->next 4 pixel + vector unsigned int vui_inc_dst_x_lower_range = { 0, 1, 2, 3 }; + vector unsigned int vui_inc_dst_x_upper_range = { 4, 5, 6, 7 }; + vector unsigned int vui_dst_x_lower_range = spu_add( vui_dst_x_tmp, vui_inc_dst_x_lower_range ); + vector unsigned int vui_dst_x_upper_range = spu_add( vui_dst_x_tmp, vui_inc_dst_x_upper_range ); + + // calculate weight EAST-WEST + vector float vf_dst_x_lower_range = spu_convtf( vui_dst_x_lower_range, 0 ); + vector float vf_dst_x_upper_range = spu_convtf( vui_dst_x_upper_range, 0 ); + vector float vf_src_x_lower_range = spu_mul( vf_dst_x_lower_range, vf_x_scale ); + vector float vf_src_x_upper_range = spu_mul( vf_dst_x_upper_range, vf_x_scale ); + vector unsigned int vui_interpl_x_lower_range = spu_convtu( vf_src_x_lower_range, 0 ); + vector unsigned int vui_interpl_x_upper_range = spu_convtu( vf_src_x_upper_range, 0 ); + vector float vf_interpl_x_lower_range = spu_convtf( vui_interpl_x_lower_range, 0 ); + vector float vf_interpl_x_upper_range = spu_convtf( vui_interpl_x_upper_range, 0 ); + vector float vf_EWweight_lower_range = spu_sub( vf_src_x_lower_range, vf_interpl_x_lower_range ); + vector float vf_EWweight_upper_range = spu_sub( vf_src_x_upper_range, vf_interpl_x_upper_range ); + + // calculate address offset + // + // pixel NORTH WEST + vector unsigned int vui_off_pixelNW_lower_range = vui_interpl_x_lower_range; + vector unsigned int vui_off_pixelNW_upper_range = vui_interpl_x_upper_range; + + // pixel NORTH EAST-->(offpixelNW+1) + vector unsigned int vui_add_1 = { 1, 1, 1, 1 }; + vector unsigned int vui_off_pixelNE_lower_range = spu_add( vui_off_pixelNW_lower_range, vui_add_1 ); + vector unsigned int vui_off_pixelNE_upper_range = spu_add( vui_off_pixelNW_upper_range, vui_add_1 ); + + // SOUTH-WEST-->(offpixelNW+src_linestride) + vector unsigned int vui_srclinestride = spu_splats( src_linestride ); + vector unsigned int vui_off_pixelSW_lower_range = spu_add( vui_srclinestride, vui_off_pixelNW_lower_range ); + vector unsigned int vui_off_pixelSW_upper_range = spu_add( vui_srclinestride, vui_off_pixelNW_upper_range ); + + // SOUTH-EAST-->(offpixelNW+src_linestride+1) + vector unsigned int vui_off_pixelSE_lower_range = spu_add( vui_srclinestride, vui_off_pixelNE_lower_range ); + vector unsigned int vui_off_pixelSE_upper_range = spu_add( vui_srclinestride, vui_off_pixelNE_upper_range ); + + // calculate each address + vector unsigned int vui_src_ls = spu_splats( (unsigned int) src ); + vector unsigned int vui_addr_pixelNW_lower_range = spu_add( vui_src_ls, vui_off_pixelNW_lower_range ); + vector unsigned int vui_addr_pixelNW_upper_range = spu_add( vui_src_ls, vui_off_pixelNW_upper_range ); + vector unsigned int vui_addr_pixelNE_lower_range = spu_add( vui_src_ls, vui_off_pixelNE_lower_range ); + vector unsigned int vui_addr_pixelNE_upper_range = spu_add( vui_src_ls, vui_off_pixelNE_upper_range ); + + vector unsigned int vui_addr_pixelSW_lower_range = spu_add( vui_src_ls, vui_off_pixelSW_lower_range ); + vector unsigned int vui_addr_pixelSW_upper_range = spu_add( vui_src_ls, vui_off_pixelSW_upper_range ); + vector unsigned int vui_addr_pixelSE_lower_range = spu_add( vui_src_ls, vui_off_pixelSE_lower_range ); + vector unsigned int vui_addr_pixelSE_upper_range = spu_add( vui_src_ls, vui_off_pixelSE_upper_range ); + + // get each pixel + // + // scalar load, afterwards insertion into the right position + // NORTH WEST + vector unsigned char null_vector = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; + vector unsigned char vuc_pixel_NW_lower_range = spu_insert( + *((unsigned char*) spu_extract( vui_addr_pixelNW_lower_range, 0 )), null_vector, 3 ); + vuc_pixel_NW_lower_range = spu_insert( + *((unsigned char*) spu_extract( vui_addr_pixelNW_lower_range, 1 )), + vuc_pixel_NW_lower_range, 7 ); + vuc_pixel_NW_lower_range = spu_insert( + *((unsigned char*) spu_extract( vui_addr_pixelNW_lower_range, 2 )), + vuc_pixel_NW_lower_range, 11 ); + vuc_pixel_NW_lower_range = spu_insert( + *((unsigned char*) spu_extract( vui_addr_pixelNW_lower_range, 3 )), + vuc_pixel_NW_lower_range, 15 ); + + vector unsigned char vuc_pixel_NW_upper_range = spu_insert( + *((unsigned char*) spu_extract( vui_addr_pixelNW_upper_range, 0 )), null_vector, 3 ); + vuc_pixel_NW_upper_range = spu_insert( + *((unsigned char*) spu_extract( vui_addr_pixelNW_upper_range, 1 )), + vuc_pixel_NW_upper_range, 7 ); + vuc_pixel_NW_upper_range = spu_insert( + *((unsigned char*) spu_extract( vui_addr_pixelNW_upper_range, 2 )), + vuc_pixel_NW_upper_range, 11 ); + vuc_pixel_NW_upper_range = spu_insert( + *((unsigned char*) spu_extract( vui_addr_pixelNW_upper_range, 3 )), + vuc_pixel_NW_upper_range, 15 ); + + // NORTH EAST + vector unsigned char vuc_pixel_NE_lower_range = spu_insert( + *((unsigned char*) spu_extract( vui_addr_pixelNE_lower_range, 0 )), null_vector, 3 ); + vuc_pixel_NE_lower_range = spu_insert( + *((unsigned char*) spu_extract( vui_addr_pixelNE_lower_range, 1 )), + vuc_pixel_NE_lower_range, 7 ); + vuc_pixel_NE_lower_range = spu_insert( + *((unsigned char*) spu_extract( vui_addr_pixelNE_lower_range, 2 )), + vuc_pixel_NE_lower_range, 11 ); + vuc_pixel_NE_lower_range = spu_insert( + *((unsigned char*) spu_extract( vui_addr_pixelNE_lower_range, 3 )), + vuc_pixel_NE_lower_range, 15 ); + + vector unsigned char vuc_pixel_NE_upper_range = spu_insert( + *((unsigned char*) spu_extract( vui_addr_pixelNE_upper_range, 0 )), null_vector, 3 ); + vuc_pixel_NE_upper_range = spu_insert( + *((unsigned char*) spu_extract( vui_addr_pixelNE_upper_range, 1 )), + vuc_pixel_NE_upper_range, 7 ); + vuc_pixel_NE_upper_range = spu_insert( + *((unsigned char*) spu_extract( vui_addr_pixelNE_upper_range, 2 )), + vuc_pixel_NE_upper_range, 11 ); + vuc_pixel_NE_upper_range = spu_insert( + *((unsigned char*) spu_extract( vui_addr_pixelNE_upper_range, 3 )), + vuc_pixel_NE_upper_range, 15 ); + + + // SOUTH WEST + vector unsigned char vuc_pixel_SW_lower_range = spu_insert( + *((unsigned char*) spu_extract( vui_addr_pixelSW_lower_range, 0 )), null_vector, 3 ); + vuc_pixel_SW_lower_range = spu_insert( + *((unsigned char*) spu_extract( vui_addr_pixelSW_lower_range, 1 )), + vuc_pixel_SW_lower_range, 7 ); + vuc_pixel_SW_lower_range = spu_insert( + *((unsigned char*) spu_extract( vui_addr_pixelSW_lower_range, 2 )), + vuc_pixel_SW_lower_range, 11 ); + vuc_pixel_SW_lower_range = spu_insert( + *((unsigned char*) spu_extract( vui_addr_pixelSW_lower_range, 3 )), + vuc_pixel_SW_lower_range, 15 ); + + vector unsigned char vuc_pixel_SW_upper_range = spu_insert( + *((unsigned char*) spu_extract( vui_addr_pixelSW_upper_range, 0 )), null_vector, 3 ); + vuc_pixel_SW_upper_range = spu_insert( + *((unsigned char*) spu_extract( vui_addr_pixelSW_upper_range, 1 )), + vuc_pixel_SW_upper_range, 7 ); + vuc_pixel_SW_upper_range = spu_insert( + *((unsigned char*) spu_extract( vui_addr_pixelSW_upper_range, 2 )), + vuc_pixel_SW_upper_range, 11 ); + vuc_pixel_SW_upper_range = spu_insert( + *((unsigned char*) spu_extract( vui_addr_pixelSW_upper_range, 3 )), + vuc_pixel_SW_upper_range, 15 ); + + // SOUTH EAST + vector unsigned char vuc_pixel_SE_lower_range = spu_insert( + *((unsigned char*) spu_extract( vui_addr_pixelSE_lower_range, 0 )), null_vector, 3 ); + vuc_pixel_SE_lower_range = spu_insert( + *((unsigned char*) spu_extract( vui_addr_pixelSE_lower_range, 1 )), + vuc_pixel_SE_lower_range, 7 ); + vuc_pixel_SE_lower_range = spu_insert( + *((unsigned char*) spu_extract( vui_addr_pixelSE_lower_range, 2 )), + vuc_pixel_SE_lower_range, 11 ); + vuc_pixel_SE_lower_range = spu_insert( + *((unsigned char*) spu_extract( vui_addr_pixelSE_lower_range, 3 )), + vuc_pixel_SE_lower_range, 15 ); + + vector unsigned char vuc_pixel_SE_upper_range = spu_insert( + *((unsigned char*) spu_extract( vui_addr_pixelSE_upper_range, 0 )), null_vector, 3 ); + vuc_pixel_SE_upper_range = spu_insert( + *((unsigned char*) spu_extract( vui_addr_pixelSE_upper_range, 1 )), + vuc_pixel_SE_upper_range, 7 ); + vuc_pixel_SE_upper_range = spu_insert( + *((unsigned char*) spu_extract( vui_addr_pixelSE_upper_range, 2 )), + vuc_pixel_SE_upper_range, 11 ); + vuc_pixel_SE_upper_range = spu_insert( + *((unsigned char*) spu_extract( vui_addr_pixelSE_upper_range, 3 )), + vuc_pixel_SE_upper_range, 15 ); + + + // convert to float + vector float vf_pixel_NW_lower_range = spu_convtf( (vector unsigned int) vuc_pixel_NW_lower_range, 0 ); + vector float vf_pixel_NW_upper_range = spu_convtf( (vector unsigned int) vuc_pixel_NW_upper_range, 0 ); + + vector float vf_pixel_SW_lower_range = spu_convtf( (vector unsigned int) vuc_pixel_SW_lower_range, 0 ); + vector float vf_pixel_SW_upper_range = spu_convtf( (vector unsigned int) vuc_pixel_SW_upper_range, 0 ); + + vector float vf_pixel_NE_lower_range = spu_convtf( (vector unsigned int) vuc_pixel_NE_lower_range, 0 ); + vector float vf_pixel_NE_upper_range = spu_convtf( (vector unsigned int) vuc_pixel_NE_upper_range, 0 ); + + vector float vf_pixel_SE_lower_range = spu_convtf( (vector unsigned int) vuc_pixel_SE_lower_range, 0 ); + vector float vf_pixel_SE_upper_range = spu_convtf( (vector unsigned int) vuc_pixel_SE_upper_range, 0 ); + + + + // first linear interpolation: EWtop + // EWtop = NW + EWweight*(NE-NW) + // + // lower range + vector float vf_EWtop_lower_range_tmp = spu_sub( vf_pixel_NE_lower_range, vf_pixel_NW_lower_range ); + vector float vf_EWtop_lower_range = spu_madd( vf_EWweight_lower_range, + vf_EWtop_lower_range_tmp, + vf_pixel_NW_lower_range ); + + // upper range + vector float vf_EWtop_upper_range_tmp = spu_sub( vf_pixel_NE_upper_range, vf_pixel_NW_upper_range ); + vector float vf_EWtop_upper_range = spu_madd( vf_EWweight_upper_range, + vf_EWtop_upper_range_tmp, + vf_pixel_NW_upper_range ); + + + + // second linear interpolation: EWbottom + // EWbottom = SW + EWweight*(SE-SW) + // + // lower range + vector float vf_EWbottom_lower_range_tmp = spu_sub( vf_pixel_SE_lower_range, vf_pixel_SW_lower_range ); + vector float vf_EWbottom_lower_range = spu_madd( vf_EWweight_lower_range, + vf_EWbottom_lower_range_tmp, + vf_pixel_SW_lower_range ); + + // upper range + vector float vf_EWbottom_upper_range_tmp = spu_sub( vf_pixel_SE_upper_range, vf_pixel_SW_upper_range ); + vector float vf_EWbottom_upper_range = spu_madd( vf_EWweight_upper_range, + vf_EWbottom_upper_range_tmp, + vf_pixel_SW_upper_range ); + + + + // third linear interpolation: the bilinear interpolated value + // result = EWtop + NSweight*(EWbottom-EWtop); + // + // lower range + vector float vf_result_lower_range_tmp = spu_sub( vf_EWbottom_lower_range, vf_EWtop_lower_range ); + vector float vf_result_lower_range = spu_madd( vf_NSweight, + vf_result_lower_range_tmp, + vf_EWtop_lower_range ); + + // upper range + vector float vf_result_upper_range_tmp = spu_sub( vf_EWbottom_upper_range, vf_EWtop_upper_range ); + vector float vf_result_upper_range = spu_madd( vf_NSweight, + vf_result_upper_range_tmp, + vf_EWtop_upper_range ); + + + // convert back: using saturated arithmetic + vector unsigned int vui_result_lower_range = vfloat_to_vuint( vf_result_lower_range ); + vector unsigned int vui_result_upper_range = vfloat_to_vuint( vf_result_upper_range ); + + // merge results->lower,upper + vector unsigned char vuc_mask_merge_result = { 0x03, 0x07, 0x0B, 0x0F, + 0x13, 0x17, 0x1B, 0x1F, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00 }; + + vector unsigned char vuc_result = spu_shuffle( (vector unsigned char) vui_result_lower_range, + (vector unsigned char) vui_result_upper_range, + vuc_mask_merge_result ); + + // partial storing + vector unsigned char vuc_mask_out = { 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF }; + + + // get currently stored data + vector unsigned char vuc_orig = *((vector unsigned char*)dst); + + // clear currently stored data + vuc_orig = spu_and( vuc_orig, + spu_rlqwbyte( vuc_mask_out, ((unsigned int)dst)&0x0F) ); + + // rotate result according to storing address + vuc_result = spu_rlqwbyte( vuc_result, ((unsigned int)dst)&0x0F ); + + // store result + *((vector unsigned char*)dst) = spu_or( vuc_result, + vuc_orig ); + dst += 8; + } +} + + +/* + * bilinear_scale_line_w16() + * + * processes a line of yuv-input, width has to be a multiple of 16 + * scaled yuv-output is written to local store buffer + * + * @param src buffer for 2 lines input + * @param dst_ buffer for 1 line output + * @param dst_width the width of the destination line + * @param vf_x_scale a float vector, at each entry is the x_scale-factor + * @param vf_NSweight a float vector, at each position is the weight NORTH/SOUTH for the current line + * @param src_linestride the stride of the srcline + */ +void bilinear_scale_line_w16( unsigned char* src, unsigned char* dst_, unsigned int dst_width, vector float vf_x_scale, vector float vf_NSweight, unsigned int src_linestride ) { + + unsigned char* dst = dst_; + + unsigned int dst_x; + for( dst_x=0; dst_x<dst_width; dst_x+=16) { + // address calculation for loading the 4 surrounding pixel of each calculated + // destination pixel + vector unsigned int vui_dst_x_tmp = spu_splats( dst_x ); + // parallelised processing + // first range->pixel 1 2 3 4 + // second range->pixel 5 6 7 8 + // third range->pixel 9 10 11 12 + // fourth range->pixel 13 14 15 16 + vector unsigned int vui_inc_dst_x_first_range = { 0, 1, 2, 3 }; + vector unsigned int vui_inc_dst_x_second_range = { 4, 5, 6, 7 }; + vector unsigned int vui_inc_dst_x_third_range = { 8, 9, 10, 11 }; + vector unsigned int vui_inc_dst_x_fourth_range = { 12, 13, 14, 15 }; + vector unsigned int vui_dst_x_first_range = spu_add( vui_dst_x_tmp, vui_inc_dst_x_first_range ); + vector unsigned int vui_dst_x_second_range = spu_add( vui_dst_x_tmp, vui_inc_dst_x_second_range ); + vector unsigned int vui_dst_x_third_range = spu_add( vui_dst_x_tmp, vui_inc_dst_x_third_range ); + vector unsigned int vui_dst_x_fourth_range = spu_add( vui_dst_x_tmp, vui_inc_dst_x_fourth_range ); + + // calculate weight EAST-WEST + vector float vf_dst_x_first_range = spu_convtf( vui_dst_x_first_range, 0 ); + vector float vf_dst_x_second_range = spu_convtf( vui_dst_x_second_range, 0 ); + vector float vf_dst_x_third_range = spu_convtf( vui_dst_x_third_range, 0 ); + vector float vf_dst_x_fourth_range = spu_convtf( vui_dst_x_fourth_range, 0 ); + vector float vf_src_x_first_range = spu_mul( vf_dst_x_first_range, vf_x_scale ); + vector float vf_src_x_second_range = spu_mul( vf_dst_x_second_range, vf_x_scale ); + vector float vf_src_x_third_range = spu_mul( vf_dst_x_third_range, vf_x_scale ); + vector float vf_src_x_fourth_range = spu_mul( vf_dst_x_fourth_range, vf_x_scale ); + vector unsigned int vui_interpl_x_first_range = spu_convtu( vf_src_x_first_range, 0 ); + vector unsigned int vui_interpl_x_second_range = spu_convtu( vf_src_x_second_range, 0 ); + vector unsigned int vui_interpl_x_third_range = spu_convtu( vf_src_x_third_range, 0 ); + vector unsigned int vui_interpl_x_fourth_range = spu_convtu( vf_src_x_fourth_range, 0 ); + vector float vf_interpl_x_first_range = spu_convtf( vui_interpl_x_first_range, 0 ); + vector float vf_interpl_x_second_range = spu_convtf( vui_interpl_x_second_range, 0 ); + vector float vf_interpl_x_third_range = spu_convtf( vui_interpl_x_third_range, 0 ); + vector float vf_interpl_x_fourth_range = spu_convtf( vui_interpl_x_fourth_range, 0 ); + vector float vf_EWweight_first_range = spu_sub( vf_src_x_first_range, vf_interpl_x_first_range ); + vector float vf_EWweight_second_range = spu_sub( vf_src_x_second_range, vf_interpl_x_second_range ); + vector float vf_EWweight_third_range = spu_sub( vf_src_x_third_range, vf_interpl_x_third_range ); + vector float vf_EWweight_fourth_range = spu_sub( vf_src_x_fourth_range, vf_interpl_x_fourth_range ); + + // calculate address offset + // + // pixel NORTH WEST + vector unsigned int vui_off_pixelNW_first_range = vui_interpl_x_first_range; + vector unsigned int vui_off_pixelNW_second_range = vui_interpl_x_second_range; + vector unsigned int vui_off_pixelNW_third_range = vui_interpl_x_third_range; + vector unsigned int vui_off_pixelNW_fourth_range = vui_interpl_x_fourth_range; + + // pixel NORTH EAST-->(offpixelNW+1) + vector unsigned int vui_add_1 = { 1, 1, 1, 1 }; + vector unsigned int vui_off_pixelNE_first_range = spu_add( vui_off_pixelNW_first_range, vui_add_1 ); + vector unsigned int vui_off_pixelNE_second_range = spu_add( vui_off_pixelNW_second_range, vui_add_1 ); + vector unsigned int vui_off_pixelNE_third_range = spu_add( vui_off_pixelNW_third_range, vui_add_1 ); + vector unsigned int vui_off_pixelNE_fourth_range = spu_add( vui_off_pixelNW_fourth_range, vui_add_1 ); + + // SOUTH-WEST-->(offpixelNW+src_linestride) + vector unsigned int vui_srclinestride = spu_splats( src_linestride ); + vector unsigned int vui_off_pixelSW_first_range = spu_add( vui_srclinestride, vui_off_pixelNW_first_range ); + vector unsigned int vui_off_pixelSW_second_range = spu_add( vui_srclinestride, vui_off_pixelNW_second_range ); + vector unsigned int vui_off_pixelSW_third_range = spu_add( vui_srclinestride, vui_off_pixelNW_third_range ); + vector unsigned int vui_off_pixelSW_fourth_range = spu_add( vui_srclinestride, vui_off_pixelNW_fourth_range ); + + // SOUTH-EAST-->(offpixelNW+src_linestride+1) + vector unsigned int vui_off_pixelSE_first_range = spu_add( vui_srclinestride, vui_off_pixelNE_first_range ); + vector unsigned int vui_off_pixelSE_second_range = spu_add( vui_srclinestride, vui_off_pixelNE_second_range ); + vector unsigned int vui_off_pixelSE_third_range = spu_add( vui_srclinestride, vui_off_pixelNE_third_range ); + vector unsigned int vui_off_pixelSE_fourth_range = spu_add( vui_srclinestride, vui_off_pixelNE_fourth_range ); + + // calculate each address + vector unsigned int vui_src_ls = spu_splats( (unsigned int) src ); + vector unsigned int vui_addr_pixelNW_first_range = spu_add( vui_src_ls, vui_off_pixelNW_first_range ); + vector unsigned int vui_addr_pixelNW_second_range = spu_add( vui_src_ls, vui_off_pixelNW_second_range ); + vector unsigned int vui_addr_pixelNW_third_range = spu_add( vui_src_ls, vui_off_pixelNW_third_range ); + vector unsigned int vui_addr_pixelNW_fourth_range = spu_add( vui_src_ls, vui_off_pixelNW_fourth_range ); + + vector unsigned int vui_addr_pixelNE_first_range = spu_add( vui_src_ls, vui_off_pixelNE_first_range ); + vector unsigned int vui_addr_pixelNE_second_range = spu_add( vui_src_ls, vui_off_pixelNE_second_range ); + vector unsigned int vui_addr_pixelNE_third_range = spu_add( vui_src_ls, vui_off_pixelNE_third_range ); + vector unsigned int vui_addr_pixelNE_fourth_range = spu_add( vui_src_ls, vui_off_pixelNE_fourth_range ); + + vector unsigned int vui_addr_pixelSW_first_range = spu_add( vui_src_ls, vui_off_pixelSW_first_range ); + vector unsigned int vui_addr_pixelSW_second_range = spu_add( vui_src_ls, vui_off_pixelSW_second_range ); + vector unsigned int vui_addr_pixelSW_third_range = spu_add( vui_src_ls, vui_off_pixelSW_third_range ); + vector unsigned int vui_addr_pixelSW_fourth_range = spu_add( vui_src_ls, vui_off_pixelSW_fourth_range ); + + vector unsigned int vui_addr_pixelSE_first_range = spu_add( vui_src_ls, vui_off_pixelSE_first_range ); + vector unsigned int vui_addr_pixelSE_second_range = spu_add( vui_src_ls, vui_off_pixelSE_second_range ); + vector unsigned int vui_addr_pixelSE_third_range = spu_add( vui_src_ls, vui_off_pixelSE_third_range ); + vector unsigned int vui_addr_pixelSE_fourth_range = spu_add( vui_src_ls, vui_off_pixelSE_fourth_range ); + + + // get each pixel + // + // scalar load, afterwards insertion into the right position + // NORTH WEST + // first range + vector unsigned char null_vector = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; + vector unsigned char vuc_pixel_NW_first_range = spu_insert( + *((unsigned char*) spu_extract( vui_addr_pixelNW_first_range, 0 )), null_vector, 3 ); + vuc_pixel_NW_first_range = spu_insert( + *((unsigned char*) spu_extract( vui_addr_pixelNW_first_range, 1 )), + vuc_pixel_NW_first_range, 7 ); + vuc_pixel_NW_first_range = spu_insert( + *((unsigned char*) spu_extract( vui_addr_pixelNW_first_range, 2 )), + vuc_pixel_NW_first_range, 11 ); + vuc_pixel_NW_first_range = spu_insert( + *((unsigned char*) spu_extract( vui_addr_pixelNW_first_range, 3 )), + vuc_pixel_NW_first_range, 15 ); + // second range + vector unsigned char vuc_pixel_NW_second_range = spu_insert( + *((unsigned char*) spu_extract( vui_addr_pixelNW_second_range, 0 )), null_vector, 3 ); + vuc_pixel_NW_second_range = spu_insert( + *((unsigned char*) spu_extract( vui_addr_pixelNW_second_range, 1 )), + vuc_pixel_NW_second_range, 7 ); + vuc_pixel_NW_second_range = spu_insert( + *((unsigned char*) spu_extract( vui_addr_pixelNW_second_range, 2 )), + vuc_pixel_NW_second_range, 11 ); + vuc_pixel_NW_second_range = spu_insert( + *((unsigned char*) spu_extract( vui_addr_pixelNW_second_range, 3 )), + vuc_pixel_NW_second_range, 15 ); + // third range + vector unsigned char vuc_pixel_NW_third_range = spu_insert( + *((unsigned char*) spu_extract( vui_addr_pixelNW_third_range, 0 )), null_vector, 3 ); + vuc_pixel_NW_third_range = spu_insert( + *((unsigned char*) spu_extract( vui_addr_pixelNW_third_range, 1 )), + vuc_pixel_NW_third_range, 7 ); + vuc_pixel_NW_third_range = spu_insert( + *((unsigned char*) spu_extract( vui_addr_pixelNW_third_range, 2 )), + vuc_pixel_NW_third_range, 11 ); + vuc_pixel_NW_third_range = spu_insert( + *((unsigned char*) spu_extract( vui_addr_pixelNW_third_range, 3 )), + vuc_pixel_NW_third_range, 15 ); + // fourth range + vector unsigned char vuc_pixel_NW_fourth_range = spu_insert( + *((unsigned char*) spu_extract( vui_addr_pixelNW_fourth_range, 0 )), null_vector, 3 ); + vuc_pixel_NW_fourth_range = spu_insert( + *((unsigned char*) spu_extract( vui_addr_pixelNW_fourth_range, 1 )), + vuc_pixel_NW_fourth_range, 7 ); + vuc_pixel_NW_fourth_range = spu_insert( + *((unsigned char*) spu_extract( vui_addr_pixelNW_fourth_range, 2 )), + vuc_pixel_NW_fourth_range, 11 ); + vuc_pixel_NW_fourth_range = spu_insert( + *((unsigned char*) spu_extract( vui_addr_pixelNW_fourth_range, 3 )), + vuc_pixel_NW_fourth_range, 15 ); + + // NORTH EAST + // first range + vector unsigned char vuc_pixel_NE_first_range = spu_insert( + *((unsigned char*) spu_extract( vui_addr_pixelNE_first_range, 0 )), null_vector, 3 ); + vuc_pixel_NE_first_range = spu_insert( + *((unsigned char*) spu_extract( vui_addr_pixelNE_first_range, 1 )), + vuc_pixel_NE_first_range, 7 ); + vuc_pixel_NE_first_range = spu_insert( + *((unsigned char*) spu_extract( vui_addr_pixelNE_first_range, 2 )), + vuc_pixel_NE_first_range, 11 ); + vuc_pixel_NE_first_range = spu_insert( + *((unsigned char*) spu_extract( vui_addr_pixelNE_first_range, 3 )), + vuc_pixel_NE_first_range, 15 ); + // second range + vector unsigned char vuc_pixel_NE_second_range = spu_insert( + *((unsigned char*) spu_extract( vui_addr_pixelNE_second_range, 0 )), null_vector, 3 ); + vuc_pixel_NE_second_range = spu_insert( + *((unsigned char*) spu_extract( vui_addr_pixelNE_second_range, 1 )), + vuc_pixel_NE_second_range, 7 ); + vuc_pixel_NE_second_range = spu_insert( + *((unsigned char*) spu_extract( vui_addr_pixelNE_second_range, 2 )), + vuc_pixel_NE_second_range, 11 ); + vuc_pixel_NE_second_range = spu_insert( + *((unsigned char*) spu_extract( vui_addr_pixelNE_second_range, 3 )), + vuc_pixel_NE_second_range, 15 ); + // third range + vector unsigned char vuc_pixel_NE_third_range = spu_insert( + *((unsigned char*) spu_extract( vui_addr_pixelNE_third_range, 0 )), null_vector, 3 ); + vuc_pixel_NE_third_range = spu_insert( + *((unsigned char*) spu_extract( vui_addr_pixelNE_third_range, 1 )), + vuc_pixel_NE_third_range, 7 ); + vuc_pixel_NE_third_range = spu_insert( + *((unsigned char*) spu_extract( vui_addr_pixelNE_third_range, 2 )), + vuc_pixel_NE_third_range, 11 ); + vuc_pixel_NE_third_range = spu_insert( + *((unsigned char*) spu_extract( vui_addr_pixelNE_third_range, 3 )), + vuc_pixel_NE_third_range, 15 ); + // fourth range + vector unsigned char vuc_pixel_NE_fourth_range = spu_insert( + *((unsigned char*) spu_extract( vui_addr_pixelNE_fourth_range, 0 )), null_vector, 3 ); + vuc_pixel_NE_fourth_range = spu_insert( + *((unsigned char*) spu_extract( vui_addr_pixelNE_fourth_range, 1 )), + vuc_pixel_NE_fourth_range, 7 ); + vuc_pixel_NE_fourth_range = spu_insert( + *((unsigned char*) spu_extract( vui_addr_pixelNE_fourth_range, 2 )), + vuc_pixel_NE_fourth_range, 11 ); + vuc_pixel_NE_fourth_range = spu_insert( + *((unsigned char*) spu_extract( vui_addr_pixelNE_fourth_range, 3 )), + vuc_pixel_NE_fourth_range, 15 ); + + // SOUTH WEST + // first range + vector unsigned char vuc_pixel_SW_first_range = spu_insert( + *((unsigned char*) spu_extract( vui_addr_pixelSW_first_range, 0 )), null_vector, 3 ); + vuc_pixel_SW_first_range = spu_insert( + *((unsigned char*) spu_extract( vui_addr_pixelSW_first_range, 1 )), + vuc_pixel_SW_first_range, 7 ); + vuc_pixel_SW_first_range = spu_insert( + *((unsigned char*) spu_extract( vui_addr_pixelSW_first_range, 2 )), + vuc_pixel_SW_first_range, 11 ); + vuc_pixel_SW_first_range = spu_insert( + *((unsigned char*) spu_extract( vui_addr_pixelSW_first_range, 3 )), + vuc_pixel_SW_first_range, 15 ); + // second range + vector unsigned char vuc_pixel_SW_second_range = spu_insert( + *((unsigned char*) spu_extract( vui_addr_pixelSW_second_range, 0 )), null_vector, 3 ); + vuc_pixel_SW_second_range = spu_insert( + *((unsigned char*) spu_extract( vui_addr_pixelSW_second_range, 1 )), + vuc_pixel_SW_second_range, 7 ); + vuc_pixel_SW_second_range = spu_insert( + *((unsigned char*) spu_extract( vui_addr_pixelSW_second_range, 2 )), + vuc_pixel_SW_second_range, 11 ); + vuc_pixel_SW_second_range = spu_insert( + *((unsigned char*) spu_extract( vui_addr_pixelSW_second_range, 3 )), + vuc_pixel_SW_second_range, 15 ); + // third range + vector unsigned char vuc_pixel_SW_third_range = spu_insert( + *((unsigned char*) spu_extract( vui_addr_pixelSW_third_range, 0 )), null_vector, 3 ); + vuc_pixel_SW_third_range = spu_insert( + *((unsigned char*) spu_extract( vui_addr_pixelSW_third_range, 1 )), + vuc_pixel_SW_third_range, 7 ); + vuc_pixel_SW_third_range = spu_insert( + *((unsigned char*) spu_extract( vui_addr_pixelSW_third_range, 2 )), + vuc_pixel_SW_third_range, 11 ); + vuc_pixel_SW_third_range = spu_insert( + *((unsigned char*) spu_extract( vui_addr_pixelSW_third_range, 3 )), + vuc_pixel_SW_third_range, 15 ); + // fourth range + vector unsigned char vuc_pixel_SW_fourth_range = spu_insert( + *((unsigned char*) spu_extract( vui_addr_pixelSW_fourth_range, 0 )), null_vector, 3 ); + vuc_pixel_SW_fourth_range = spu_insert( + *((unsigned char*) spu_extract( vui_addr_pixelSW_fourth_range, 1 )), + vuc_pixel_SW_fourth_range, 7 ); + vuc_pixel_SW_fourth_range = spu_insert( + *((unsigned char*) spu_extract( vui_addr_pixelSW_fourth_range, 2 )), + vuc_pixel_SW_fourth_range, 11 ); + vuc_pixel_SW_fourth_range = spu_insert( + *((unsigned char*) spu_extract( vui_addr_pixelSW_fourth_range, 3 )), + vuc_pixel_SW_fourth_range, 15 ); + + // NORTH EAST + // first range + vector unsigned char vuc_pixel_SE_first_range = spu_insert( + *((unsigned char*) spu_extract( vui_addr_pixelSE_first_range, 0 )), null_vector, 3 ); + vuc_pixel_SE_first_range = spu_insert( + *((unsigned char*) spu_extract( vui_addr_pixelSE_first_range, 1 )), + vuc_pixel_SE_first_range, 7 ); + vuc_pixel_SE_first_range = spu_insert( + *((unsigned char*) spu_extract( vui_addr_pixelSE_first_range, 2 )), + vuc_pixel_SE_first_range, 11 ); + vuc_pixel_SE_first_range = spu_insert( + *((unsigned char*) spu_extract( vui_addr_pixelSE_first_range, 3 )), + vuc_pixel_SE_first_range, 15 ); + // second range + vector unsigned char vuc_pixel_SE_second_range = spu_insert( + *((unsigned char*) spu_extract( vui_addr_pixelSE_second_range, 0 )), null_vector, 3 ); + vuc_pixel_SE_second_range = spu_insert( + *((unsigned char*) spu_extract( vui_addr_pixelSE_second_range, 1 )), + vuc_pixel_SE_second_range, 7 ); + vuc_pixel_SE_second_range = spu_insert( + *((unsigned char*) spu_extract( vui_addr_pixelSE_second_range, 2 )), + vuc_pixel_SE_second_range, 11 ); + vuc_pixel_SE_second_range = spu_insert( + *((unsigned char*) spu_extract( vui_addr_pixelSE_second_range, 3 )), + vuc_pixel_SE_second_range, 15 ); + // third range + vector unsigned char vuc_pixel_SE_third_range = spu_insert( + *((unsigned char*) spu_extract( vui_addr_pixelSE_third_range, 0 )), null_vector, 3 ); + vuc_pixel_SE_third_range = spu_insert( + *((unsigned char*) spu_extract( vui_addr_pixelSE_third_range, 1 )), + vuc_pixel_SE_third_range, 7 ); + vuc_pixel_SE_third_range = spu_insert( + *((unsigned char*) spu_extract( vui_addr_pixelSE_third_range, 2 )), + vuc_pixel_SE_third_range, 11 ); + vuc_pixel_SE_third_range = spu_insert( + *((unsigned char*) spu_extract( vui_addr_pixelSE_third_range, 3 )), + vuc_pixel_SE_third_range, 15 ); + // fourth range + vector unsigned char vuc_pixel_SE_fourth_range = spu_insert( + *((unsigned char*) spu_extract( vui_addr_pixelSE_fourth_range, 0 )), null_vector, 3 ); + vuc_pixel_SE_fourth_range = spu_insert( + *((unsigned char*) spu_extract( vui_addr_pixelSE_fourth_range, 1 )), + vuc_pixel_SE_fourth_range, 7 ); + vuc_pixel_SE_fourth_range = spu_insert( + *((unsigned char*) spu_extract( vui_addr_pixelSE_fourth_range, 2 )), + vuc_pixel_SE_fourth_range, 11 ); + vuc_pixel_SE_fourth_range = spu_insert( + *((unsigned char*) spu_extract( vui_addr_pixelSE_fourth_range, 3 )), + vuc_pixel_SE_fourth_range, 15 ); + + + + // convert to float + vector float vf_pixel_NW_first_range = spu_convtf( (vector unsigned int) vuc_pixel_NW_first_range, 0 ); + vector float vf_pixel_NW_second_range = spu_convtf( (vector unsigned int) vuc_pixel_NW_second_range, 0 ); + vector float vf_pixel_NW_third_range = spu_convtf( (vector unsigned int) vuc_pixel_NW_third_range, 0 ); + vector float vf_pixel_NW_fourth_range = spu_convtf( (vector unsigned int) vuc_pixel_NW_fourth_range, 0 ); + + vector float vf_pixel_NE_first_range = spu_convtf( (vector unsigned int) vuc_pixel_NE_first_range, 0 ); + vector float vf_pixel_NE_second_range = spu_convtf( (vector unsigned int) vuc_pixel_NE_second_range, 0 ); + vector float vf_pixel_NE_third_range = spu_convtf( (vector unsigned int) vuc_pixel_NE_third_range, 0 ); + vector float vf_pixel_NE_fourth_range = spu_convtf( (vector unsigned int) vuc_pixel_NE_fourth_range, 0 ); + + vector float vf_pixel_SW_first_range = spu_convtf( (vector unsigned int) vuc_pixel_SW_first_range, 0 ); + vector float vf_pixel_SW_second_range = spu_convtf( (vector unsigned int) vuc_pixel_SW_second_range, 0 ); + vector float vf_pixel_SW_third_range = spu_convtf( (vector unsigned int) vuc_pixel_SW_third_range, 0 ); + vector float vf_pixel_SW_fourth_range = spu_convtf( (vector unsigned int) vuc_pixel_SW_fourth_range, 0 ); + + vector float vf_pixel_SE_first_range = spu_convtf( (vector unsigned int) vuc_pixel_SE_first_range, 0 ); + vector float vf_pixel_SE_second_range = spu_convtf( (vector unsigned int) vuc_pixel_SE_second_range, 0 ); + vector float vf_pixel_SE_third_range = spu_convtf( (vector unsigned int) vuc_pixel_SE_third_range, 0 ); + vector float vf_pixel_SE_fourth_range = spu_convtf( (vector unsigned int) vuc_pixel_SE_fourth_range, 0 ); + + // first linear interpolation: EWtop + // EWtop = NW + EWweight*(NE-NW) + // + // first range + vector float vf_EWtop_first_range_tmp = spu_sub( vf_pixel_NE_first_range, vf_pixel_NW_first_range ); + vector float vf_EWtop_first_range = spu_madd( vf_EWweight_first_range, + vf_EWtop_first_range_tmp, + vf_pixel_NW_first_range ); + + // second range + vector float vf_EWtop_second_range_tmp = spu_sub( vf_pixel_NE_second_range, vf_pixel_NW_second_range ); + vector float vf_EWtop_second_range = spu_madd( vf_EWweight_second_range, + vf_EWtop_second_range_tmp, + vf_pixel_NW_second_range ); + + // third range + vector float vf_EWtop_third_range_tmp = spu_sub( vf_pixel_NE_third_range, vf_pixel_NW_third_range ); + vector float vf_EWtop_third_range = spu_madd( vf_EWweight_third_range, + vf_EWtop_third_range_tmp, + vf_pixel_NW_third_range ); + + // fourth range + vector float vf_EWtop_fourth_range_tmp = spu_sub( vf_pixel_NE_fourth_range, vf_pixel_NW_fourth_range ); + vector float vf_EWtop_fourth_range = spu_madd( vf_EWweight_fourth_range, + vf_EWtop_fourth_range_tmp, + vf_pixel_NW_fourth_range ); + + + + // second linear interpolation: EWbottom + // EWbottom = SW + EWweight*(SE-SW) + // + // first range + vector float vf_EWbottom_first_range_tmp = spu_sub( vf_pixel_SE_first_range, vf_pixel_SW_first_range ); + vector float vf_EWbottom_first_range = spu_madd( vf_EWweight_first_range, + vf_EWbottom_first_range_tmp, + vf_pixel_SW_first_range ); + + // second range + vector float vf_EWbottom_second_range_tmp = spu_sub( vf_pixel_SE_second_range, vf_pixel_SW_second_range ); + vector float vf_EWbottom_second_range = spu_madd( vf_EWweight_second_range, + vf_EWbottom_second_range_tmp, + vf_pixel_SW_second_range ); + // first range + vector float vf_EWbottom_third_range_tmp = spu_sub( vf_pixel_SE_third_range, vf_pixel_SW_third_range ); + vector float vf_EWbottom_third_range = spu_madd( vf_EWweight_third_range, + vf_EWbottom_third_range_tmp, + vf_pixel_SW_third_range ); + + // first range + vector float vf_EWbottom_fourth_range_tmp = spu_sub( vf_pixel_SE_fourth_range, vf_pixel_SW_fourth_range ); + vector float vf_EWbottom_fourth_range = spu_madd( vf_EWweight_fourth_range, + vf_EWbottom_fourth_range_tmp, + vf_pixel_SW_fourth_range ); + + + + // third linear interpolation: the bilinear interpolated value + // result = EWtop + NSweight*(EWbottom-EWtop); + // + // first range + vector float vf_result_first_range_tmp = spu_sub( vf_EWbottom_first_range, vf_EWtop_first_range ); + vector float vf_result_first_range = spu_madd( vf_NSweight, + vf_result_first_range_tmp, + vf_EWtop_first_range ); + + // second range + vector float vf_result_second_range_tmp = spu_sub( vf_EWbottom_second_range, vf_EWtop_second_range ); + vector float vf_result_second_range = spu_madd( vf_NSweight, + vf_result_second_range_tmp, + vf_EWtop_second_range ); + + // third range + vector float vf_result_third_range_tmp = spu_sub( vf_EWbottom_third_range, vf_EWtop_third_range ); + vector float vf_result_third_range = spu_madd( vf_NSweight, + vf_result_third_range_tmp, + vf_EWtop_third_range ); + + // fourth range + vector float vf_result_fourth_range_tmp = spu_sub( vf_EWbottom_fourth_range, vf_EWtop_fourth_range ); + vector float vf_result_fourth_range = spu_madd( vf_NSweight, + vf_result_fourth_range_tmp, + vf_EWtop_fourth_range ); + + + + // convert back: using saturated arithmetic + vector unsigned int vui_result_first_range = vfloat_to_vuint( vf_result_first_range ); + vector unsigned int vui_result_second_range = vfloat_to_vuint( vf_result_second_range ); + vector unsigned int vui_result_third_range = vfloat_to_vuint( vf_result_third_range ); + vector unsigned int vui_result_fourth_range = vfloat_to_vuint( vf_result_fourth_range ); + + // merge results->lower,upper + vector unsigned char vuc_mask_merge_result_first_second = { 0x03, 0x07, 0x0B, 0x0F, + 0x13, 0x17, 0x1B, 0x1F, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00 }; + + vector unsigned char vuc_mask_merge_result_third_fourth = { 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x03, 0x07, 0x0B, 0x0F, + 0x13, 0x17, 0x1B, 0x1F }; + + vector unsigned char vuc_result_first_second = + spu_shuffle( (vector unsigned char) vui_result_first_range, + (vector unsigned char) vui_result_second_range, + vuc_mask_merge_result_first_second ); + + vector unsigned char vuc_result_third_fourth = + spu_shuffle( (vector unsigned char) vui_result_third_range, + (vector unsigned char) vui_result_fourth_range, + vuc_mask_merge_result_third_fourth ); + + // store result + *((vector unsigned char*)dst) = spu_or( vuc_result_first_second, + vuc_result_third_fourth ); + dst += 16; + } +} + diff --git a/3rdparty/SDL/src/video/ps3/spulibs/fb_writer.c b/3rdparty/SDL/src/video/ps3/spulibs/fb_writer.c new file mode 100644 index 0000000..0eb51cc --- /dev/null +++ b/3rdparty/SDL/src/video/ps3/spulibs/fb_writer.c @@ -0,0 +1,193 @@ +/* + * SDL - Simple DirectMedia Layer + * CELL BE Support for PS3 Framebuffer + * Copyright (C) 2008, 2009 International Business Machines Corporation + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 + * USA + * + * Martin Lowinski <lowinski [at] de [dot] ibm [ibm] com> + * Dirk Herrendoerfer <d.herrendoerfer [at] de [dot] ibm [dot] com> + * SPE code based on research by: + * Rene Becker + * Thimo Emmerich + */ + +#include "spu_common.h" + +#include <spu_intrinsics.h> +#include <spu_mfcio.h> +#include <stdio.h> +#include <string.h> + +// Debugging +//#define DEBUG + +#ifdef DEBUG +#define deprintf(fmt, args... ) \ + fprintf( stdout, fmt, ##args ); \ + fflush( stdout ); +#else +#define deprintf( fmt, args... ) +#endif + +void cpy_to_fb(unsigned int); + +/* fb_writer_spu parms */ +static volatile struct fb_writer_parms_t parms __attribute__ ((aligned(128))); + +/* Code running on SPU */ +int main(unsigned long long spe_id __attribute__ ((unused)), unsigned long long argp __attribute__ ((unused))) +{ + deprintf("[SPU] fb_writer_spu is up... (on SPE #%llu)\n", spe_id); + uint32_t ea_mfc, mbox; + // send ready message + spu_write_out_mbox(SPU_READY); + + while (1) { + /* Check mailbox */ + mbox = spu_read_in_mbox(); + deprintf("[SPU] Message is %u\n", mbox); + switch (mbox) { + case SPU_EXIT: + deprintf("[SPU] fb_writer goes down...\n"); + return 0; + case SPU_START: + break; + default: + deprintf("[SPU] Cannot handle message\n"); + continue; + } + + /* Tag Manager setup */ + unsigned int tags; + tags = mfc_multi_tag_reserve(5); + if (tags == MFC_TAG_INVALID) { + deprintf("[SPU] Failed to reserve mfc tags on fb_writer\n"); + return 0; + } + + /* Framebuffer parms */ + ea_mfc = spu_read_in_mbox(); + deprintf("[SPU] Message on fb_writer is %u\n", ea_mfc); + spu_mfcdma32(&parms, (unsigned int)ea_mfc, + sizeof(struct fb_writer_parms_t), tags, + MFC_GET_CMD); + deprintf("[SPU] argp = %u\n", (unsigned int)argp); + DMA_WAIT_TAG(tags); + + /* Copy parms->data to framebuffer */ + deprintf("[SPU] Copying to framebuffer started\n"); + cpy_to_fb(tags); + deprintf("[SPU] Copying to framebuffer done!\n"); + + mfc_multi_tag_release(tags, 5); + deprintf("[SPU] fb_writer_spu... done!\n"); + /* Send FIN msg */ + spu_write_out_mbox(SPU_FIN); + } + + return 0; +} + +void cpy_to_fb(unsigned int tag_id_base) +{ + unsigned int i; + unsigned char current_buf; + uint8_t *in = parms.data; + + /* Align fb pointer which was centered before */ + uint8_t *fb = + (unsigned char *)((unsigned int)parms.center & 0xFFFFFFF0); + + uint32_t bounded_input_height = parms.bounded_input_height; + uint32_t bounded_input_width = parms.bounded_input_width; + uint32_t fb_pixel_size = parms.fb_pixel_size; + + uint32_t out_line_stride = parms.out_line_stride; + uint32_t in_line_stride = parms.in_line_stride; + uint32_t in_line_size = bounded_input_width * fb_pixel_size; + + current_buf = 0; + + /* Local store buffer */ + static volatile uint8_t buf[4][BUFFER_SIZE] + __attribute__ ((aligned(128))); + /* do 4-times multibuffering using DMA list, process in two steps */ + for (i = 0; i < bounded_input_height >> 2; i++) { + /* first buffer */ + DMA_WAIT_TAG(tag_id_base + 1); + // retrieve buffer + spu_mfcdma32(buf[0], (unsigned int)in, in_line_size, + tag_id_base + 1, MFC_GETB_CMD); + DMA_WAIT_TAG(tag_id_base + 1); + // store buffer + spu_mfcdma32(buf[0], (unsigned int)fb, in_line_size, + tag_id_base + 1, MFC_PUTB_CMD); + in += in_line_stride; + fb += out_line_stride; + deprintf("[SPU] 1st buffer copied in=0x%x, fb=0x%x\n", in, + fb); + + /* second buffer */ + DMA_WAIT_TAG(tag_id_base + 2); + // retrieve buffer + spu_mfcdma32(buf[1], (unsigned int)in, in_line_size, + tag_id_base + 2, MFC_GETB_CMD); + DMA_WAIT_TAG(tag_id_base + 2); + // store buffer + spu_mfcdma32(buf[1], (unsigned int)fb, in_line_size, + tag_id_base + 2, MFC_PUTB_CMD); + in += in_line_stride; + fb += out_line_stride; + deprintf("[SPU] 2nd buffer copied in=0x%x, fb=0x%x\n", in, + fb); + + /* third buffer */ + DMA_WAIT_TAG(tag_id_base + 3); + // retrieve buffer + spu_mfcdma32(buf[2], (unsigned int)in, in_line_size, + tag_id_base + 3, MFC_GETB_CMD); + DMA_WAIT_TAG(tag_id_base + 3); + // store buffer + spu_mfcdma32(buf[2], (unsigned int)fb, in_line_size, + tag_id_base + 3, MFC_PUTB_CMD); + in += in_line_stride; + fb += out_line_stride; + deprintf("[SPU] 3rd buffer copied in=0x%x, fb=0x%x\n", in, + fb); + + /* fourth buffer */ + DMA_WAIT_TAG(tag_id_base + 4); + // retrieve buffer + spu_mfcdma32(buf[3], (unsigned int)in, in_line_size, + tag_id_base + 4, MFC_GETB_CMD); + DMA_WAIT_TAG(tag_id_base + 4); + // store buffer + spu_mfcdma32(buf[3], (unsigned int)fb, in_line_size, + tag_id_base + 4, MFC_PUTB_CMD); + in += in_line_stride; + fb += out_line_stride; + deprintf("[SPU] 4th buffer copied in=0x%x, fb=0x%x\n", in, + fb); + deprintf("[SPU] Loop #%i, bounded_input_height=%i\n", i, + bounded_input_height >> 2); + } + DMA_WAIT_TAG(tag_id_base + 2); + DMA_WAIT_TAG(tag_id_base + 3); + DMA_WAIT_TAG(tag_id_base + 4); +} + + diff --git a/3rdparty/SDL/src/video/ps3/spulibs/spu_common.h b/3rdparty/SDL/src/video/ps3/spulibs/spu_common.h new file mode 100644 index 0000000..42c328c --- /dev/null +++ b/3rdparty/SDL/src/video/ps3/spulibs/spu_common.h @@ -0,0 +1,108 @@ +/* + * SDL - Simple DirectMedia Layer + * CELL BE Support for PS3 Framebuffer + * Copyright (C) 2008, 2009 International Business Machines Corporation + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 + * USA + * + * Martin Lowinski <lowinski [at] de [dot] ibm [ibm] com> + * Dirk Herrendoerfer <d.herrendoerfer [at] de [dot] ibm [dot] com> + * SPE code based on research by: + * Rene Becker + * Thimo Emmerich + */ + +/* Common definitions/makros for SPUs */ + +#ifndef _SPU_COMMON_H +#define _SPU_COMMON_H + +#include <stdio.h> +#include <stdint.h> +#include <string.h> + +/* Tag management */ +#define DMA_WAIT_TAG(_tag) \ + mfc_write_tag_mask(1<<(_tag)); \ + mfc_read_tag_status_all(); + +/* SPU mailbox messages */ +#define SPU_READY 0 +#define SPU_START 1 +#define SPU_FIN 2 +#define SPU_EXIT 3 + +/* Tags */ +#define RETR_BUF 0 +#define STR_BUF 1 +#define TAG_INIT 2 + +/* Buffersizes */ +#define MAX_HDTV_WIDTH 1920 +#define MAX_HDTV_HEIGHT 1080 +/* One stride of HDTV */ +#define BUFFER_SIZE 7680 + +/* fb_writer ppu/spu exchange parms */ +struct fb_writer_parms_t { + uint8_t *data; + uint8_t *center; + uint32_t out_line_stride; + uint32_t in_line_stride; + uint32_t bounded_input_height; + uint32_t bounded_input_width; + uint32_t fb_pixel_size; + + /* This padding is to fulfill the need for 16 byte alignment. On parm change, update! */ + char padding[4]; +} __attribute__((aligned(128))); + +/* yuv2rgb ppu/spu exchange parms */ +struct yuv2rgb_parms_t { + uint8_t* y_plane; + uint8_t* v_plane; + uint8_t* u_plane; + + uint8_t* dstBuffer; + + unsigned int src_pixel_width; + unsigned int src_pixel_height; + + /* This padding is to fulfill the need for 16 byte alignment. On parm change, update! */ + char padding[128 - ((4 * sizeof(uint8_t *) + 2 * sizeof(unsigned int)) & 0x7F)]; +} __attribute__((aligned(128))); + +/* bilin_scaler ppu/spu exchange parms */ +struct scale_parms_t { + uint8_t* y_plane; + uint8_t* v_plane; + uint8_t* u_plane; + + uint8_t* dstBuffer; + + unsigned int src_pixel_width; + unsigned int src_pixel_height; + + unsigned int dst_pixel_width; + unsigned int dst_pixel_height; + + /* This padding is to fulfill the need for 16 byte alignment. On parm change, update! */ + char padding[128 - ((4 * sizeof(uint8_t *) + 4 * sizeof(unsigned int)) & 0x7F)]; +} __attribute__((aligned(128))); + +#endif /* _SPU_COMMON_H */ + + diff --git a/3rdparty/SDL/src/video/ps3/spulibs/yuv2rgb_converter.c b/3rdparty/SDL/src/video/ps3/spulibs/yuv2rgb_converter.c new file mode 100644 index 0000000..5e16691 --- /dev/null +++ b/3rdparty/SDL/src/video/ps3/spulibs/yuv2rgb_converter.c @@ -0,0 +1,629 @@ +/* + * SDL - Simple DirectMedia Layer + * CELL BE Support for PS3 Framebuffer + * Copyright (C) 2008, 2009 International Business Machines Corporation + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 + * USA + * + * Martin Lowinski <lowinski [at] de [dot] ibm [ibm] com> + * Dirk Herrendoerfer <d.herrendoerfer [at] de [dot] ibm [dot] com> + * SPE code based on research by: + * Rene Becker + * Thimo Emmerich + */ + +#include "spu_common.h" + +#include <spu_intrinsics.h> +#include <spu_mfcio.h> + +// Debugging +//#define DEBUG + +#ifdef DEBUG +#define deprintf(fmt, args... ) \ + fprintf( stdout, fmt, ##args ); \ + fflush( stdout ); +#else +#define deprintf( fmt, args... ) +#endif + +struct yuv2rgb_parms_t parms_converter __attribute__((aligned(128))); + +/* A maximum of 8 lines Y, therefore 4 lines V, 4 lines U are stored + * there might be the need to retrieve misaligned data, adjust + * incoming v and u plane to be able to handle this (add 128) + */ +unsigned char y_plane[2][(MAX_HDTV_WIDTH + 128) * 4] __attribute__((aligned(128))); +unsigned char v_plane[2][(MAX_HDTV_WIDTH + 128) * 2] __attribute__((aligned(128))); +unsigned char u_plane[2][(MAX_HDTV_WIDTH + 128) * 2] __attribute__((aligned(128))); + +/* A maximum of 4 lines BGRA are stored, 4 byte per pixel */ +unsigned char bgra[4 * MAX_HDTV_WIDTH * 4] __attribute__((aligned(128))); + +/* some vectors needed by the float to int conversion */ +static const vector float vec_255 = { 255.0f, 255.0f, 255.0f, 255.0f }; +static const vector float vec_0_1 = { 0.1f, 0.1f, 0.1f, 0.1f }; + +void yuv_to_rgb_w16(); +void yuv_to_rgb_w32(); + +void yuv_to_rgb_w16_line(unsigned char* y_addr, unsigned char* v_addr, unsigned char* u_addr, unsigned char* bgra_addr, unsigned int width); +void yuv_to_rgb_w32_line(unsigned char* y_addr, unsigned char* v_addr, unsigned char* u_addr, unsigned char* bgra_addr_, unsigned int width); + + +int main(unsigned long long spe_id __attribute__((unused)), unsigned long long argp __attribute__ ((unused))) +{ + deprintf("[SPU] yuv2rgb_spu is up... (on SPE #%llu)\n", spe_id); + uint32_t ea_mfc, mbox; + // send ready message + spu_write_out_mbox(SPU_READY); + + while (1) { + /* Check mailbox */ + mbox = spu_read_in_mbox(); + deprintf("[SPU] Message is %u\n", mbox); + switch (mbox) { + case SPU_EXIT: + deprintf("[SPU] fb_writer goes down...\n"); + return 0; + case SPU_START: + break; + default: + deprintf("[SPU] Cannot handle message\n"); + continue; + } + + /* Tag Manager setup */ + unsigned int tag_id; + tag_id = mfc_multi_tag_reserve(1); + if (tag_id == MFC_TAG_INVALID) { + deprintf("[SPU] Failed to reserve mfc tags on yuv2rgb_converter\n"); + return 0; + } + + /* DMA transfer for the input parameters */ + ea_mfc = spu_read_in_mbox(); + deprintf("[SPU] Message on yuv2rgb_converter is %u\n", ea_mfc); + spu_mfcdma32(&parms_converter, (unsigned int)ea_mfc, sizeof(struct yuv2rgb_parms_t), tag_id, MFC_GET_CMD); + DMA_WAIT_TAG(tag_id); + + /* There are alignment issues that involve handling of special cases + * a width of 32 results in a width of 16 in the chrominance + * --> choose the proper handling to optimize the performance + */ + deprintf("[SPU] Convert %ix%i from YUV to RGB\n", parms_converter.src_pixel_width, parms_converter.src_pixel_height); + if (parms_converter.src_pixel_width & 0x1f) { + deprintf("[SPU] Using yuv_to_rgb_w16\n"); + yuv_to_rgb_w16(); + } else { + deprintf("[SPU] Using yuv_to_rgb_w32\n"); + yuv_to_rgb_w32(); + } + + mfc_multi_tag_release(tag_id, 1); + deprintf("[SPU] yuv2rgb_spu... done!\n"); + /* Send FIN message */ + spu_write_out_mbox(SPU_FIN); + } + + return 0; +} + + +/* + * float_to_char() + * + * converts a float to a character using saturated + * arithmetic + * + * @param s float for conversion + * @returns converted character + */ +inline static unsigned char float_to_char(float s) { + vector float vec_s = spu_splats(s); + vector unsigned int select_1 = spu_cmpgt(vec_0_1, vec_s); + vec_s = spu_sel(vec_s, vec_0_1, select_1); + + vector unsigned int select_2 = spu_cmpgt(vec_s, vec_255); + vec_s = spu_sel(vec_s, vec_255, select_2); + return (unsigned char) spu_extract(vec_s,0); +} + + +/* + * vfloat_to_vuint() + * + * converts a float vector to an unsinged int vector using saturated + * arithmetic + * + * @param vec_s float vector for conversion + * @returns converted unsigned int vector + */ +inline static vector unsigned int vfloat_to_vuint(vector float vec_s) { + vector unsigned int select_1 = spu_cmpgt(vec_0_1, vec_s); + vec_s = spu_sel(vec_s, vec_0_1, select_1); + + vector unsigned int select_2 = spu_cmpgt(vec_s, vec_255); + vec_s = spu_sel(vec_s, vec_255, select_2); + return spu_convtu(vec_s,0); +} + + +void yuv_to_rgb_w16() { + // Pixel dimensions of the picture + uint32_t width, height; + + // Extract parameters + width = parms_converter.src_pixel_width; + height = parms_converter.src_pixel_height; + + // Plane data management + // Y + unsigned char* ram_addr_y = parms_converter.y_plane; + // V + unsigned char* ram_addr_v = parms_converter.v_plane; + // U + unsigned char* ram_addr_u = parms_converter.u_plane; + + // BGRA + unsigned char* ram_addr_bgra = parms_converter.dstBuffer; + + // Strides + unsigned int stride_y = width; + unsigned int stride_vu = width>>1; + + // Buffer management + unsigned int buf_idx = 0; + unsigned int size_4lines_y = stride_y<<2; + unsigned int size_2lines_y = stride_y<<1; + unsigned int size_2lines_vu = stride_vu<<1; + + // 2*width*4byte_per_pixel + unsigned int size_2lines_bgra = width<<3; + + + // start double-buffered processing + // 4 lines y + spu_mfcdma32(y_plane[buf_idx], (unsigned int) ram_addr_y, size_4lines_y, RETR_BUF+buf_idx, MFC_GET_CMD); + + // 2 lines v + spu_mfcdma32(v_plane[buf_idx], (unsigned int) ram_addr_v, size_2lines_vu, RETR_BUF+buf_idx, MFC_GET_CMD); + + // 2 lines u + spu_mfcdma32(u_plane[buf_idx], (unsigned int) ram_addr_u, size_2lines_vu, RETR_BUF+buf_idx, MFC_GET_CMD); + + // Wait for these transfers to be completed + DMA_WAIT_TAG((RETR_BUF + buf_idx)); + + unsigned int i; + for(i=0; i<(height>>2)-1; i++) { + + buf_idx^=1; + + // 4 lines y + spu_mfcdma32(y_plane[buf_idx], (unsigned int) ram_addr_y+size_4lines_y, size_4lines_y, RETR_BUF+buf_idx, MFC_GET_CMD); + + // 2 lines v + spu_mfcdma32(v_plane[buf_idx], (unsigned int) ram_addr_v+size_2lines_vu, size_2lines_vu, RETR_BUF+buf_idx, MFC_GET_CMD); + + // 2 lines u + spu_mfcdma32(u_plane[buf_idx], (unsigned int) ram_addr_u+size_2lines_vu, size_2lines_vu, RETR_BUF+buf_idx, MFC_GET_CMD); + + DMA_WAIT_TAG((RETR_BUF + buf_idx)); + + buf_idx^=1; + + + // Convert YUV to BGRA, store it back (first two lines) + yuv_to_rgb_w16_line(y_plane[buf_idx], v_plane[buf_idx], u_plane[buf_idx], bgra, width); + + // Next two lines + yuv_to_rgb_w16_line(y_plane[buf_idx] + size_2lines_y, + v_plane[buf_idx] + stride_vu, + u_plane[buf_idx] + stride_vu, + bgra + size_2lines_bgra, + width); + + // Wait for previous storing transfer to be completed + DMA_WAIT_TAG(STR_BUF); + + // Store converted lines in two steps->max transfer size 16384 + spu_mfcdma32(bgra, (unsigned int) ram_addr_bgra, size_2lines_bgra, STR_BUF, MFC_PUT_CMD); + ram_addr_bgra += size_2lines_bgra; + spu_mfcdma32(bgra+size_2lines_bgra, (unsigned int) ram_addr_bgra, size_2lines_bgra, STR_BUF, MFC_PUT_CMD); + ram_addr_bgra += size_2lines_bgra; + + // Move 4 lines + ram_addr_y += size_4lines_y; + ram_addr_v += size_2lines_vu; + ram_addr_u += size_2lines_vu; + + buf_idx^=1; + } + + // Convert YUV to BGRA, store it back (first two lines) + yuv_to_rgb_w16_line(y_plane[buf_idx], v_plane[buf_idx], u_plane[buf_idx], bgra, width); + + // Next two lines + yuv_to_rgb_w16_line(y_plane[buf_idx] + size_2lines_y, + v_plane[buf_idx] + stride_vu, + u_plane[buf_idx] + stride_vu, + bgra + size_2lines_bgra, + width); + + // Wait for previous storing transfer to be completed + DMA_WAIT_TAG(STR_BUF); + spu_mfcdma32(bgra, (unsigned int) ram_addr_bgra, size_2lines_bgra, STR_BUF, MFC_PUT_CMD); + ram_addr_bgra += size_2lines_bgra; + spu_mfcdma32(bgra+size_2lines_bgra, (unsigned int) ram_addr_bgra, size_2lines_bgra, STR_BUF, MFC_PUT_CMD); + + // wait for previous storing transfer to be completed + DMA_WAIT_TAG(STR_BUF); + +} + + +void yuv_to_rgb_w32() { + // Pixel dimensions of the picture + uint32_t width, height; + + // Extract parameters + width = parms_converter.src_pixel_width; + height = parms_converter.src_pixel_height; + + // Plane data management + // Y + unsigned char* ram_addr_y = parms_converter.y_plane; + // V + unsigned char* ram_addr_v = parms_converter.v_plane; + // U + unsigned char* ram_addr_u = parms_converter.u_plane; + + // BGRA + unsigned char* ram_addr_bgra = parms_converter.dstBuffer; + + // Strides + unsigned int stride_y = width; + unsigned int stride_vu = width>>1; + + // Buffer management + unsigned int buf_idx = 0; + unsigned int size_4lines_y = stride_y<<2; + unsigned int size_2lines_y = stride_y<<1; + unsigned int size_2lines_vu = stride_vu<<1; + + // 2*width*4byte_per_pixel + unsigned int size_2lines_bgra = width<<3; + + // start double-buffered processing + // 4 lines y + spu_mfcdma32(y_plane[buf_idx], (unsigned int) ram_addr_y, size_4lines_y, RETR_BUF + buf_idx, MFC_GET_CMD); + // 2 lines v + spu_mfcdma32(v_plane[buf_idx], (unsigned int) ram_addr_v, size_2lines_vu, RETR_BUF + buf_idx, MFC_GET_CMD); + // 2 lines u + spu_mfcdma32(u_plane[buf_idx], (unsigned int) ram_addr_u, size_2lines_vu, RETR_BUF + buf_idx, MFC_GET_CMD); + + // Wait for these transfers to be completed + DMA_WAIT_TAG((RETR_BUF + buf_idx)); + + unsigned int i; + for(i=0; i < (height>>2)-1; i++) { + buf_idx^=1; + // 4 lines y + spu_mfcdma32(y_plane[buf_idx], (unsigned int) ram_addr_y+size_4lines_y, size_4lines_y, RETR_BUF + buf_idx, MFC_GET_CMD); + deprintf("4lines = %d\n", size_4lines_y); + // 2 lines v + spu_mfcdma32(v_plane[buf_idx], (unsigned int) ram_addr_v+size_2lines_vu, size_2lines_vu, RETR_BUF + buf_idx, MFC_GET_CMD); + deprintf("2lines = %d\n", size_2lines_vu); + // 2 lines u + spu_mfcdma32(u_plane[buf_idx], (unsigned int) ram_addr_u+size_2lines_vu, size_2lines_vu, RETR_BUF + buf_idx, MFC_GET_CMD); + deprintf("2lines = %d\n", size_2lines_vu); + + DMA_WAIT_TAG((RETR_BUF + buf_idx)); + + buf_idx^=1; + + // Convert YUV to BGRA, store it back (first two lines) + yuv_to_rgb_w32_line(y_plane[buf_idx], v_plane[buf_idx], u_plane[buf_idx], bgra, width); + + // Next two lines + yuv_to_rgb_w32_line(y_plane[buf_idx] + size_2lines_y, + v_plane[buf_idx] + stride_vu, + u_plane[buf_idx] + stride_vu, + bgra + size_2lines_bgra, + width); + + // Wait for previous storing transfer to be completed + DMA_WAIT_TAG(STR_BUF); + + // Store converted lines in two steps->max transfer size 16384 + spu_mfcdma32(bgra, (unsigned int)ram_addr_bgra, size_2lines_bgra, STR_BUF, MFC_PUT_CMD); + ram_addr_bgra += size_2lines_bgra; + spu_mfcdma32(bgra + size_2lines_bgra, (unsigned int)ram_addr_bgra, size_2lines_bgra, STR_BUF, MFC_PUT_CMD); + ram_addr_bgra += size_2lines_bgra; + + // Move 4 lines + ram_addr_y += size_4lines_y; + ram_addr_v += size_2lines_vu; + ram_addr_u += size_2lines_vu; + + buf_idx^=1; + } + + // Convert YUV to BGRA, store it back (first two lines) + yuv_to_rgb_w32_line(y_plane[buf_idx], v_plane[buf_idx], u_plane[buf_idx], bgra, width); + + // Next two lines + yuv_to_rgb_w32_line(y_plane[buf_idx] + size_2lines_y, + v_plane[buf_idx] + stride_vu, + u_plane[buf_idx] + stride_vu, + bgra + size_2lines_bgra, + width); + + // Wait for previous storing transfer to be completed + DMA_WAIT_TAG(STR_BUF); + spu_mfcdma32(bgra, (unsigned int) ram_addr_bgra, size_2lines_bgra, STR_BUF, MFC_PUT_CMD); + ram_addr_bgra += size_2lines_bgra; + spu_mfcdma32(bgra + size_2lines_bgra, (unsigned int) ram_addr_bgra, size_2lines_bgra, STR_BUF, MFC_PUT_CMD); + + // Wait for previous storing transfer to be completed + DMA_WAIT_TAG(STR_BUF); +} + + +/* Some vectors needed by the yuv 2 rgb conversion algorithm */ +const vector float vec_minus_128 = { -128.0f, -128.0f, -128.0f, -128.0f }; +const vector unsigned char vec_null = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; +const vector unsigned char vec_char2int_first = { 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x13 }; +const vector unsigned char vec_char2int_second = { 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x17 }; +const vector unsigned char vec_char2int_third = { 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 0x1A, 0x00, 0x00, 0x00, 0x1B }; +const vector unsigned char vec_char2int_fourth = { 0x00, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x00, 0x1D, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x00, 0x1F }; + +const vector float vec_R_precalc_coeff = {1.403f, 1.403f, 1.403f, 1.403f}; +const vector float vec_Gu_precalc_coeff = {-0.344f, -0.344f, -0.344f, -0.344f}; +const vector float vec_Gv_precalc_coeff = {-0.714f, -0.714f, -0.714f, -0.714f}; +const vector float vec_B_precalc_coeff = {1.773f, 1.773f, 1.773f, 1.773f}; + +const vector unsigned int vec_alpha = { 255 << 24, 255 << 24, 255 << 24, 255 << 24 }; + +const vector unsigned char vec_select_floats_upper = { 0x00, 0x01, 0x02, 0x03, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x04, 0x05, 0x06, 0x07 }; +const vector unsigned char vec_select_floats_lower = { 0x08, 0x09, 0x0A, 0x0B, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x0C, 0x0D, 0x0E, 0x0F }; + + +/* + * yuv_to_rgb_w16() + * + * processes to line of yuv-input, width has to be a multiple of 16 + * two lines of yuv are taken as input + * + * @param y_addr address of the y plane in local store + * @param v_addr address of the v plane in local store + * @param u_addr address of the u plane in local store + * @param bgra_addr_ address of the bgra output buffer + * @param width the width in pixel + */ +void yuv_to_rgb_w16_line(unsigned char* y_addr, unsigned char* v_addr, unsigned char* u_addr, unsigned char* bgra_addr_, unsigned int width) { + // each pixel is stored as an integer + unsigned int* bgra_addr = (unsigned int*) bgra_addr_; + + unsigned int x; + for(x = 0; x < width; x+=2) { + // Gehe zweischrittig durch die zeile, da jeder u und v wert fuer 4 pixel(zwei hoch, zwei breit) gilt + const unsigned char Y_1 = *(y_addr + x); + const unsigned char Y_2 = *(y_addr + x + 1); + const unsigned char Y_3 = *(y_addr + x + width); + const unsigned char Y_4 = *(y_addr + x + width + 1); + const unsigned char U = *(u_addr + (x >> 1)); + const unsigned char V = *(v_addr + (x >> 1)); + + float V_minus_128 = (float)((float)V - 128.0f); + float U_minus_128 = (float)((float)U - 128.0f); + + float R_precalculate = 1.403f * V_minus_128; + float G_precalculate = -(0.344f * U_minus_128 + 0.714f * V_minus_128); + float B_precalculate = 1.773f * U_minus_128; + + const unsigned char R_1 = float_to_char((Y_1 + R_precalculate)); + const unsigned char R_2 = float_to_char((Y_2 + R_precalculate)); + const unsigned char R_3 = float_to_char((Y_3 + R_precalculate)); + const unsigned char R_4 = float_to_char((Y_4 + R_precalculate)); + const unsigned char G_1 = float_to_char((Y_1 + G_precalculate)); + const unsigned char G_2 = float_to_char((Y_2 + G_precalculate)); + const unsigned char G_3 = float_to_char((Y_3 + G_precalculate)); + const unsigned char G_4 = float_to_char((Y_4 + G_precalculate)); + const unsigned char B_1 = float_to_char((Y_1 + B_precalculate)); + const unsigned char B_2 = float_to_char((Y_2 + B_precalculate)); + const unsigned char B_3 = float_to_char((Y_3 + B_precalculate)); + const unsigned char B_4 = float_to_char((Y_4 + B_precalculate)); + + *(bgra_addr + x) = (B_1 << 0)| (G_1 << 8) | (R_1 << 16) | (255 << 24); + *(bgra_addr + x + 1) = (B_2 << 0)| (G_2 << 8) | (R_2 << 16) | (255 << 24); + *(bgra_addr + x + width) = (B_3 << 0)| (G_3 << 8) | (R_3 << 16) | (255 << 24); + *(bgra_addr + x + width + 1) = (B_4 << 0)| (G_4 << 8) | (R_4 << 16) | (255 << 24); + } +} + + +/* + * yuv_to_rgb_w32() + * + * processes to line of yuv-input, width has to be a multiple of 32 + * two lines of yuv are taken as input + * + * @param y_addr address of the y plane in local store + * @param v_addr address of the v plane in local store + * @param u_addr address of the u plane in local store + * @param bgra_addr_ address of the bgra output buffer + * @param width the width in pixel + */ +void yuv_to_rgb_w32_line(unsigned char* y_addr, unsigned char* v_addr, unsigned char* u_addr, unsigned char* bgra_addr_, unsigned int width) { + // each pixel is stored as an integer + unsigned int* bgra_addr = (unsigned int*) bgra_addr_; + + unsigned int x; + for(x = 0; x < width; x+=32) { + // Gehe zweischrittig durch die zeile, da jeder u und v wert fuer 4 pixel(zwei hoch, zwei breit) gilt + + const vector unsigned char vchar_Y_1 = *((vector unsigned char*)(y_addr + x)); + const vector unsigned char vchar_Y_2 = *((vector unsigned char*)(y_addr + x + 16)); + const vector unsigned char vchar_Y_3 = *((vector unsigned char*)(y_addr + x + width)); + const vector unsigned char vchar_Y_4 = *((vector unsigned char*)(y_addr + x + width + 16)); + const vector unsigned char vchar_U = *((vector unsigned char*)(u_addr + (x >> 1))); + const vector unsigned char vchar_V = *((vector unsigned char*)(v_addr + (x >> 1))); + + const vector float vfloat_U_1 = spu_add(spu_convtf((vector unsigned int)spu_shuffle(vec_null, vchar_U, vec_char2int_first), 0),vec_minus_128); + const vector float vfloat_U_2 = spu_add(spu_convtf((vector unsigned int)spu_shuffle(vec_null, vchar_U, vec_char2int_second), 0),vec_minus_128); + const vector float vfloat_U_3 = spu_add(spu_convtf((vector unsigned int)spu_shuffle(vec_null, vchar_U, vec_char2int_third), 0),vec_minus_128); + const vector float vfloat_U_4 = spu_add(spu_convtf((vector unsigned int)spu_shuffle(vec_null, vchar_U, vec_char2int_fourth), 0),vec_minus_128); + + const vector float vfloat_V_1 = spu_add(spu_convtf((vector unsigned int)spu_shuffle(vec_null, vchar_V, vec_char2int_first), 0),vec_minus_128); + const vector float vfloat_V_2 = spu_add(spu_convtf((vector unsigned int)spu_shuffle(vec_null, vchar_V, vec_char2int_second), 0),vec_minus_128); + const vector float vfloat_V_3 = spu_add(spu_convtf((vector unsigned int)spu_shuffle(vec_null, vchar_V, vec_char2int_third), 0),vec_minus_128); + const vector float vfloat_V_4 = spu_add(spu_convtf((vector unsigned int)spu_shuffle(vec_null, vchar_V, vec_char2int_fourth), 0),vec_minus_128); + + vector float Y_1 = spu_convtf((vector unsigned int)spu_shuffle(vec_null, vchar_Y_1, vec_char2int_first), 0); + vector float Y_2 = spu_convtf((vector unsigned int)spu_shuffle(vec_null, vchar_Y_1, vec_char2int_second), 0); + vector float Y_3 = spu_convtf((vector unsigned int)spu_shuffle(vec_null, vchar_Y_1, vec_char2int_third), 0); + vector float Y_4 = spu_convtf((vector unsigned int)spu_shuffle(vec_null, vchar_Y_1, vec_char2int_fourth), 0); + vector float Y_5 = spu_convtf((vector unsigned int)spu_shuffle(vec_null, vchar_Y_2, vec_char2int_first), 0); + vector float Y_6 = spu_convtf((vector unsigned int)spu_shuffle(vec_null, vchar_Y_2, vec_char2int_second), 0); + vector float Y_7 = spu_convtf((vector unsigned int)spu_shuffle(vec_null, vchar_Y_2, vec_char2int_third), 0); + vector float Y_8 = spu_convtf((vector unsigned int)spu_shuffle(vec_null, vchar_Y_2, vec_char2int_fourth), 0); + vector float Y_9 = spu_convtf((vector unsigned int)spu_shuffle(vec_null, vchar_Y_3, vec_char2int_first), 0); + vector float Y_10 = spu_convtf((vector unsigned int)spu_shuffle(vec_null, vchar_Y_3, vec_char2int_second), 0); + vector float Y_11 = spu_convtf((vector unsigned int)spu_shuffle(vec_null, vchar_Y_3, vec_char2int_third), 0); + vector float Y_12 = spu_convtf((vector unsigned int)spu_shuffle(vec_null, vchar_Y_3, vec_char2int_fourth), 0); + vector float Y_13 = spu_convtf((vector unsigned int)spu_shuffle(vec_null, vchar_Y_4, vec_char2int_first), 0); + vector float Y_14 = spu_convtf((vector unsigned int)spu_shuffle(vec_null, vchar_Y_4, vec_char2int_second), 0); + vector float Y_15 = spu_convtf((vector unsigned int)spu_shuffle(vec_null, vchar_Y_4, vec_char2int_third), 0); + vector float Y_16 = spu_convtf((vector unsigned int)spu_shuffle(vec_null, vchar_Y_4, vec_char2int_fourth), 0); + + const vector float R1a_precalculate = spu_mul(vec_R_precalc_coeff, vfloat_V_1); + const vector float R2a_precalculate = spu_mul(vec_R_precalc_coeff, vfloat_V_2); + const vector float R3a_precalculate = spu_mul(vec_R_precalc_coeff, vfloat_V_3); + const vector float R4a_precalculate = spu_mul(vec_R_precalc_coeff, vfloat_V_4); + + const vector float R1_precalculate = spu_shuffle(R1a_precalculate, R1a_precalculate, vec_select_floats_upper); + const vector float R2_precalculate = spu_shuffle(R1a_precalculate, R1a_precalculate, vec_select_floats_lower); + const vector float R3_precalculate = spu_shuffle(R2a_precalculate, R2a_precalculate, vec_select_floats_upper); + const vector float R4_precalculate = spu_shuffle(R2a_precalculate, R2a_precalculate, vec_select_floats_lower); + const vector float R5_precalculate = spu_shuffle(R3a_precalculate, R3a_precalculate, vec_select_floats_upper); + const vector float R6_precalculate = spu_shuffle(R3a_precalculate, R3a_precalculate, vec_select_floats_lower); + const vector float R7_precalculate = spu_shuffle(R4a_precalculate, R4a_precalculate, vec_select_floats_upper); + const vector float R8_precalculate = spu_shuffle(R4a_precalculate, R4a_precalculate, vec_select_floats_lower); + + + const vector float G1a_precalculate = spu_madd(vec_Gu_precalc_coeff, vfloat_U_1, spu_mul(vfloat_V_1, vec_Gv_precalc_coeff)); + const vector float G2a_precalculate = spu_madd(vec_Gu_precalc_coeff, vfloat_U_2, spu_mul(vfloat_V_2, vec_Gv_precalc_coeff)); + const vector float G3a_precalculate = spu_madd(vec_Gu_precalc_coeff, vfloat_U_3, spu_mul(vfloat_V_3, vec_Gv_precalc_coeff)); + const vector float G4a_precalculate = spu_madd(vec_Gu_precalc_coeff, vfloat_U_4, spu_mul(vfloat_V_4, vec_Gv_precalc_coeff)); + + const vector float G1_precalculate = spu_shuffle(G1a_precalculate, G1a_precalculate, vec_select_floats_upper); + const vector float G2_precalculate = spu_shuffle(G1a_precalculate, G1a_precalculate, vec_select_floats_lower); + const vector float G3_precalculate = spu_shuffle(G2a_precalculate, G2a_precalculate, vec_select_floats_upper); + const vector float G4_precalculate = spu_shuffle(G2a_precalculate, G2a_precalculate, vec_select_floats_lower); + const vector float G5_precalculate = spu_shuffle(G3a_precalculate, G3a_precalculate, vec_select_floats_upper); + const vector float G6_precalculate = spu_shuffle(G3a_precalculate, G3a_precalculate, vec_select_floats_lower); + const vector float G7_precalculate = spu_shuffle(G4a_precalculate, G4a_precalculate, vec_select_floats_upper); + const vector float G8_precalculate = spu_shuffle(G4a_precalculate, G4a_precalculate, vec_select_floats_lower); + + + const vector float B1a_precalculate = spu_mul(vec_B_precalc_coeff, vfloat_U_1); + const vector float B2a_precalculate = spu_mul(vec_B_precalc_coeff, vfloat_U_2); + const vector float B3a_precalculate = spu_mul(vec_B_precalc_coeff, vfloat_U_3); + const vector float B4a_precalculate = spu_mul(vec_B_precalc_coeff, vfloat_U_4); + + const vector float B1_precalculate = spu_shuffle(B1a_precalculate, B1a_precalculate, vec_select_floats_upper); + const vector float B2_precalculate = spu_shuffle(B1a_precalculate, B1a_precalculate, vec_select_floats_lower); + const vector float B3_precalculate = spu_shuffle(B2a_precalculate, B2a_precalculate, vec_select_floats_upper); + const vector float B4_precalculate = spu_shuffle(B2a_precalculate, B2a_precalculate, vec_select_floats_lower); + const vector float B5_precalculate = spu_shuffle(B3a_precalculate, B3a_precalculate, vec_select_floats_upper); + const vector float B6_precalculate = spu_shuffle(B3a_precalculate, B3a_precalculate, vec_select_floats_lower); + const vector float B7_precalculate = spu_shuffle(B4a_precalculate, B4a_precalculate, vec_select_floats_upper); + const vector float B8_precalculate = spu_shuffle(B4a_precalculate, B4a_precalculate, vec_select_floats_lower); + + + const vector unsigned int R_1 = vfloat_to_vuint(spu_add( Y_1, R1_precalculate)); + const vector unsigned int R_2 = vfloat_to_vuint(spu_add( Y_2, R2_precalculate)); + const vector unsigned int R_3 = vfloat_to_vuint(spu_add( Y_3, R3_precalculate)); + const vector unsigned int R_4 = vfloat_to_vuint(spu_add( Y_4, R4_precalculate)); + const vector unsigned int R_5 = vfloat_to_vuint(spu_add( Y_5, R5_precalculate)); + const vector unsigned int R_6 = vfloat_to_vuint(spu_add( Y_6, R6_precalculate)); + const vector unsigned int R_7 = vfloat_to_vuint(spu_add( Y_7, R7_precalculate)); + const vector unsigned int R_8 = vfloat_to_vuint(spu_add( Y_8, R8_precalculate)); + const vector unsigned int R_9 = vfloat_to_vuint(spu_add( Y_9, R1_precalculate)); + const vector unsigned int R_10 = vfloat_to_vuint(spu_add(Y_10, R2_precalculate)); + const vector unsigned int R_11 = vfloat_to_vuint(spu_add(Y_11, R3_precalculate)); + const vector unsigned int R_12 = vfloat_to_vuint(spu_add(Y_12, R4_precalculate)); + const vector unsigned int R_13 = vfloat_to_vuint(spu_add(Y_13, R5_precalculate)); + const vector unsigned int R_14 = vfloat_to_vuint(spu_add(Y_14, R6_precalculate)); + const vector unsigned int R_15 = vfloat_to_vuint(spu_add(Y_15, R7_precalculate)); + const vector unsigned int R_16 = vfloat_to_vuint(spu_add(Y_16, R8_precalculate)); + + const vector unsigned int G_1 = vfloat_to_vuint(spu_add( Y_1, G1_precalculate)); + const vector unsigned int G_2 = vfloat_to_vuint(spu_add( Y_2, G2_precalculate)); + const vector unsigned int G_3 = vfloat_to_vuint(spu_add( Y_3, G3_precalculate)); + const vector unsigned int G_4 = vfloat_to_vuint(spu_add( Y_4, G4_precalculate)); + const vector unsigned int G_5 = vfloat_to_vuint(spu_add( Y_5, G5_precalculate)); + const vector unsigned int G_6 = vfloat_to_vuint(spu_add( Y_6, G6_precalculate)); + const vector unsigned int G_7 = vfloat_to_vuint(spu_add( Y_7, G7_precalculate)); + const vector unsigned int G_8 = vfloat_to_vuint(spu_add( Y_8, G8_precalculate)); + const vector unsigned int G_9 = vfloat_to_vuint(spu_add( Y_9, G1_precalculate)); + const vector unsigned int G_10 = vfloat_to_vuint(spu_add(Y_10, G2_precalculate)); + const vector unsigned int G_11 = vfloat_to_vuint(spu_add(Y_11, G3_precalculate)); + const vector unsigned int G_12 = vfloat_to_vuint(spu_add(Y_12, G4_precalculate)); + const vector unsigned int G_13 = vfloat_to_vuint(spu_add(Y_13, G5_precalculate)); + const vector unsigned int G_14 = vfloat_to_vuint(spu_add(Y_14, G6_precalculate)); + const vector unsigned int G_15 = vfloat_to_vuint(spu_add(Y_15, G7_precalculate)); + const vector unsigned int G_16 = vfloat_to_vuint(spu_add(Y_16, G8_precalculate)); + + const vector unsigned int B_1 = vfloat_to_vuint(spu_add( Y_1, B1_precalculate)); + const vector unsigned int B_2 = vfloat_to_vuint(spu_add( Y_2, B2_precalculate)); + const vector unsigned int B_3 = vfloat_to_vuint(spu_add( Y_3, B3_precalculate)); + const vector unsigned int B_4 = vfloat_to_vuint(spu_add( Y_4, B4_precalculate)); + const vector unsigned int B_5 = vfloat_to_vuint(spu_add( Y_5, B5_precalculate)); + const vector unsigned int B_6 = vfloat_to_vuint(spu_add( Y_6, B6_precalculate)); + const vector unsigned int B_7 = vfloat_to_vuint(spu_add( Y_7, B7_precalculate)); + const vector unsigned int B_8 = vfloat_to_vuint(spu_add( Y_8, B8_precalculate)); + const vector unsigned int B_9 = vfloat_to_vuint(spu_add( Y_9, B1_precalculate)); + const vector unsigned int B_10 = vfloat_to_vuint(spu_add(Y_10, B2_precalculate)); + const vector unsigned int B_11 = vfloat_to_vuint(spu_add(Y_11, B3_precalculate)); + const vector unsigned int B_12 = vfloat_to_vuint(spu_add(Y_12, B4_precalculate)); + const vector unsigned int B_13 = vfloat_to_vuint(spu_add(Y_13, B5_precalculate)); + const vector unsigned int B_14 = vfloat_to_vuint(spu_add(Y_14, B6_precalculate)); + const vector unsigned int B_15 = vfloat_to_vuint(spu_add(Y_15, B7_precalculate)); + const vector unsigned int B_16 = vfloat_to_vuint(spu_add(Y_16, B8_precalculate)); + + *((vector unsigned int*)(bgra_addr + x)) = spu_or(spu_or(vec_alpha, B_1), spu_or(spu_slqwbyte( R_1, 2),spu_slqwbyte(G_1, 1))); + *((vector unsigned int*)(bgra_addr + x + 4)) = spu_or(spu_or(vec_alpha, B_2), spu_or(spu_slqwbyte( R_2, 2),spu_slqwbyte(G_2, 1))); + *((vector unsigned int*)(bgra_addr + x + 8)) = spu_or(spu_or(vec_alpha, B_3), spu_or(spu_slqwbyte( R_3, 2),spu_slqwbyte(G_3, 1))); + *((vector unsigned int*)(bgra_addr + x + 12)) = spu_or(spu_or(vec_alpha, B_4), spu_or(spu_slqwbyte( R_4, 2),spu_slqwbyte(G_4, 1))); + *((vector unsigned int*)(bgra_addr + x + 16)) = spu_or(spu_or(vec_alpha, B_5), spu_or(spu_slqwbyte( R_5, 2),spu_slqwbyte(G_5, 1))); + *((vector unsigned int*)(bgra_addr + x + 20)) = spu_or(spu_or(vec_alpha, B_6), spu_or(spu_slqwbyte( R_6, 2),spu_slqwbyte(G_6, 1))); + *((vector unsigned int*)(bgra_addr + x + 24)) = spu_or(spu_or(vec_alpha, B_7), spu_or(spu_slqwbyte( R_7, 2),spu_slqwbyte(G_7, 1))); + *((vector unsigned int*)(bgra_addr + x + 28)) = spu_or(spu_or(vec_alpha, B_8), spu_or(spu_slqwbyte( R_8, 2),spu_slqwbyte(G_8, 1))); + *((vector unsigned int*)(bgra_addr + x + width)) = spu_or(spu_or(vec_alpha, B_9), spu_or(spu_slqwbyte( R_9, 2),spu_slqwbyte(G_9, 1))); + *((vector unsigned int*)(bgra_addr + x + width + 4)) = spu_or(spu_or(vec_alpha, B_10), spu_or(spu_slqwbyte(R_10, 2),spu_slqwbyte(G_10, 1))); + *((vector unsigned int*)(bgra_addr + x + width + 8)) = spu_or(spu_or(vec_alpha, B_11), spu_or(spu_slqwbyte(R_11, 2),spu_slqwbyte(G_11, 1))); + *((vector unsigned int*)(bgra_addr + x + width + 12)) = spu_or(spu_or(vec_alpha, B_12), spu_or(spu_slqwbyte(R_12, 2),spu_slqwbyte(G_12, 1))); + *((vector unsigned int*)(bgra_addr + x + width + 16)) = spu_or(spu_or(vec_alpha, B_13), spu_or(spu_slqwbyte(R_13, 2),spu_slqwbyte(G_13, 1))); + *((vector unsigned int*)(bgra_addr + x + width + 20)) = spu_or(spu_or(vec_alpha, B_14), spu_or(spu_slqwbyte(R_14, 2),spu_slqwbyte(G_14, 1))); + *((vector unsigned int*)(bgra_addr + x + width + 24)) = spu_or(spu_or(vec_alpha, B_15), spu_or(spu_slqwbyte(R_15, 2),spu_slqwbyte(G_15, 1))); + *((vector unsigned int*)(bgra_addr + x + width + 28)) = spu_or(spu_or(vec_alpha, B_16), spu_or(spu_slqwbyte(R_16, 2),spu_slqwbyte(G_16, 1))); + } +} + diff --git a/3rdparty/SDL/src/video/qtopia/SDL_QPEApp.cc b/3rdparty/SDL/src/video/qtopia/SDL_QPEApp.cc new file mode 100644 index 0000000..8daf1c5 --- /dev/null +++ b/3rdparty/SDL/src/video/qtopia/SDL_QPEApp.cc @@ -0,0 +1,63 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#include <qpe/qpeapplication.h> +#include <qapplication.h> +#include <qevent.h> + +#include "SDL_thread.h" +#include "SDL_timer.h" +#include "SDL_error.h" + +/* Flag to tell whether or not the Be application is active or not */ +int SDL_QPEAppActive = 0; +static QPEApplication *app; + +int SDL_InitQPEApp() { + if(SDL_QPEAppActive <= 0) { + if(!qApp) { + int argc = 1; + char *argv[] = { { "SDLApp" } }; + app = new QPEApplication(argc, argv); + QWidget dummy; + app->showMainWidget(&dummy); + } else { + app = (QPEApplication*)qApp; + } + SDL_QPEAppActive++; + } + return 0; +} + +/* Quit the QPE Application, if there's nothing left to do */ +void SDL_QuitQPEApp(void) +{ + /* Decrement the application reference count */ + SDL_QPEAppActive--; + /* If the reference count reached zero, clean up the app */ + if ( SDL_QPEAppActive == 0 && app) { + delete app; + app = 0; + qApp = 0; + } +} diff --git a/3rdparty/SDL/src/video/qtopia/SDL_QPEApp.h b/3rdparty/SDL/src/video/qtopia/SDL_QPEApp.h new file mode 100644 index 0000000..8a9ab77 --- /dev/null +++ b/3rdparty/SDL/src/video/qtopia/SDL_QPEApp.h @@ -0,0 +1,33 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* Handle the QPE application loop */ + +/* Initialize the QPE Application, if it's not already started */ +extern int SDL_InitQPEApp(void); + +/* Quit the QPE Application, if there's nothing left to do */ +extern void SDL_QuitQPEApp(void); + +/* Flag to tell whether the app is active or not */ +extern int SDL_QPEAppActive; diff --git a/3rdparty/SDL/src/video/qtopia/SDL_QWin.cc b/3rdparty/SDL/src/video/qtopia/SDL_QWin.cc new file mode 100644 index 0000000..04474ed --- /dev/null +++ b/3rdparty/SDL/src/video/qtopia/SDL_QWin.cc @@ -0,0 +1,527 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#include "SDL_QWin.h" +#include <qapplication.h> +#include <qdirectpainter_qws.h> + +screenRotationT screenRotation = SDL_QT_NO_ROTATION; + +SDL_QWin::SDL_QWin(const QSize& size) + : QWidget(0, "SDL_main"), my_painter(0), my_image(0), + my_inhibit_resize(false), my_mouse_pos(-1,-1), my_flags(0), + my_has_fullscreen(false), my_locked(0) +{ + setBackgroundMode(NoBackground); +} + +SDL_QWin::~SDL_QWin() { + // Nothing to do yet. + if(my_image) { + delete my_image; + } +} + +void SDL_QWin::setImage(QImage *image) { + if ( my_image ) { + delete my_image; + } + my_image = image; + // setFixedSize(image->size()); +} + +void SDL_QWin::resizeEvent(QResizeEvent *e) { + if(size() != qApp->desktop()->size()) { + // Widget is not the correct size, so do the fullscreen magic + my_has_fullscreen = false; + enableFullscreen(); + } + if(my_inhibit_resize) { + my_inhibit_resize = false; + } else { + SDL_PrivateResize(e->size().width(), e->size().height()); + } +} + +void SDL_QWin::focusInEvent(QFocusEvent *) { + // Always do it here, no matter the size. + enableFullscreen(); + SDL_PrivateAppActive(true, SDL_APPINPUTFOCUS); +} + +void SDL_QWin::focusOutEvent(QFocusEvent *) { + my_has_fullscreen = false; + SDL_PrivateAppActive(false, SDL_APPINPUTFOCUS); +} + +void SDL_QWin::closeEvent(QCloseEvent *e) { + SDL_PrivateQuit(); + e->ignore(); +} + +void SDL_QWin::setMousePos(const QPoint &pos) { + if(my_image->width() == height()) { + if (screenRotation == SDL_QT_ROTATION_90) + my_mouse_pos = QPoint(height()-pos.y(), pos.x()); + else if (screenRotation == SDL_QT_ROTATION_270) + my_mouse_pos = QPoint(pos.y(), width()-pos.x()); + } else { + my_mouse_pos = pos; + } +} + +void SDL_QWin::mouseMoveEvent(QMouseEvent *e) { + Qt::ButtonState button = e->button(); + int sdlstate = 0; + if( (button & Qt::LeftButton)) { + sdlstate |= SDL_BUTTON_LMASK; + } + if( (button & Qt::RightButton)) { + sdlstate |= SDL_BUTTON_RMASK; + } + if( (button & Qt::MidButton)) { + sdlstate |= SDL_BUTTON_MMASK; + } + setMousePos(e->pos()); + SDL_PrivateMouseMotion(sdlstate, 0, my_mouse_pos.x(), my_mouse_pos.y()); +} + +void SDL_QWin::mousePressEvent(QMouseEvent *e) { + mouseMoveEvent(e); + Qt::ButtonState button = e->button(); + SDL_PrivateMouseButton(SDL_PRESSED, + (button & Qt::LeftButton) ? 1 : + ((button & Qt::RightButton) ? 2 : 3), + my_mouse_pos.x(), my_mouse_pos.y()); +} + +void SDL_QWin::mouseReleaseEvent(QMouseEvent *e) { + setMousePos(e->pos()); + Qt::ButtonState button = e->button(); + SDL_PrivateMouseButton(SDL_RELEASED, + (button & Qt::LeftButton) ? 1 : + ((button & Qt::RightButton) ? 2 : 3), + my_mouse_pos.x(), my_mouse_pos.y()); + my_mouse_pos = QPoint(-1, -1); +} + +static inline void +gs_fastRotateBlit_3 ( unsigned short *fb, + unsigned short *bits, + const QRect& rect ) +{ + // FIXME: this only works correctly for 240x320 displays + int startx, starty; + int width, height; + + startx = rect.left() >> 1; + starty = rect.top() >> 1; + width = ((rect.right() - rect.left()) >> 1) + 2; + height = ((rect.bottom() - rect.top()) >> 1) + 2; + + if((startx+width) > 120) { + width = 120 - startx; // avoid horizontal overflow + } + if((starty+height) > 160) { + height = 160 - starty; // avoid vertical overflow + } + + ulong *sp1, *sp2, *dp1, *dp2; + ulong stop, sbot, dtop, dbot; + + sp1 = (ulong*)bits + startx + starty*240; + sp2 = sp1 + 120; + dp1 = (ulong *)fb + (159 - starty) + startx*320; + dp2 = dp1 + 160; + int rowadd = (-320*width) - 1; + int rowadd2 = 240 - width; + // transfer in cells of 2x2 pixels in words + for (int y=0; y<height; y++) { + for (int x=0; x<width; x++) { + // read source pixels + stop = *sp1; + sbot = *sp2; + // rotate pixels + dtop = (sbot & 0xffff) + ((stop & 0xffff)<<16); + dbot = ((sbot & 0xffff0000)>>16) + (stop & 0xffff0000); + // write to framebuffer + *dp1 = dtop; + *dp2 = dbot; + // update source ptrs + sp1++; sp2++; + // update dest ptrs - 2 pix at a time + dp1 += 320; + dp2 += 320; + } + // adjust src ptrs - skip a row as we work in pairs + sp1 += rowadd2; + sp2 += rowadd2; + // adjust dest ptrs for rotation + dp1 += rowadd; + dp2 += rowadd; + } +} + +static inline void +gs_fastRotateBlit_1 ( unsigned short *fb, + unsigned short *bits, + const QRect& rect ) { + // FIXME: this only works correctly for 240x320 displays + int startx, starty; + int width, height; + + startx = rect.left() >> 1; + starty = rect.top() >> 1; + width = ((rect.right() - rect.left()) >> 1) + 2; + height = ((rect.bottom() - rect.top()) >> 1) + 2; + + if((startx+width) > 120) { + width = 120 - startx; // avoid horizontal overflow + } + if((starty+height) > 160) { + height = 160 - starty; // avoid vertical overflow + } + + ulong *sp1, *sp2, *dp1, *dp2; + ulong stop, sbot, dtop, dbot; + fb += 320*239; // Move "fb" to top left corner + sp1 = (ulong*)bits + startx + starty*240; + sp2 = sp1 + 120; + dp1 = (ulong*)fb - startx * 320 - starty; + dp2 = dp1 - 160; + int rowadd = (320*width) + 1; + int rowadd2 = 240 - width; + // transfer in cells of 2x2 pixels in words + for (int y=0; y<height; y++) { + for (int x=0; x<width; x++) { + // read + stop = *sp1; + sbot = *sp2; + // rotate + dtop = (stop & 0xffff) + ((sbot & 0xffff)<<16); + dbot = ((stop & 0xffff0000)>>16) + (sbot & 0xffff0000); + // write + *dp1 = dtop; + *dp2 = dbot; + // update source ptrs + sp1++; sp2++; + // update dest ptrs - 2 pix at a time + dp1 -= 320; + dp2 -= 320; + } + // adjust src ptrs - skip a row as we work in pairs + sp1 += rowadd2; + sp2 += rowadd2; + // adjust dest ptrs for rotation + dp1 += rowadd; + dp2 += rowadd; + } +} + +// desktop, SL-A300 etc +bool SDL_QWin::repaintRotation0(const QRect& rect) { + if(my_image->width() == width()) { + uchar *fb = (uchar*)my_painter->frameBuffer(); + uchar *buf = (uchar*)my_image->bits(); + if(rect == my_image->rect()) { + SDL_memcpy(fb, buf, width()*height()*2); + } else { + int h = rect.height(); + int wd = rect.width()<<1; + int fblineadd = my_painter->lineStep(); + int buflineadd = my_image->bytesPerLine(); + fb += (rect.left()<<1) + rect.top() * my_painter->lineStep(); + buf += (rect.left()<<1) + rect.top() * my_image->bytesPerLine(); + while(h--) { + SDL_memcpy(fb, buf, wd); + fb += fblineadd; + buf += buflineadd; + } + } + } else { + return false; // FIXME: Landscape + } +#ifdef __i386__ + my_painter->fillRect( rect, QBrush( Qt::NoBrush ) ); +#endif + return true; +} + + +// Sharp Zaurus SL-5500 etc +bool SDL_QWin::repaintRotation3(const QRect& rect) { + if(my_image->width() == width()) { + ushort *fb = (ushort*)my_painter->frameBuffer(); + ushort *buf = (ushort*)my_image->bits(); + gs_fastRotateBlit_3(fb, buf, rect); + } else { + // landscape mode + if (screenRotation == SDL_QT_ROTATION_90) { + uchar *fb = (uchar*)my_painter->frameBuffer(); + uchar *buf = (uchar*)my_image->bits(); + if(rect == my_image->rect()) { + SDL_memcpy(fb, buf, width()*height()*2); + } else { + int h = rect.height(); + int wd = rect.width()<<1; + int fblineadd = my_painter->lineStep(); + int buflineadd = my_image->bytesPerLine(); + fb += (rect.left()<<1) + rect.top() * my_painter->lineStep(); + buf += (rect.left()<<1) + rect.top() * my_image->bytesPerLine(); + while(h--) { + SDL_memcpy(fb, buf, wd); + fb += fblineadd; + buf += buflineadd; + } + } + } else if (screenRotation == SDL_QT_ROTATION_270) { + int h = rect.height(); + int wd = rect.width(); + int fblineadd = my_painter->lineStep() - (rect.width() << 1); + int buflineadd = my_image->bytesPerLine() - (rect.width() << 1); + int w; + + uchar *fb = (uchar*)my_painter->frameBuffer(); + uchar *buf = (uchar*)my_image->bits(); + + fb += ((my_painter->width() - (rect.top() + rect.height())) * + my_painter->lineStep()) + ((my_painter->height() - ((rect.left() + + rect.width()))) << 1); + + buf += my_image->bytesPerLine() * (rect.top() + rect.height()) - + (((my_image->width() - (rect.left() + rect.width())) << 1) + 2); + + while(h--) { + w = wd; + while(w--) *((unsigned short*)fb)++ = *((unsigned short*)buf)--; + fb += fblineadd; + buf -= buflineadd; + } + } + } + return true; +} + +// ipaq 3800... +bool SDL_QWin::repaintRotation1(const QRect& rect) { + if(my_image->width() == width()) { + ushort *fb = (ushort*)my_painter->frameBuffer(); + ushort *buf = (ushort*)my_image->bits(); + gs_fastRotateBlit_1(fb, buf, rect); + } else { + return false; // FIXME: landscape mode + } + return true; +} + +void SDL_QWin::repaintRect(const QRect& rect) { + if(!my_painter || !rect.width() || !rect.height()) { + return; + } + + if(QPixmap::defaultDepth() == 16) { + switch(my_painter->transformOrientation()) { + case 3: + if(repaintRotation3(rect)) { return; } + break; + case 1: + if(repaintRotation1(rect)) { return; } + break; + case 0: + if(repaintRotation0(rect)) { return; } + break; + } + } + my_painter->drawImage(rect.topLeft(), *my_image, rect); +} + +// This paints the current buffer to the screen, when desired. +void SDL_QWin::paintEvent(QPaintEvent *ev) { + if(my_image) { + lockScreen(true); + repaintRect(ev->rect()); + unlockScreen(); + } +} + +/* Function to translate a keyboard transition and queue the key event + * This should probably be a table although this method isn't exactly + * slow. + */ +void SDL_QWin::QueueKey(QKeyEvent *e, int pressed) +{ + SDL_keysym keysym; + int scancode = e->key(); + /* Set the keysym information */ + if(scancode >= 'A' && scancode <= 'Z') { + // Qt sends uppercase, SDL wants lowercase + keysym.sym = static_cast<SDLKey>(scancode + 32); + } else if(scancode >= 0x1000) { + // Special keys + switch(scancode) { + case Qt::Key_Escape: scancode = SDLK_ESCAPE; break; + case Qt::Key_Tab: scancode = SDLK_TAB; break; + case Qt::Key_Backspace: scancode = SDLK_BACKSPACE; break; + case Qt::Key_Return: scancode = SDLK_RETURN; break; + case Qt::Key_Enter: scancode = SDLK_KP_ENTER; break; + case Qt::Key_Insert: scancode = SDLK_INSERT; break; + case Qt::Key_Delete: scancode = SDLK_DELETE; break; + case Qt::Key_Pause: scancode = SDLK_PAUSE; break; + case Qt::Key_Print: scancode = SDLK_PRINT; break; + case Qt::Key_SysReq: scancode = SDLK_SYSREQ; break; + case Qt::Key_Home: scancode = SDLK_HOME; break; + case Qt::Key_End: scancode = SDLK_END; break; + // We want the control keys to rotate with the screen + case Qt::Key_Left: + if (screenRotation == SDL_QT_ROTATION_90) scancode = SDLK_UP; + else if (screenRotation == SDL_QT_ROTATION_270) scancode = SDLK_DOWN; + else scancode = SDLK_LEFT; + break; + case Qt::Key_Up: + if (screenRotation == SDL_QT_ROTATION_90) scancode = SDLK_RIGHT; + else if (screenRotation == SDL_QT_ROTATION_270) scancode = SDLK_LEFT; + else scancode = SDLK_UP; + break; + case Qt::Key_Right: + if (screenRotation == SDL_QT_ROTATION_90) scancode = SDLK_DOWN; + else if (screenRotation == SDL_QT_ROTATION_270) scancode = SDLK_UP; + else scancode = SDLK_RIGHT; + break; + case Qt::Key_Down: + if (screenRotation == SDL_QT_ROTATION_90) scancode = SDLK_LEFT; + else if (screenRotation == SDL_QT_ROTATION_270) scancode = SDLK_RIGHT; + else scancode = SDLK_DOWN; + break; + case Qt::Key_Prior: scancode = SDLK_PAGEUP; break; + case Qt::Key_Next: scancode = SDLK_PAGEDOWN; break; + case Qt::Key_Shift: scancode = SDLK_LSHIFT; break; + case Qt::Key_Control: scancode = SDLK_LCTRL; break; + case Qt::Key_Meta: scancode = SDLK_LMETA; break; + case Qt::Key_Alt: scancode = SDLK_LALT; break; + case Qt::Key_CapsLock: scancode = SDLK_CAPSLOCK; break; + case Qt::Key_NumLock: scancode = SDLK_NUMLOCK; break; + case Qt::Key_ScrollLock: scancode = SDLK_SCROLLOCK; break; + case Qt::Key_F1: scancode = SDLK_F1; break; + case Qt::Key_F2: scancode = SDLK_F2; break; + case Qt::Key_F3: scancode = SDLK_F3; break; + case Qt::Key_F4: scancode = SDLK_F4; break; + case Qt::Key_F5: scancode = SDLK_F5; break; + case Qt::Key_F6: scancode = SDLK_F6; break; + case Qt::Key_F7: scancode = SDLK_F7; break; + case Qt::Key_F8: scancode = SDLK_F8; break; + case Qt::Key_F9: scancode = SDLK_F9; break; + case Qt::Key_F10: scancode = SDLK_F10; break; + case Qt::Key_F11: scancode = SDLK_F11; break; + case Qt::Key_F12: scancode = SDLK_F12; break; + case Qt::Key_F13: scancode = SDLK_F13; break; + case Qt::Key_F14: scancode = SDLK_F14; break; + case Qt::Key_F15: scancode = SDLK_F15; break; + case Qt::Key_Super_L: scancode = SDLK_LSUPER; break; + case Qt::Key_Super_R: scancode = SDLK_RSUPER; break; + case Qt::Key_Menu: scancode = SDLK_MENU; break; + case Qt::Key_Help: scancode = SDLK_HELP; break; + + case Qt::Key_F33: + // FIXME: This is a hack to enable the OK key on + // Zaurii devices. SDLK_RETURN is a suitable key to use + // since it often is used as such. + // david@hedbor.org + scancode = SDLK_RETURN; + break; + default: + scancode = SDLK_UNKNOWN; + break; + } + keysym.sym = static_cast<SDLKey>(scancode); + } else { + keysym.sym = static_cast<SDLKey>(scancode); + } + keysym.scancode = scancode; + keysym.mod = KMOD_NONE; + ButtonState st = e->state(); + if( (st & ShiftButton) ) { keysym.mod = static_cast<SDLMod>(keysym.mod | KMOD_LSHIFT); } + if( (st & ControlButton) ) { keysym.mod = static_cast<SDLMod>(keysym.mod | KMOD_LCTRL); } + if( (st & AltButton) ) { keysym.mod = static_cast<SDLMod>(keysym.mod | KMOD_LALT); } + if ( SDL_TranslateUNICODE ) { + QChar qchar = e->text()[0]; + keysym.unicode = qchar.unicode(); + } else { + keysym.unicode = 0; + } + + /* NUMLOCK and CAPSLOCK are implemented as double-presses in reality */ + // if ( (keysym.sym == SDLK_NUMLOCK) || (keysym.sym == SDLK_CAPSLOCK) ) { + // pressed = 1; + // } + + /* Queue the key event */ + if ( pressed ) { + SDL_PrivateKeyboard(SDL_PRESSED, &keysym); + } else { + SDL_PrivateKeyboard(SDL_RELEASED, &keysym); + } +} + +void SDL_QWin::setFullscreen(bool fs_on) { + my_has_fullscreen = false; + enableFullscreen(); +} + +void SDL_QWin::enableFullscreen() { + // Make sure size is correct + if(!my_has_fullscreen) { + setFixedSize(qApp->desktop()->size()); + // This call is needed because showFullScreen won't work + // correctly if the widget already considers itself to be fullscreen. + showNormal(); + // This is needed because showNormal() forcefully changes the window + // style to WSTyle_TopLevel. + setWFlags(WStyle_Customize | WStyle_NoBorder); + // Enable fullscreen. + showFullScreen(); + my_has_fullscreen = true; + } +} + +bool SDL_QWin::lockScreen(bool force) { + if(!my_painter) { + if(force || (isVisible() && isActiveWindow())) { + my_painter = new QDirectPainter(this); + } else { + return false; + } + } + my_locked++; // Increate lock refcount + return true; +} + +void SDL_QWin::unlockScreen() { + if(my_locked > 0) { + my_locked--; // decrease lock refcount; + } + if(!my_locked && my_painter) { + my_painter->end(); + delete my_painter; + my_painter = 0; + } +} diff --git a/3rdparty/SDL/src/video/qtopia/SDL_QWin.h b/3rdparty/SDL/src/video/qtopia/SDL_QWin.h new file mode 100644 index 0000000..2531834 --- /dev/null +++ b/3rdparty/SDL/src/video/qtopia/SDL_QWin.h @@ -0,0 +1,110 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#ifndef _SDL_QWin_h +#define _SDL_QWin_h + +#include <stdio.h> + +#include <qimage.h> +#include <qpixmap.h> +#include <qwidget.h> +#include <qpainter.h> +#include <qdirectpainter_qws.h> + +#include "SDL_events.h" + +extern "C" { +#include "../../events/SDL_events_c.h" +}; + +typedef enum { + SDL_QT_NO_ROTATION = 0, + SDL_QT_ROTATION_90, + SDL_QT_ROTATION_270 +} screenRotationT; + +extern screenRotationT screenRotation; + +class SDL_QWin : public QWidget +{ + void QueueKey(QKeyEvent *e, int pressed); + public: + SDL_QWin(const QSize& size); + virtual ~SDL_QWin(); + virtual bool shown(void) { + return isVisible(); + } + /* If called, the next resize event will not be forwarded to SDL. */ + virtual void inhibitResize(void) { + my_inhibit_resize = true; + } + void setImage(QImage *image); + void setOffset(int x, int y) { + my_offset = QPoint(x, y); + } + void GetXYOffset(int &x, int &y) { + x = my_offset.x(); + y = my_offset.y(); + } + QImage *image(void) { return my_image; } + + void setWFlags(WFlags flags) { + QWidget::setWFlags(flags); + my_flags = flags; + } + const QPoint& mousePos() const { return my_mouse_pos; } + void setMousePos(const QPoint& newpos); + void setFullscreen(bool); + + bool lockScreen(bool force=false); + void unlockScreen(); + void repaintRect(const QRect& rect); + protected: + /* Handle resizing of the window */ + virtual void resizeEvent(QResizeEvent *e); + void focusInEvent(QFocusEvent *); + void focusOutEvent(QFocusEvent *); + void closeEvent(QCloseEvent *e); + void mouseMoveEvent(QMouseEvent *e); + void mousePressEvent(QMouseEvent *e); + void mouseReleaseEvent(QMouseEvent *e); + void paintEvent(QPaintEvent *ev); + void keyPressEvent(QKeyEvent *e) { QueueKey(e, 1); } + void keyReleaseEvent(QKeyEvent *e) { QueueKey(e, 0); } + private: + bool repaintRotation0(const QRect& rect); + bool repaintRotation1(const QRect& rect); + bool repaintRotation3(const QRect& rect); + void enableFullscreen(); + QDirectPainter *my_painter; + QImage *my_image; + bool my_inhibit_resize; + QPoint my_offset; + QPoint my_mouse_pos; + WFlags my_flags; + WFlags my_has_fullscreen; + unsigned int my_locked; +}; + +#endif /* _SDL_QWin_h */ diff --git a/3rdparty/SDL/src/video/qtopia/SDL_lowvideo.h b/3rdparty/SDL/src/video/qtopia/SDL_lowvideo.h new file mode 100644 index 0000000..1d05c72 --- /dev/null +++ b/3rdparty/SDL/src/video/qtopia/SDL_lowvideo.h @@ -0,0 +1,65 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#ifndef _SDL_lowvideo_h +#define _SDL_lowvideo_h + +#include "SDL_mouse.h" +#include "../SDL_sysvideo.h" + +/* Hidden "this" pointer for the video functions */ +#define _THIS SDL_VideoDevice *_this + +/* Private display data */ +struct SDL_PrivateVideoData { + /* The main window */ + SDL_QWin *SDL_Win; + + /* The fullscreen mode list */ +#define NUM_MODELISTS 4 /* 8, 16, 24, and 32 bits-per-pixel */ + int SDL_nummodes[NUM_MODELISTS]; + SDL_Rect **SDL_modelist[NUM_MODELISTS]; + + /* A completely clear cursor */ + WMcursor *BlankCursor; + + /* Mouse state variables */ + Uint32 last_buttons; + QPoint last_point; + + /* Keyboard state variables */ + int key_flip; + //struct key_info keyinfo[2]; +}; +/* Old variable names */ +#define SDL_Win (_this->hidden->SDL_Win) +#define saved_mode (_this->hidden->saved_mode) +#define SDL_nummodes (_this->hidden->SDL_nummodes) +#define SDL_modelist (_this->hidden->SDL_modelist) +#define SDL_BlankCursor (_this->hidden->BlankCursor) +#define last_buttons (_this->hidden->last_buttons) +#define last_point (_this->hidden->last_point) +#define key_flip (_this->hidden->key_flip) +#define keyinfo (_this->hidden->keyinfo) + +#endif /* _SDL_lowvideo_h */ diff --git a/3rdparty/SDL/src/video/qtopia/SDL_sysevents.cc b/3rdparty/SDL/src/video/qtopia/SDL_sysevents.cc new file mode 100644 index 0000000..4aaf814 --- /dev/null +++ b/3rdparty/SDL/src/video/qtopia/SDL_sysevents.cc @@ -0,0 +1,269 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#include <qpe/qpeapplication.h> + +#include <stdio.h> +#include <string.h> +#include "SDL_error.h" +#include "SDL_events.h" +#include "SDL_QWin.h" +#include "SDL_lowvideo.h" +#include "SDL_timer.h" + +extern "C" { +#include "../../events/SDL_sysevents.h" +#include "../../events/SDL_events_c.h" +#include "SDL_sysevents_c.h" + + // static SDLKey keymap[128]; +/* This is special because we know it will be run in a loop in a separate + thread. Normally this function should loop as long as there are input + states changing, i.e. new events arriving. +*/ +void QT_PumpEvents(_THIS) +{ + if(!qApp) { + return; + } + // printf("processing events: %p\n", qApp); + //qApp->processOneEvent(); // wait for a event + qApp->processEvents(); // and process all outstanding ones +#if 0 + BView *view; + BRect bounds; + BPoint point; + uint32 buttons; + const uint32 button_masks[3] = { + B_PRIMARY_MOUSE_BUTTON, + B_TERTIARY_MOUSE_BUTTON, + B_SECONDARY_MOUSE_BUTTON, + }; + unsigned int i, j; + + /* Check out the mouse buttons and position (slight race condition) */ + if ( SDL_Win->Lock() ) { + /* Don't do anything if we have no view */ + view = SDL_Win->View(); + if ( ! view ) { + SDL_Win->Unlock(); + return; + } + bounds = view->Bounds(); + /* Get new input state, if still active */ + if ( SDL_Win->IsActive() ) { + key_flip = !key_flip; + get_key_info(&keyinfo[key_flip]); + view->GetMouse(&point, &buttons, true); + } else { + key_flip = key_flip; + point = last_point; + buttons = last_buttons; + } + SDL_Win->Unlock(); + } else { + return; + } + + /* If our view is active, we'll find key changes here */ + if ( SDL_memcmp(keyinfo[0].key_states, keyinfo[1].key_states, 16) != 0 ) { + for ( i=0; i<16; ++i ) { + Uint8 new_state, transition; + + new_state = keyinfo[key_flip].key_states[i]; + transition = keyinfo[!key_flip].key_states[i] ^ + keyinfo[ key_flip].key_states[i]; + for ( j=0; j<8; ++j ) { + if ( transition&0x80 ) + QueueKey(i*8+j, new_state&0x80); + transition <<= 1; + new_state <<= 1; + } + } + } + + /* We check keyboard, but not mouse if mouse isn't in window */ + if ( ! bounds.Contains(point) ) { + /* Mouse moved outside our view? */ + if ( SDL_GetAppState() & SDL_APPMOUSEFOCUS ) { + SDL_PrivateAppActive(0, SDL_APPMOUSEFOCUS); + be_app->SetCursor(B_HAND_CURSOR); + } + return; + } + /* Has the mouse moved back into our view? */ + if ( ! (SDL_GetAppState() & SDL_APPMOUSEFOCUS) ) { + /* Reset the B_HAND_CURSOR to our own */ + SDL_PrivateAppActive(1, SDL_APPMOUSEFOCUS); + SDL_SetCursor(NULL); + } + + /* Check for mouse motion */ + if ( point != last_point ) { + int x, y; + + SDL_Win->GetXYOffset(x, y); + x = (int)point.x - x; + y = (int)point.y - y; + SDL_PrivateMouseMotion(0, 0, x, y); + } + last_point = point; + + /* Add any mouse button events */ + for ( i=0; i<SDL_TABLESIZE(button_masks); ++i ) { + if ( (buttons ^ last_buttons) & button_masks[i] ) { + if ( buttons & button_masks[i] ) { + SDL_PrivateMouseButton(SDL_PRESSED, 1+i, 0, 0); + } else { + SDL_PrivateMouseButton(SDL_RELEASED, 1+i, 0, 0); + } + } + } + last_buttons = buttons; +#endif +} + +void QT_InitOSKeymap(_THIS) +{ +#if 0 + unsigned int i; + + /* Initialize all the key states as "up" */ + key_flip = 0; + SDL_memset(keyinfo[key_flip].key_states, 0, 16); + + /* Initialize the key translation table */ + for ( i=0; i<SDL_TABLESIZE(keymap); ++i ) + keymap[i] = SDLK_UNKNOWN; + + // keymap[0x01] = SDLK_ESCAPE; + // keymap[B_F1_KEY] = SDLK_F1; + // keymap[B_F2_KEY] = SDLK_F2; + // keymap[B_F3_KEY] = SDLK_F3; + // keymap[B_F4_KEY] = SDLK_F4; + // keymap[B_F5_KEY] = SDLK_F5; + // keymap[B_F6_KEY] = SDLK_F6; + // keymap[B_F7_KEY] = SDLK_F7; + // keymap[B_F8_KEY] = SDLK_F8; + // keymap[B_F9_KEY] = SDLK_F9; + // keymap[B_F10_KEY] = SDLK_F10; + // keymap[B_F11_KEY] = SDLK_F11; + // keymap[B_F12_KEY] = SDLK_F12; + // keymap[B_PRINT_KEY] = SDLK_PRINT; + //keymap[B_SCROLL_KEY] = SDLK_SCROLLOCK; + // keymap[B_PAUSE_KEY] = SDLK_PAUSE; + keymap[0x11] = SDLK_BACKQUOTE; + keymap[0x12] = SDLK_1; + keymap[0x13] = SDLK_2; + keymap[0x14] = SDLK_3; + keymap[0x15] = SDLK_4; + keymap[0x16] = SDLK_5; + keymap[0x17] = SDLK_6; + keymap[0x18] = SDLK_7; + keymap[0x19] = SDLK_8; + keymap[0x1a] = SDLK_9; + keymap[0x1b] = SDLK_0; + keymap[0x1c] = SDLK_MINUS; + keymap[0x1d] = SDLK_EQUALS; + keymap[0x1e] = SDLK_BACKSPACE; + keymap[0x1f] = SDLK_INSERT; + keymap[0x20] = SDLK_HOME; + keymap[0x21] = SDLK_PAGEUP; + //keymap[0x22] = SDLK_NUMLOCK; + keymap[0x23] = SDLK_KP_DIVIDE; + keymap[0x24] = SDLK_KP_MULTIPLY; + keymap[0x25] = SDLK_KP_MINUS; + keymap[0x26] = SDLK_TAB; + keymap[0x27] = SDLK_q; + keymap[0x28] = SDLK_w; + keymap[0x29] = SDLK_e; + keymap[0x2a] = SDLK_r; + keymap[0x2b] = SDLK_t; + keymap[0x2c] = SDLK_y; + keymap[0x2d] = SDLK_u; + keymap[0x2e] = SDLK_i; + keymap[0x2f] = SDLK_o; + keymap[0x30] = SDLK_p; + keymap[0x31] = SDLK_LEFTBRACKET; + keymap[0x32] = SDLK_RIGHTBRACKET; + keymap[0x33] = SDLK_BACKSLASH; + keymap[0x34] = SDLK_DELETE; + keymap[0x35] = SDLK_END; + keymap[0x36] = SDLK_PAGEDOWN; + keymap[0x37] = SDLK_KP7; + keymap[0x38] = SDLK_KP8; + keymap[0x39] = SDLK_KP9; + keymap[0x3a] = SDLK_KP_PLUS; + //keymap[0x3b] = SDLK_CAPSLOCK; + keymap[0x3c] = SDLK_a; + keymap[0x3d] = SDLK_s; + keymap[0x3e] = SDLK_d; + keymap[0x3f] = SDLK_f; + keymap[0x40] = SDLK_g; + keymap[0x41] = SDLK_h; + keymap[0x42] = SDLK_j; + keymap[0x43] = SDLK_k; + keymap[0x44] = SDLK_l; + keymap[0x45] = SDLK_SEMICOLON; + keymap[0x46] = SDLK_QUOTE; + keymap[0x47] = SDLK_RETURN; + keymap[0x48] = SDLK_KP4; + keymap[0x49] = SDLK_KP5; + keymap[0x4a] = SDLK_KP6; + keymap[0x4b] = SDLK_LSHIFT; + keymap[0x4c] = SDLK_z; + keymap[0x4d] = SDLK_x; + keymap[0x4e] = SDLK_c; + keymap[0x4f] = SDLK_v; + keymap[0x50] = SDLK_b; + keymap[0x51] = SDLK_n; + keymap[0x52] = SDLK_m; + keymap[0x53] = SDLK_COMMA; + keymap[0x54] = SDLK_PERIOD; + keymap[0x55] = SDLK_SLASH; + keymap[0x56] = SDLK_RSHIFT; + keymap[0x57] = SDLK_UP; + keymap[0x58] = SDLK_KP1; + keymap[0x59] = SDLK_KP2; + keymap[0x5a] = SDLK_KP3; + keymap[0x5b] = SDLK_KP_ENTER; + //keymap[0x5c] = SDLK_LCTRL; + //keymap[0x5d] = SDLK_LALT; + keymap[0x5e] = SDLK_SPACE; + //keymap[0x5f] = SDLK_RALT; + //keymap[0x60] = SDLK_RCTRL; + keymap[0x61] = SDLK_LEFT; + keymap[0x62] = SDLK_DOWN; + keymap[0x63] = SDLK_RIGHT; + keymap[0x64] = SDLK_KP0; + keymap[0x65] = SDLK_KP_PERIOD; + //keymap[0x66] = SDLK_LMETA; + //keymap[0x67] = SDLK_RMETA; + //keymap[0x68] = SDLK_MENU; + keymap[0x69] = SDLK_EURO; + keymap[0x6a] = SDLK_KP_EQUALS; + keymap[0x6b] = SDLK_POWER; +#endif +} + +}; /* Extern C */ diff --git a/3rdparty/SDL/src/video/qtopia/SDL_sysevents_c.h b/3rdparty/SDL/src/video/qtopia/SDL_sysevents_c.h new file mode 100644 index 0000000..5e26759 --- /dev/null +++ b/3rdparty/SDL/src/video/qtopia/SDL_sysevents_c.h @@ -0,0 +1,31 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#include "SDL_lowvideo.h" + +/* Variables and functions exported by SDL_sysevents.c to other parts + of the native video subsystem (SDL_sysvideo.c) +*/ + +extern void QT_InitOSKeymap(_THIS); +extern void QT_PumpEvents(_THIS); diff --git a/3rdparty/SDL/src/video/qtopia/SDL_sysmouse.cc b/3rdparty/SDL/src/video/qtopia/SDL_sysmouse.cc new file mode 100644 index 0000000..1a655b6 --- /dev/null +++ b/3rdparty/SDL/src/video/qtopia/SDL_sysmouse.cc @@ -0,0 +1,56 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#include "SDL_QWin.h" + +extern "C" { + +#include "SDL_sysmouse_c.h" + +/* The implementation dependent data for the window manager cursor */ +struct WMcursor { + char *bits; +}; +WMcursor *QT_CreateWMCursor(_THIS, + Uint8 *data, Uint8 *mask, int w, int h, int hot_x, int hot_y) +{ + static WMcursor dummy; + dummy.bits = 0; + return &dummy; +} + +int QT_ShowWMCursor(_THIS, WMcursor *cursor) +{ + return 1; +} + +void QT_FreeWMCursor(_THIS, WMcursor *cursor) +{ +} + +void QT_WarpWMCursor(_THIS, Uint16 x, Uint16 y) +{ + SDL_Win->setMousePos(QPoint(x, y)); +} + +}; /* Extern C */ diff --git a/3rdparty/SDL/src/video/qtopia/SDL_sysmouse_c.h b/3rdparty/SDL/src/video/qtopia/SDL_sysmouse_c.h new file mode 100644 index 0000000..98e4cf5 --- /dev/null +++ b/3rdparty/SDL/src/video/qtopia/SDL_sysmouse_c.h @@ -0,0 +1,32 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#include "SDL_lowvideo.h" + +/* Functions to be exported */ +extern void QT_FreeWMCursor(_THIS, WMcursor *cursor); +extern WMcursor *QT_CreateWMCursor(_THIS, + Uint8 *data, Uint8 *mask, int w, int h, int hot_x, int hot_y); +extern int QT_ShowWMCursor(_THIS, WMcursor *cursor); +extern void QT_WarpWMCursor(_THIS, Uint16 x, Uint16 y); + diff --git a/3rdparty/SDL/src/video/qtopia/SDL_sysvideo.cc b/3rdparty/SDL/src/video/qtopia/SDL_sysvideo.cc new file mode 100644 index 0000000..0e07874 --- /dev/null +++ b/3rdparty/SDL/src/video/qtopia/SDL_sysvideo.cc @@ -0,0 +1,403 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* Qtopia based framebuffer implementation */ + +#include <unistd.h> + +#include <qapplication.h> +#include <qpe/qpeapplication.h> + +#include "SDL_timer.h" + +#include "SDL_QWin.h" + +extern "C" { + +#include "../SDL_sysvideo.h" +#include "../../events/SDL_events_c.h" +#include "SDL_sysevents_c.h" +#include "SDL_sysmouse_c.h" +#include "SDL_syswm_c.h" +#include "SDL_lowvideo.h" + + //#define QTOPIA_DEBUG +#define QT_HIDDEN_SIZE 32 /* starting hidden window size */ + + /* Name of the environment variable used to invert the screen rotation or not: + Possible values: + !=0 : Screen is 270 rotated + 0: Screen is 90 rotated*/ +#define SDL_QT_ROTATION_ENV_NAME "SDL_QT_INVERT_ROTATION" + + /* Initialization/Query functions */ + static int QT_VideoInit(_THIS, SDL_PixelFormat *vformat); + static SDL_Rect **QT_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags); + static SDL_Surface *QT_SetVideoMode(_THIS, SDL_Surface *current, int width, int height, int bpp, Uint32 flags); + static void QT_UpdateMouse(_THIS); + static int QT_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors); + static void QT_VideoQuit(_THIS); + + /* Hardware surface functions */ + static int QT_AllocHWSurface(_THIS, SDL_Surface *surface); + static int QT_LockHWSurface(_THIS, SDL_Surface *surface); + static void QT_UnlockHWSurface(_THIS, SDL_Surface *surface); + static void QT_FreeHWSurface(_THIS, SDL_Surface *surface); + + static int QT_ToggleFullScreen(_THIS, int fullscreen); + + static int QT_IconifyWindow(_THIS); + static SDL_GrabMode QT_GrabInput(_THIS, SDL_GrabMode mode); + + /* FB driver bootstrap functions */ + + static int QT_Available(void) + { + return(1); + } + + static void QT_DeleteDevice(SDL_VideoDevice *device) + { + SDL_free(device->hidden); + SDL_free(device); + } + + static SDL_VideoDevice *QT_CreateDevice(int devindex) + { + SDL_VideoDevice *device; + + /* Initialize all variables that we clean on shutdown */ + device = (SDL_VideoDevice *)SDL_malloc(sizeof(SDL_VideoDevice)); + if ( device ) { + SDL_memset(device, 0, (sizeof *device)); + device->hidden = (struct SDL_PrivateVideoData *) + SDL_malloc((sizeof *device->hidden)); + } + if ( (device == NULL) || (device->hidden == NULL) ) { + SDL_OutOfMemory(); + if ( device ) { + SDL_free(device); + } + return(0); + } + SDL_memset(device->hidden, 0, (sizeof *device->hidden)); + + /* Set the function pointers */ + device->VideoInit = QT_VideoInit; + device->ListModes = QT_ListModes; + device->SetVideoMode = QT_SetVideoMode; + device->UpdateMouse = QT_UpdateMouse; + device->SetColors = QT_SetColors; + device->UpdateRects = NULL; + device->VideoQuit = QT_VideoQuit; + device->AllocHWSurface = QT_AllocHWSurface; + device->CheckHWBlit = NULL; + device->FillHWRect = NULL; + device->SetHWColorKey = NULL; + device->SetHWAlpha = NULL; + device->LockHWSurface = QT_LockHWSurface; + device->UnlockHWSurface = QT_UnlockHWSurface; + device->FlipHWSurface = NULL; + device->FreeHWSurface = QT_FreeHWSurface; + device->SetIcon = NULL; + device->SetCaption = QT_SetWMCaption; + device->IconifyWindow = QT_IconifyWindow; + device->GrabInput = QT_GrabInput; + device->GetWMInfo = NULL; + device->FreeWMCursor = QT_FreeWMCursor; + device->CreateWMCursor = QT_CreateWMCursor; + device->ShowWMCursor = QT_ShowWMCursor; + device->WarpWMCursor = QT_WarpWMCursor; + device->InitOSKeymap = QT_InitOSKeymap; + device->PumpEvents = QT_PumpEvents; + + device->free = QT_DeleteDevice; + device->ToggleFullScreen = QT_ToggleFullScreen; + + /* Set the driver flags */ + device->handles_any_size = 0; + + return device; + } + + VideoBootStrap Qtopia_bootstrap = { + "qtopia", "Qtopia / QPE graphics", + QT_Available, QT_CreateDevice + }; + + /* Function to sort the display_list */ + static int CompareModes(const void *A, const void *B) + { +#if 0 + const display_mode *a = (display_mode *)A; + const display_mode *b = (display_mode *)B; + + if ( a->space == b->space ) { + return((b->virtual_width*b->virtual_height)- + (a->virtual_width*a->virtual_height)); + } else { + return(ColorSpaceToBitsPerPixel(b->space)- + ColorSpaceToBitsPerPixel(a->space)); + } +#endif + return 0; + } + + /* Yes, this isn't the fastest it could be, but it works nicely */ + static int QT_AddMode(_THIS, int index, unsigned int w, unsigned int h) + { + SDL_Rect *mode; + int i; + int next_mode; + + /* Check to see if we already have this mode */ + if ( SDL_nummodes[index] > 0 ) { + for ( i=SDL_nummodes[index]-1; i >= 0; --i ) { + mode = SDL_modelist[index][i]; + if ( (mode->w == w) && (mode->h == h) ) { + return(0); + } + } + } + + /* Set up the new video mode rectangle */ + mode = (SDL_Rect *)SDL_malloc(sizeof *mode); + if ( mode == NULL ) { + SDL_OutOfMemory(); + return(-1); + } + mode->x = 0; + mode->y = 0; + mode->w = w; + mode->h = h; +#ifdef QTOPIA_DEBUG + fprintf(stderr, "Adding mode %dx%d at %d bytes per pixel\n", w, h, index+1); +#endif + + /* Allocate the new list of modes, and fill in the new mode */ + next_mode = SDL_nummodes[index]; + SDL_modelist[index] = (SDL_Rect **) + SDL_realloc(SDL_modelist[index], (1+next_mode+1)*sizeof(SDL_Rect *)); + if ( SDL_modelist[index] == NULL ) { + SDL_OutOfMemory(); + SDL_nummodes[index] = 0; + SDL_free(mode); + return(-1); + } + SDL_modelist[index][next_mode] = mode; + SDL_modelist[index][next_mode+1] = NULL; + SDL_nummodes[index]++; + + return(0); + } + + int QT_VideoInit(_THIS, SDL_PixelFormat *vformat) + { + /* Initialize the QPE Application */ + /* Determine the screen depth */ + vformat->BitsPerPixel = QPixmap::defaultDepth(); + + // For now we hardcode the current depth because anything else + // might as well be emulated by SDL rather than by Qtopia. + + QSize desktop_size = qApp->desktop()->size(); + QT_AddMode(_this, ((vformat->BitsPerPixel+7)/8)-1, + desktop_size.width(), desktop_size.height()); + QT_AddMode(_this, ((vformat->BitsPerPixel+7)/8)-1, + desktop_size.height(), desktop_size.width()); + + /* Determine the current screen size */ + _this->info.current_w = desktop_size.width(); + _this->info.current_h = desktop_size.height(); + + /* Create the window / widget */ + SDL_Win = new SDL_QWin(QSize(QT_HIDDEN_SIZE, QT_HIDDEN_SIZE)); + ((QPEApplication*)qApp)->showMainWidget(SDL_Win); + /* Fill in some window manager capabilities */ + _this->info.wm_available = 0; + + /* We're done! */ + return(0); + } + + /* We support any dimension at our bit-depth */ + SDL_Rect **QT_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags) + { + SDL_Rect **modes; + + modes = ((SDL_Rect **)0); + if ( (flags & SDL_FULLSCREEN) == SDL_FULLSCREEN ) { + modes = SDL_modelist[((format->BitsPerPixel+7)/8)-1]; + } else { + if ( format->BitsPerPixel == + _this->screen->format->BitsPerPixel ) { + modes = ((SDL_Rect **)-1); + } + } + return(modes); + } + + /* Various screen update functions available */ + static void QT_NormalUpdate(_THIS, int numrects, SDL_Rect *rects); + + + static int QT_SetFullScreen(_THIS, SDL_Surface *screen, int fullscreen) + { + return -1; + } + + static int QT_ToggleFullScreen(_THIS, int fullscreen) + { + return -1; + } + + /* FIXME: check return values and cleanup here */ + SDL_Surface *QT_SetVideoMode(_THIS, SDL_Surface *current, + int width, int height, int bpp, Uint32 flags) + { + + QImage *qimage; + QSize desktop_size = qApp->desktop()->size(); + + + current->flags = 0; //SDL_FULLSCREEN; // We always run fullscreen. + + if(width <= desktop_size.width() + && height <= desktop_size.height()) { + current->w = desktop_size.width(); + current->h = desktop_size.height(); + } else if(width <= desktop_size.height() && height <= desktop_size.width()) { + // Landscape mode + char * envString = SDL_getenv(SDL_QT_ROTATION_ENV_NAME); + int envValue = envString ? atoi(envString) : 0; + screenRotation = envValue ? SDL_QT_ROTATION_270 : SDL_QT_ROTATION_90; + current->h = desktop_size.width(); + current->w = desktop_size.height(); + } else { + SDL_SetError("Unsupported resolution, %dx%d\n", width, height); + } + if ( flags & SDL_OPENGL ) { + SDL_SetError("OpenGL not supported"); + return(NULL); + } + /* Create the QImage framebuffer */ + qimage = new QImage(current->w, current->h, bpp); + if (qimage->isNull()) { + SDL_SetError("Couldn't create screen bitmap"); + delete qimage; + return(NULL); + } + current->pitch = qimage->bytesPerLine(); + current->pixels = (void *)qimage->bits(); + SDL_Win->setImage(qimage); + _this->UpdateRects = QT_NormalUpdate; + SDL_Win->setFullscreen(true); + /* We're done */ + return(current); + } + + /* Update the current mouse state and position */ + void QT_UpdateMouse(_THIS) + { + QPoint point(-1, -1); + if ( SDL_Win->isActiveWindow() ) { + point = SDL_Win->mousePos(); + } + + if ( (point.x() >= 0) && (point.x() < SDL_VideoSurface->w) && + (point.y() >= 0) && (point.y() < SDL_VideoSurface->h) ) { + SDL_PrivateAppActive(1, SDL_APPMOUSEFOCUS); + SDL_PrivateMouseMotion(0, 0, + (Sint16)point.x(), (Sint16)point.y()); + } else { + SDL_PrivateAppActive(0, SDL_APPMOUSEFOCUS); + } + } + + /* We don't actually allow hardware surfaces other than the main one */ + static int QT_AllocHWSurface(_THIS, SDL_Surface *surface) + { + return(-1); + } + static void QT_FreeHWSurface(_THIS, SDL_Surface *surface) + { + return; + } + static int QT_LockHWSurface(_THIS, SDL_Surface *surface) + { + return(0); + } + static void QT_UnlockHWSurface(_THIS, SDL_Surface *surface) + { + return; + } + + static void QT_NormalUpdate(_THIS, int numrects, SDL_Rect *rects) + { + if(SDL_Win->lockScreen()) { + for(int i=0; i<numrects; ++i ) { + QRect rect(rects[i].x, rects[i].y, + rects[i].w, rects[i].h); + SDL_Win->repaintRect(rect); + } + SDL_Win->unlockScreen(); + } + } + /* Is the system palette settable? */ + int QT_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors) + { + return -1; + } + + void QT_VideoQuit(_THIS) + { + // This is dumb, but if I free this, the app doesn't exit correctly. + // Of course, this will leak memory if init video is done more than once. + // Sucks but such is life. + + // -- David Hedbor + // delete SDL_Win; + // SDL_Win = 0; + _this->screen->pixels = NULL; + QT_GrabInput(_this, SDL_GRAB_OFF); + } + + static int QT_IconifyWindow(_THIS) { + SDL_Win->hide(); + + return true; + } + + static SDL_GrabMode QT_GrabInput(_THIS, SDL_GrabMode mode) { + if(mode == SDL_GRAB_OFF) { + QPEApplication::grabKeyboard(); + qApp->processEvents(); + QPEApplication::ungrabKeyboard(); + } else { + QPEApplication::grabKeyboard(); + } + qApp->processEvents(); + return mode; + } + +}; /* Extern C */ diff --git a/3rdparty/SDL/src/video/qtopia/SDL_syswm.cc b/3rdparty/SDL/src/video/qtopia/SDL_syswm.cc new file mode 100644 index 0000000..47f988f --- /dev/null +++ b/3rdparty/SDL/src/video/qtopia/SDL_syswm.cc @@ -0,0 +1,35 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#include "SDL_QWin.h" + +extern "C" { + +#include "SDL_syswm_c.h" + +void QT_SetWMCaption(_THIS, const char *title, const char *icon) +{ + SDL_Win->setCaption(title); +} + +}; /* Extern C */ diff --git a/3rdparty/SDL/src/video/qtopia/SDL_syswm_c.h b/3rdparty/SDL/src/video/qtopia/SDL_syswm_c.h new file mode 100644 index 0000000..4e4326b --- /dev/null +++ b/3rdparty/SDL/src/video/qtopia/SDL_syswm_c.h @@ -0,0 +1,28 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#include "SDL_lowvideo.h" + +/* Functions to be exported */ +extern void QT_SetWMCaption(_THIS, const char *title, const char *icon); + diff --git a/3rdparty/SDL/src/video/quartz/CGS.h b/3rdparty/SDL/src/video/quartz/CGS.h new file mode 100644 index 0000000..abe47f7 --- /dev/null +++ b/3rdparty/SDL/src/video/quartz/CGS.h @@ -0,0 +1,84 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* + Obscuring code: maximum number of windows above ours (inclusive) + + Note: this doesn't work too well in practice and should be + phased out when we add OpenGL 2D acceleration. It was never + enabled in the first place, so this shouldn't be a problem ;-) +*/ +#define kMaxWindows 256 + +/* Some of the Core Graphics Server API for obscuring code */ +#define kCGSWindowLevelTop 2147483632 +#define kCGSWindowLevelDockIconDrag 500 +#define kCGSWindowLevelDockMenu 101 +#define kCGSWindowLevelMenuIgnore 21 +#define kCGSWindowLevelMenu 20 +#define kCGSWindowLevelDockLabel 12 +#define kCGSWindowLevelDockIcon 11 +#define kCGSWindowLevelDock 10 +#define kCGSWindowLevelUtility 3 +#define kCGSWindowLevelNormal 0 + +/* + For completeness; We never use these window levels, they are always below us + #define kCGSWindowLevelMBarShadow -20 + #define kCGSWindowLevelDesktopPicture -2147483647 + #define kCGSWindowLevelDesktop -2147483648 +*/ + +typedef CGError CGSError; +typedef long CGSWindowCount; +typedef void * CGSConnectionID; +typedef int CGSWindowID; +typedef CGSWindowID* CGSWindowIDList; +typedef CGWindowLevel CGSWindowLevel; +typedef NSRect CGSRect; + +extern CGSConnectionID _CGSDefaultConnection (); + +extern CGSError CGSGetOnScreenWindowList (CGSConnectionID cid, + CGSConnectionID owner, + CGSWindowCount listCapacity, + CGSWindowIDList list, + CGSWindowCount *listCount); + +extern CGSError CGSGetScreenRectForWindow (CGSConnectionID cid, + CGSWindowID wid, + CGSRect *rect); + +extern CGWindowLevel CGSGetWindowLevel (CGSConnectionID cid, + CGSWindowID wid, + CGSWindowLevel *level); + +extern CGSError CGSDisplayHWFill (CGDirectDisplayID id, unsigned int x, unsigned int y, + unsigned int w, unsigned int h, unsigned int color); + +extern CGSError CGSDisplayCanHWFill (CGDirectDisplayID id); + +extern CGSError CGSGetMouseEnabledFlags (CGSConnectionID cid, CGSWindowID wid, int *flags); + +int CGSDisplayHWSync (CGDirectDisplayID id); + diff --git a/3rdparty/SDL/src/video/quartz/SDL_QuartzEvents.m b/3rdparty/SDL/src/video/quartz/SDL_QuartzEvents.m new file mode 100644 index 0000000..773eb01 --- /dev/null +++ b/3rdparty/SDL/src/video/quartz/SDL_QuartzEvents.m @@ -0,0 +1,1063 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#include "SDL_QuartzVideo.h" +#include "SDL_QuartzWM.h" + +#include <IOKit/IOMessage.h> /* For wake from sleep detection */ +#include <IOKit/pwr_mgt/IOPMLib.h> /* For wake from sleep detection */ +#include "SDL_QuartzKeys.h" + +/* + * On Leopard, this is missing from the 64-bit headers + */ +#if defined(__LP64__) && !defined(__POWER__) +/* + * Workaround for a bug in the 10.5 SDK: By accident, OSService.h does + * not include Power.h at all when compiling in 64bit mode. This has + * been fixed in 10.6, but for 10.5, we manually define UsrActivity + * to ensure compilation works. + */ +#define UsrActivity 1 +#endif + +/* + * In Panther, this header defines device dependent masks for + * right side keys. These definitions only exist in Panther, but + * the header seems to exist at least in Jaguar and probably earlier + * versions of the OS, so this should't break anything. + */ +#include <IOKit/hidsystem/IOLLEvent.h> +/* + * These are not defined before Panther. To keep the code compiling + * on systems without these, I will define if they don't exist. + */ +#ifndef NX_DEVICERCTLKEYMASK + #define NX_DEVICELCTLKEYMASK 0x00000001 +#endif +#ifndef NX_DEVICELSHIFTKEYMASK + #define NX_DEVICELSHIFTKEYMASK 0x00000002 +#endif +#ifndef NX_DEVICERSHIFTKEYMASK + #define NX_DEVICERSHIFTKEYMASK 0x00000004 +#endif +#ifndef NX_DEVICELCMDKEYMASK + #define NX_DEVICELCMDKEYMASK 0x00000008 +#endif +#ifndef NX_DEVICERCMDKEYMASK + #define NX_DEVICERCMDKEYMASK 0x00000010 +#endif +#ifndef NX_DEVICELALTKEYMASK + #define NX_DEVICELALTKEYMASK 0x00000020 +#endif +#ifndef NX_DEVICERALTKEYMASK + #define NX_DEVICERALTKEYMASK 0x00000040 +#endif +#ifndef NX_DEVICERCTLKEYMASK + #define NX_DEVICERCTLKEYMASK 0x00002000 +#endif + +void QZ_InitOSKeymap (_THIS) { + BOOL saw_layout = NO; + UInt32 state; + UInt32 value; + Uint16 i; + int world = SDLK_WORLD_0; + + for ( i=0; i<SDL_TABLESIZE(keymap); ++i ) + keymap[i] = SDLK_UNKNOWN; + + /* This keymap is almost exactly the same as the OS 9 one */ + keymap[QZ_ESCAPE] = SDLK_ESCAPE; + keymap[QZ_F1] = SDLK_F1; + keymap[QZ_F2] = SDLK_F2; + keymap[QZ_F3] = SDLK_F3; + keymap[QZ_F4] = SDLK_F4; + keymap[QZ_F5] = SDLK_F5; + keymap[QZ_F6] = SDLK_F6; + keymap[QZ_F7] = SDLK_F7; + keymap[QZ_F8] = SDLK_F8; + keymap[QZ_F9] = SDLK_F9; + keymap[QZ_F10] = SDLK_F10; + keymap[QZ_F11] = SDLK_F11; + keymap[QZ_F12] = SDLK_F12; + keymap[QZ_F13] = SDLK_F13; + keymap[QZ_F14] = SDLK_F14; + keymap[QZ_F15] = SDLK_F15; +/* + keymap[QZ_PRINT] = SDLK_PRINT; + keymap[QZ_SCROLLOCK] = SDLK_SCROLLOCK; + keymap[QZ_PAUSE] = SDLK_PAUSE; +*/ + keymap[QZ_POWER] = SDLK_POWER; + keymap[QZ_BACKQUOTE] = SDLK_BACKQUOTE; + keymap[QZ_1] = SDLK_1; + keymap[QZ_2] = SDLK_2; + keymap[QZ_3] = SDLK_3; + keymap[QZ_4] = SDLK_4; + keymap[QZ_5] = SDLK_5; + keymap[QZ_6] = SDLK_6; + keymap[QZ_7] = SDLK_7; + keymap[QZ_8] = SDLK_8; + keymap[QZ_9] = SDLK_9; + keymap[QZ_0] = SDLK_0; + keymap[QZ_MINUS] = SDLK_MINUS; + keymap[QZ_EQUALS] = SDLK_EQUALS; + keymap[QZ_BACKSPACE] = SDLK_BACKSPACE; + keymap[QZ_INSERT] = SDLK_INSERT; + keymap[QZ_HOME] = SDLK_HOME; + keymap[QZ_PAGEUP] = SDLK_PAGEUP; + keymap[QZ_NUMLOCK] = SDLK_NUMLOCK; + keymap[QZ_KP_EQUALS] = SDLK_KP_EQUALS; + keymap[QZ_KP_DIVIDE] = SDLK_KP_DIVIDE; + keymap[QZ_KP_MULTIPLY] = SDLK_KP_MULTIPLY; + keymap[QZ_TAB] = SDLK_TAB; + keymap[QZ_q] = SDLK_q; + keymap[QZ_w] = SDLK_w; + keymap[QZ_e] = SDLK_e; + keymap[QZ_r] = SDLK_r; + keymap[QZ_t] = SDLK_t; + keymap[QZ_y] = SDLK_y; + keymap[QZ_u] = SDLK_u; + keymap[QZ_i] = SDLK_i; + keymap[QZ_o] = SDLK_o; + keymap[QZ_p] = SDLK_p; + keymap[QZ_LEFTBRACKET] = SDLK_LEFTBRACKET; + keymap[QZ_RIGHTBRACKET] = SDLK_RIGHTBRACKET; + keymap[QZ_BACKSLASH] = SDLK_BACKSLASH; + keymap[QZ_DELETE] = SDLK_DELETE; + keymap[QZ_END] = SDLK_END; + keymap[QZ_PAGEDOWN] = SDLK_PAGEDOWN; + keymap[QZ_KP7] = SDLK_KP7; + keymap[QZ_KP8] = SDLK_KP8; + keymap[QZ_KP9] = SDLK_KP9; + keymap[QZ_KP_MINUS] = SDLK_KP_MINUS; + keymap[QZ_CAPSLOCK] = SDLK_CAPSLOCK; + keymap[QZ_a] = SDLK_a; + keymap[QZ_s] = SDLK_s; + keymap[QZ_d] = SDLK_d; + keymap[QZ_f] = SDLK_f; + keymap[QZ_g] = SDLK_g; + keymap[QZ_h] = SDLK_h; + keymap[QZ_j] = SDLK_j; + keymap[QZ_k] = SDLK_k; + keymap[QZ_l] = SDLK_l; + keymap[QZ_SEMICOLON] = SDLK_SEMICOLON; + keymap[QZ_QUOTE] = SDLK_QUOTE; + keymap[QZ_RETURN] = SDLK_RETURN; + keymap[QZ_KP4] = SDLK_KP4; + keymap[QZ_KP5] = SDLK_KP5; + keymap[QZ_KP6] = SDLK_KP6; + keymap[QZ_KP_PLUS] = SDLK_KP_PLUS; + keymap[QZ_LSHIFT] = SDLK_LSHIFT; + keymap[QZ_RSHIFT] = SDLK_RSHIFT; + keymap[QZ_z] = SDLK_z; + keymap[QZ_x] = SDLK_x; + keymap[QZ_c] = SDLK_c; + keymap[QZ_v] = SDLK_v; + keymap[QZ_b] = SDLK_b; + keymap[QZ_n] = SDLK_n; + keymap[QZ_m] = SDLK_m; + keymap[QZ_COMMA] = SDLK_COMMA; + keymap[QZ_PERIOD] = SDLK_PERIOD; + keymap[QZ_SLASH] = SDLK_SLASH; + keymap[QZ_UP] = SDLK_UP; + keymap[QZ_KP1] = SDLK_KP1; + keymap[QZ_KP2] = SDLK_KP2; + keymap[QZ_KP3] = SDLK_KP3; + keymap[QZ_KP_ENTER] = SDLK_KP_ENTER; + keymap[QZ_LCTRL] = SDLK_LCTRL; + keymap[QZ_LALT] = SDLK_LALT; + keymap[QZ_LMETA] = SDLK_LMETA; + keymap[QZ_RCTRL] = SDLK_RCTRL; + keymap[QZ_RALT] = SDLK_RALT; + keymap[QZ_RMETA] = SDLK_RMETA; + keymap[QZ_SPACE] = SDLK_SPACE; + keymap[QZ_LEFT] = SDLK_LEFT; + keymap[QZ_DOWN] = SDLK_DOWN; + keymap[QZ_RIGHT] = SDLK_RIGHT; + keymap[QZ_KP0] = SDLK_KP0; + keymap[QZ_KP_PERIOD] = SDLK_KP_PERIOD; + keymap[QZ_IBOOK_ENTER] = SDLK_KP_ENTER; + keymap[QZ_IBOOK_RIGHT] = SDLK_RIGHT; + keymap[QZ_IBOOK_DOWN] = SDLK_DOWN; + keymap[QZ_IBOOK_UP] = SDLK_UP; + keymap[QZ_IBOOK_LEFT] = SDLK_LEFT; + + /* + Up there we setup a static scancode->keysym map. However, it will not + work very well on international keyboard. Hence we now query MacOS + for its own keymap to adjust our own mapping table. However, this is + basically only useful for ascii char keys. This is also the reason + why we keep the static table, too. + */ + +#if (MAC_OS_X_VERSION_MAX_ALLOWED >= 1050) + if (TISCopyCurrentKeyboardLayoutInputSource != NULL) { + TISInputSourceRef src = TISCopyCurrentKeyboardLayoutInputSource(); + if (src != NULL) { + CFDataRef data = (CFDataRef) + TISGetInputSourceProperty(src, + kTISPropertyUnicodeKeyLayoutData); + if (data != NULL) { + const UCKeyboardLayout *layout = (const UCKeyboardLayout *) + CFDataGetBytePtr(data); + if (layout != NULL) { + const UInt32 kbdtype = LMGetKbdType(); + saw_layout = YES; + + /* Loop over all 127 possible scan codes */ + for (i = 0; i < 0x7F; i++) { + UniChar buf[16]; + UniCharCount count = 0; + + /* We pretend a clean start to begin with (i.e. no dead keys active */ + state = 0; + + if (UCKeyTranslate(layout, i, kUCKeyActionDown, 0, kbdtype, + 0, &state, 16, &count, buf) != noErr) { + continue; + } + + /* If the state become 0, it was a dead key. We need to + translate again, passing in the new state, to get + the actual key value */ + if (state != 0) { + if (UCKeyTranslate(layout, i, kUCKeyActionDown, 0, kbdtype, + 0, &state, 16, &count, buf) != noErr) { + continue; + } + } + + if (count != 1) { + continue; /* no multi-char. Use SDL 1.3 instead. :) */ + } + + value = (UInt32) buf[0]; + if (value >= 128) { + /* Some non-ASCII char, map it to SDLK_WORLD_* */ + if (world < 0xFF) { + keymap[i] = world++; + } + } else if (value >= 32) { /* non-control ASCII char */ + keymap[i] = value; + } + } + } + } + CFRelease(src); + } + } +#endif + +#if (MAC_OS_X_VERSION_MIN_REQUIRED < 1050) + if (!saw_layout) { + /* Get a pointer to the systems cached KCHR */ + const void *KCHRPtr = (const void *)GetScriptManagerVariable(smKCHRCache); + if (KCHRPtr) + { + /* Loop over all 127 possible scan codes */ + for (i = 0; i < 0x7F; i++) + { + /* We pretend a clean start to begin with (i.e. no dead keys active */ + state = 0; + + /* Now translate the key code to a key value */ + value = KeyTranslate(KCHRPtr, i, &state) & 0xff; + + /* If the state become 0, it was a dead key. We need to translate again, + passing in the new state, to get the actual key value */ + if (state != 0) + value = KeyTranslate(KCHRPtr, i, &state) & 0xff; + + /* Now we should have an ascii value, or 0. Try to figure out to which SDL symbol it maps */ + if (value >= 128) { /* Some non-ASCII char, map it to SDLK_WORLD_* */ + if (world < 0xFF) { + keymap[i] = world++; + } + } else if (value >= 32) { /* non-control ASCII char */ + keymap[i] = value; + } + } + } + } +#endif + + /* + The keypad codes are re-setup here, because the loop above cannot + distinguish between a key on the keypad and a regular key. We maybe + could get around this problem in another fashion: NSEvent's flags + include a "NSNumericPadKeyMask" bit; we could check that and modify + the symbol we return on the fly. However, this flag seems to exhibit + some weird behaviour related to the num lock key + */ + keymap[QZ_KP0] = SDLK_KP0; + keymap[QZ_KP1] = SDLK_KP1; + keymap[QZ_KP2] = SDLK_KP2; + keymap[QZ_KP3] = SDLK_KP3; + keymap[QZ_KP4] = SDLK_KP4; + keymap[QZ_KP5] = SDLK_KP5; + keymap[QZ_KP6] = SDLK_KP6; + keymap[QZ_KP7] = SDLK_KP7; + keymap[QZ_KP8] = SDLK_KP8; + keymap[QZ_KP9] = SDLK_KP9; + keymap[QZ_KP_MINUS] = SDLK_KP_MINUS; + keymap[QZ_KP_PLUS] = SDLK_KP_PLUS; + keymap[QZ_KP_PERIOD] = SDLK_KP_PERIOD; + keymap[QZ_KP_EQUALS] = SDLK_KP_EQUALS; + keymap[QZ_KP_DIVIDE] = SDLK_KP_DIVIDE; + keymap[QZ_KP_MULTIPLY] = SDLK_KP_MULTIPLY; + keymap[QZ_KP_ENTER] = SDLK_KP_ENTER; +} + +static void QZ_DoKey (_THIS, int state, NSEvent *event) { + + NSString *chars = NULL; + unsigned int i, numChars; + SDL_keysym key; + + /* + A key event can contain multiple characters, + or no characters at all. In most cases, it + will contain a single character. If it contains + 0 characters, we'll use 0 as the unicode. If it + contains multiple characters, we'll use 0 as + the scancode/keysym. + */ + if (SDL_TranslateUNICODE && state == SDL_PRESSED) { + [field_edit interpretKeyEvents:[NSArray arrayWithObject:event]]; + chars = [ event characters ]; + numChars = [ chars length ]; + if (numChars > 0) + [field_edit setString:@""]; + } else { + numChars = 0; + } + + if (numChars == 0) { + + key.scancode = [ event keyCode ]; + key.sym = keymap [ key.scancode ]; + key.unicode = 0; + key.mod = KMOD_NONE; + + SDL_PrivateKeyboard (state, &key); + } + else if (numChars >= 1) { + + key.scancode = [ event keyCode ]; + key.sym = keymap [ key.scancode ]; + key.unicode = [ chars characterAtIndex:0 ]; + key.mod = KMOD_NONE; + + SDL_PrivateKeyboard (state, &key); + + for (i = 1; i < numChars; i++) { + + key.scancode = 0; + key.sym = 0; + key.unicode = [ chars characterAtIndex:i]; + key.mod = KMOD_NONE; + + SDL_PrivateKeyboard (state, &key); + } + } + + if (SDL_getenv ("SDL_ENABLEAPPEVENTS")) + [ NSApp sendEvent:event ]; +} + +/* This is the original behavior, before support was added for + * differentiating between left and right versions of the keys. + */ +static void QZ_DoUnsidedModifiers (_THIS, unsigned int newMods) { + + const int mapping[] = { SDLK_CAPSLOCK, SDLK_LSHIFT, SDLK_LCTRL, SDLK_LALT, SDLK_LMETA }; + + int i; + int bit; + SDL_keysym key; + + key.scancode = 0; + key.sym = SDLK_UNKNOWN; + key.unicode = 0; + key.mod = KMOD_NONE; + + /* Iterate through the bits, testing each against the current modifiers */ + for (i = 0, bit = NSAlphaShiftKeyMask; bit <= NSCommandKeyMask; bit <<= 1, ++i) { + + unsigned int currentMask, newMask; + + currentMask = current_mods & bit; + newMask = newMods & bit; + + if ( currentMask && + currentMask != newMask ) { /* modifier up event */ + + key.sym = mapping[i]; + /* If this was Caps Lock, we need some additional voodoo to make SDL happy */ + if (bit == NSAlphaShiftKeyMask) + SDL_PrivateKeyboard (SDL_PRESSED, &key); + SDL_PrivateKeyboard (SDL_RELEASED, &key); + } + else if ( newMask && + currentMask != newMask ) { /* modifier down event */ + + key.sym = mapping[i]; + SDL_PrivateKeyboard (SDL_PRESSED, &key); + /* If this was Caps Lock, we need some additional voodoo to make SDL happy */ + if (bit == NSAlphaShiftKeyMask) + SDL_PrivateKeyboard (SDL_RELEASED, &key); + } + } +} + +/* This is a helper function for QZ_HandleModifierSide. This + * function reverts back to behavior before the distinction between + * sides was made. + */ +static void QZ_HandleNonDeviceModifier ( _THIS, unsigned int device_independent_mask, unsigned int newMods, unsigned int key_sym) { + unsigned int currentMask, newMask; + SDL_keysym key; + + key.scancode = 0; + key.sym = key_sym; + key.unicode = 0; + key.mod = KMOD_NONE; + + /* Isolate just the bits we care about in the depedent bits so we can + * figure out what changed + */ + currentMask = current_mods & device_independent_mask; + newMask = newMods & device_independent_mask; + + if ( currentMask && + currentMask != newMask ) { /* modifier up event */ + SDL_PrivateKeyboard (SDL_RELEASED, &key); + } + else if ( newMask && + currentMask != newMask ) { /* modifier down event */ + SDL_PrivateKeyboard (SDL_PRESSED, &key); + } +} + +/* This is a helper function for QZ_HandleModifierSide. + * This function sets the actual SDL_PrivateKeyboard event. + */ +static void QZ_HandleModifierOneSide ( _THIS, unsigned int newMods, + unsigned int key_sym, + unsigned int sided_device_dependent_mask ) { + + SDL_keysym key; + unsigned int current_dep_mask, new_dep_mask; + + key.scancode = 0; + key.sym = key_sym; + key.unicode = 0; + key.mod = KMOD_NONE; + + /* Isolate just the bits we care about in the depedent bits so we can + * figure out what changed + */ + current_dep_mask = current_mods & sided_device_dependent_mask; + new_dep_mask = newMods & sided_device_dependent_mask; + + /* We now know that this side bit flipped. But we don't know if + * it went pressed to released or released to pressed, so we must + * find out which it is. + */ + if( new_dep_mask && + current_dep_mask != new_dep_mask ) { + /* Modifier down event */ + SDL_PrivateKeyboard (SDL_PRESSED, &key); + } + else /* Modifier up event */ { + SDL_PrivateKeyboard (SDL_RELEASED, &key); + } +} + +/* This is a helper function for QZ_DoSidedModifiers. + * This function will figure out if the modifier key is the left or right side, + * e.g. left-shift vs right-shift. + */ +static void QZ_HandleModifierSide ( _THIS, int device_independent_mask, + unsigned int newMods, + unsigned int left_key_sym, + unsigned int right_key_sym, + unsigned int left_device_dependent_mask, + unsigned int right_device_dependent_mask ) { + unsigned int device_dependent_mask = 0; + unsigned int diff_mod = 0; + + device_dependent_mask = left_device_dependent_mask | right_device_dependent_mask; + /* On the basis that the device independent mask is set, but there are + * no device dependent flags set, we'll assume that we can't detect this + * keyboard and revert to the unsided behavior. + */ + if ( (device_dependent_mask & newMods) == 0 ) { + /* Revert to the old behavior */ + QZ_HandleNonDeviceModifier ( this, device_independent_mask, newMods, left_key_sym ); + return; + } + + /* XOR the previous state against the new state to see if there's a change */ + diff_mod = (device_dependent_mask & current_mods) + ^ (device_dependent_mask & newMods); + + if ( diff_mod ) { + /* A change in state was found. Isolate the left and right bits + * to handle them separately just in case the values can simulataneously + * change or if the bits don't both exist. + */ + if ( left_device_dependent_mask & diff_mod ) { + QZ_HandleModifierOneSide ( this, newMods, left_key_sym, left_device_dependent_mask ); + } + if ( right_device_dependent_mask & diff_mod ) { + QZ_HandleModifierOneSide ( this, newMods, right_key_sym, right_device_dependent_mask ); + } + } +} + +/* This is a helper function for QZ_DoSidedModifiers. + * This function will release a key press in the case that + * it is clear that the modifier has been released (i.e. one side + * can't still be down). + */ +static void QZ_ReleaseModifierSide ( _THIS, + unsigned int device_independent_mask, + unsigned int newMods, + unsigned int left_key_sym, + unsigned int right_key_sym, + unsigned int left_device_dependent_mask, + unsigned int right_device_dependent_mask ) { + unsigned int device_dependent_mask = 0; + SDL_keysym key; + + key.scancode = 0; + key.sym = SDLK_UNKNOWN; + key.unicode = 0; + key.mod = KMOD_NONE; + + device_dependent_mask = left_device_dependent_mask | right_device_dependent_mask; + /* On the basis that the device independent mask is set, but there are + * no device dependent flags set, we'll assume that we can't detect this + * keyboard and revert to the unsided behavior. + */ + if ( (device_dependent_mask & current_mods) == 0 ) { + /* In this case, we can't detect the keyboard, so use the left side + * to represent both, and release it. + */ + key.sym = left_key_sym; + SDL_PrivateKeyboard (SDL_RELEASED, &key); + + return; + } + + + /* + * This could have been done in an if-else case because at this point, + * we know that all keys have been released when calling this function. + * But I'm being paranoid so I want to handle each separately, + * so I hope this doesn't cause other problems. + */ + if ( left_device_dependent_mask & current_mods ) { + key.sym = left_key_sym; + SDL_PrivateKeyboard (SDL_RELEASED, &key); + } + if ( right_device_dependent_mask & current_mods ) { + key.sym = right_key_sym; + SDL_PrivateKeyboard (SDL_RELEASED, &key); + } +} + +/* This is a helper function for QZ_DoSidedModifiers. + * This function handles the CapsLock case. + */ +static void QZ_HandleCapsLock (_THIS, unsigned int newMods) { + unsigned int currentMask, newMask; + SDL_keysym key; + + key.scancode = 0; + key.sym = SDLK_CAPSLOCK; + key.unicode = 0; + key.mod = KMOD_NONE; + + currentMask = current_mods & NSAlphaShiftKeyMask; + newMask = newMods & NSAlphaShiftKeyMask; + + if ( currentMask && + currentMask != newMask ) { /* modifier up event */ + /* If this was Caps Lock, we need some additional voodoo to make SDL happy */ + SDL_PrivateKeyboard (SDL_PRESSED, &key); + SDL_PrivateKeyboard (SDL_RELEASED, &key); + } + else if ( newMask && + currentMask != newMask ) { /* modifier down event */ + /* If this was Caps Lock, we need some additional voodoo to make SDL happy */ + SDL_PrivateKeyboard (SDL_PRESSED, &key); + SDL_PrivateKeyboard (SDL_RELEASED, &key); + } +} + +/* This function will handle the modifier keys and also determine the + * correct side of the key. + */ +static void QZ_DoSidedModifiers (_THIS, unsigned int newMods) { + /* Set up arrays for the key syms for the left and right side. */ + const unsigned int left_mapping[] = { SDLK_LSHIFT, SDLK_LCTRL, SDLK_LALT, SDLK_LMETA }; + const unsigned int right_mapping[] = { SDLK_RSHIFT, SDLK_RCTRL, SDLK_RALT, SDLK_RMETA }; + /* Set up arrays for the device dependent masks with indices that + * correspond to the _mapping arrays + */ + const unsigned int left_device_mapping[] = { NX_DEVICELSHIFTKEYMASK, NX_DEVICELCTLKEYMASK, NX_DEVICELALTKEYMASK, NX_DEVICELCMDKEYMASK }; + const unsigned int right_device_mapping[] = { NX_DEVICERSHIFTKEYMASK, NX_DEVICERCTLKEYMASK, NX_DEVICERALTKEYMASK, NX_DEVICERCMDKEYMASK }; + + unsigned int i; + unsigned int bit; + + /* Handle CAPSLOCK separately because it doesn't have a left/right side */ + QZ_HandleCapsLock ( this, newMods ); + + /* Iterate through the bits, testing each against the current modifiers */ + for (i = 0, bit = NSShiftKeyMask; bit <= NSCommandKeyMask; bit <<= 1, ++i) { + + unsigned int currentMask, newMask; + + currentMask = current_mods & bit; + newMask = newMods & bit; + + /* If the bit is set, we must always examine it because the left + * and right side keys may alternate or both may be pressed. + */ + if ( newMask ) { + QZ_HandleModifierSide ( this, bit, newMods, + left_mapping[i], + right_mapping[i], + left_device_mapping[i], + right_device_mapping[i] ); + } + /* If the state changed from pressed to unpressed, we must examine + * the device dependent bits to release the correct keys. + */ + else if ( currentMask && + currentMask != newMask ) { /* modifier up event */ + QZ_ReleaseModifierSide ( this, bit, newMods, + left_mapping[i], + right_mapping[i], + left_device_mapping[i], + right_device_mapping[i] ); + } + } +} + +/* This function is called to handle the modifiers. + * It will try to distinguish between the left side and right side + * of the keyboard for those modifiers that qualify if the + * operating system version supports it. Otherwise, the code + * will not try to make the distinction. + */ +static void QZ_DoModifiers (_THIS, unsigned int newMods) { + + if (current_mods == newMods) + return; + + /* + * Starting with Panther (10.3.0), the ability to distinguish between + * left side and right side modifiers is available. + */ + if( system_version >= 0x1030 ) { + QZ_DoSidedModifiers (this, newMods); + } + else { + QZ_DoUnsidedModifiers (this, newMods); + } + + current_mods = newMods; +} + +static void QZ_GetMouseLocation (_THIS, NSPoint *p) { + *p = [ NSEvent mouseLocation ]; /* global coordinates */ + if (qz_window) + QZ_PrivateGlobalToLocal (this, p); + QZ_PrivateCocoaToSDL (this, p); +} + +void QZ_DoActivate (_THIS) { + + SDL_PrivateAppActive (1, SDL_APPINPUTFOCUS | (QZ_IsMouseInWindow (this) ? SDL_APPMOUSEFOCUS : 0)); + + QZ_UpdateCursor(this); + + /* Regrab input, only if it was previously grabbed */ + if ( current_grab_mode == SDL_GRAB_ON ) { + + /* Restore cursor location if input was grabbed */ + QZ_PrivateWarpCursor (this, cursor_loc.x, cursor_loc.y); + QZ_ChangeGrabState (this, QZ_ENABLE_GRAB); + } + else { + /* Update SDL's mouse location */ + NSPoint p; + QZ_GetMouseLocation (this, &p); + SDL_PrivateMouseMotion (0, 0, p.x, p.y); + } + + QZ_UpdateCursor(this); +} + +void QZ_DoDeactivate (_THIS) { + + SDL_PrivateAppActive (0, SDL_APPINPUTFOCUS | SDL_APPMOUSEFOCUS); + + /* Get the current cursor location, for restore on activate */ + QZ_GetMouseLocation (this, &cursor_loc); + + /* Reassociate mouse and cursor */ + CGAssociateMouseAndMouseCursorPosition (1); + + QZ_UpdateCursor(this); +} + +void QZ_SleepNotificationHandler (void * refcon, + io_service_t service, + natural_t messageType, + void * messageArgument ) +{ + SDL_VideoDevice *this = (SDL_VideoDevice*)refcon; + + switch(messageType) + { + case kIOMessageSystemWillSleep: + IOAllowPowerChange(power_connection, (long) messageArgument); + break; + case kIOMessageCanSystemSleep: + IOAllowPowerChange(power_connection, (long) messageArgument); + break; + case kIOMessageSystemHasPoweredOn: + /* awake */ + SDL_PrivateExpose(); + break; + } +} + +void QZ_RegisterForSleepNotifications (_THIS) +{ + CFRunLoopSourceRef rls; + IONotificationPortRef thePortRef; + io_object_t notifier; + + power_connection = IORegisterForSystemPower (this, &thePortRef, QZ_SleepNotificationHandler, ¬ifier); + + if (power_connection == 0) + NSLog(@"SDL: QZ_SleepNotificationHandler() IORegisterForSystemPower failed."); + + rls = IONotificationPortGetRunLoopSource (thePortRef); + CFRunLoopAddSource (CFRunLoopGetCurrent(), rls, kCFRunLoopDefaultMode); + CFRelease (rls); +} + + +/* Try to map Quartz mouse buttons to SDL's lingo... */ +static int QZ_OtherMouseButtonToSDL(int button) +{ + switch (button) + { + case 0: + return(SDL_BUTTON_LEFT); /* 1 */ + case 1: + return(SDL_BUTTON_RIGHT); /* 3 */ + case 2: + return(SDL_BUTTON_MIDDLE); /* 2 */ + } + + /* >= 3: skip 4 & 5, since those are the SDL mousewheel buttons. */ + return(button + 3); +} + + +void QZ_PumpEvents (_THIS) +{ + int32_t dx, dy; + + NSDate *distantPast; + NSEvent *event; + NSRect winRect; + NSAutoreleasePool *pool; + + if (!SDL_VideoSurface) + return; /* don't do anything if there's no screen surface. */ + + /* Update activity every five seconds to prevent screensaver. --ryan. */ + if (!allow_screensaver) { + static Uint32 screensaverTicks; + Uint32 nowTicks = SDL_GetTicks(); + if ((nowTicks - screensaverTicks) > 5000) + { + UpdateSystemActivity(UsrActivity); + screensaverTicks = nowTicks; + } + } + + pool = [ [ NSAutoreleasePool alloc ] init ]; + distantPast = [ NSDate distantPast ]; + + winRect = NSMakeRect (0, 0, SDL_VideoSurface->w, SDL_VideoSurface->h); + + /* while grabbed, accumulate all mouse moved events into one SDL mouse event */ + dx = 0; + dy = 0; + + do { + + /* Poll for an event. This will not block */ + event = [ NSApp nextEventMatchingMask:NSAnyEventMask + untilDate:distantPast + inMode: NSDefaultRunLoopMode dequeue:YES ]; + if (event != nil) { + + int button; + unsigned int type; + BOOL isInGameWin; + + #define DO_MOUSE_DOWN(button) do { \ + if ( SDL_GetAppState() & SDL_APPMOUSEFOCUS ) { \ + SDL_PrivateMouseButton (SDL_PRESSED, button, 0, 0); \ + expect_mouse_up |= 1<<button; \ + } \ + [ NSApp sendEvent:event ]; \ + } while(0) + + #define DO_MOUSE_UP(button) do { \ + if ( expect_mouse_up & (1<<button) ) { \ + SDL_PrivateMouseButton (SDL_RELEASED, button, 0, 0); \ + expect_mouse_up &= ~(1<<button); \ + } \ + [ NSApp sendEvent:event ]; \ + } while(0) + + type = [ event type ]; + isInGameWin = QZ_IsMouseInWindow (this); + + QZ_DoModifiers(this, [ event modifierFlags ] ); + + switch (type) { + case NSLeftMouseDown: + if ( SDL_getenv("SDL_HAS3BUTTONMOUSE") ) { + DO_MOUSE_DOWN (SDL_BUTTON_LEFT); + } else { + if ( NSCommandKeyMask & current_mods ) { + last_virtual_button = SDL_BUTTON_RIGHT; + DO_MOUSE_DOWN (SDL_BUTTON_RIGHT); + } + else if ( NSAlternateKeyMask & current_mods ) { + last_virtual_button = SDL_BUTTON_MIDDLE; + DO_MOUSE_DOWN (SDL_BUTTON_MIDDLE); + } + else { + DO_MOUSE_DOWN (SDL_BUTTON_LEFT); + } + } + break; + + case NSLeftMouseUp: + if ( last_virtual_button != 0 ) { + DO_MOUSE_UP (last_virtual_button); + last_virtual_button = 0; + } + else { + DO_MOUSE_UP (SDL_BUTTON_LEFT); + } + break; + + case NSOtherMouseDown: + case NSRightMouseDown: + button = QZ_OtherMouseButtonToSDL([ event buttonNumber ]); + DO_MOUSE_DOWN (button); + break; + + case NSOtherMouseUp: + case NSRightMouseUp: + button = QZ_OtherMouseButtonToSDL([ event buttonNumber ]); + DO_MOUSE_UP (button); + break; + + case NSSystemDefined: + /* + Future: up to 32 "mouse" buttons can be handled. + if ([event subtype] == 7) { + unsigned int buttons; + buttons = [ event data2 ]; + */ + break; + case NSLeftMouseDragged: + case NSRightMouseDragged: + case NSOtherMouseDragged: /* usually middle mouse dragged */ + case NSMouseMoved: + if ( grab_state == QZ_INVISIBLE_GRAB ) { + + /* + If input is grabbed+hidden, the cursor doesn't move, + so we have to call the lowlevel window server + function. This is less accurate but works OK. + */ + int32_t dx1, dy1; + CGGetLastMouseDelta (&dx1, &dy1); + dx += dx1; + dy += dy1; + } + else { + + /* + Get the absolute mouse location. This is not the + mouse location after the currently processed event, + but the *current* mouse location, i.e. after all + pending events. This means that if there are + multiple mouse moved events in the queue, we make + multiple identical calls to SDL_PrivateMouseMotion(), + but that's no problem since the latter only + generates SDL events for nonzero movements. In my + experience on PBG4/10.4.8, this rarely happens anyway. + */ + NSPoint p; + QZ_GetMouseLocation (this, &p); + SDL_PrivateMouseMotion (0, 0, p.x, p.y); + } + + /* + Handle grab input+cursor visible by warping the cursor back + into the game window. This still generates a mouse moved event, + but not as a result of the warp (so it's in the right direction). + */ + if ( grab_state == QZ_VISIBLE_GRAB && !isInGameWin ) { + + NSPoint p; + QZ_GetMouseLocation (this, &p); + + if ( p.x < 0.0 ) + p.x = 0.0; + + if ( p.y < 0.0 ) + p.y = 0.0; + + if ( p.x >= winRect.size.width ) + p.x = winRect.size.width-1; + + if ( p.y >= winRect.size.height ) + p.y = winRect.size.height-1; + + QZ_PrivateWarpCursor (this, p.x, p.y); + } + else + if ( !isInGameWin && (SDL_GetAppState() & SDL_APPMOUSEFOCUS) ) { + + SDL_PrivateAppActive (0, SDL_APPMOUSEFOCUS); + + if (grab_state == QZ_INVISIBLE_GRAB) + /*The cursor has left the window even though it is + disassociated from the mouse (and therefore + shouldn't move): this can happen with Wacom + tablets, and it effectively breaks the grab, since + mouse down events now go to background + applications. The only possibility to avoid this + seems to be talking to the tablet driver + (AppleEvents) to constrain its mapped area to the + window, which may not be worth the effort. For + now, handle the condition more gracefully than + before by reassociating cursor and mouse until the + cursor enters the window again, making it obvious + to the user that the grab is broken.*/ + CGAssociateMouseAndMouseCursorPosition (1); + + QZ_UpdateCursor(this); + } + else + if ( isInGameWin && (SDL_GetAppState() & (SDL_APPMOUSEFOCUS | SDL_APPINPUTFOCUS)) == SDL_APPINPUTFOCUS ) { + + SDL_PrivateAppActive (1, SDL_APPMOUSEFOCUS); + + QZ_UpdateCursor(this); + + if (grab_state == QZ_INVISIBLE_GRAB) { /*see comment above*/ + QZ_PrivateWarpCursor (this, SDL_VideoSurface->w / 2, SDL_VideoSurface->h / 2); + CGAssociateMouseAndMouseCursorPosition (0); + } + } + break; + case NSScrollWheel: + if ( isInGameWin ) { + float dy, dx; + Uint8 button; + dy = [ event deltaY ]; + dx = [ event deltaX ]; + if ( dy > 0.0 ) /* Scroll up */ + button = SDL_BUTTON_WHEELUP; + else if ( dy < 0.0 ) /* Scroll down */ + button = SDL_BUTTON_WHEELDOWN; + else + break; /* Horizontal scroll */ + /* For now, wheel is sent as a quick down+up */ + SDL_PrivateMouseButton (SDL_PRESSED, button, 0, 0); + SDL_PrivateMouseButton (SDL_RELEASED, button, 0, 0); + } + break; + case NSKeyUp: + QZ_DoKey (this, SDL_RELEASED, event); + break; + case NSKeyDown: + QZ_DoKey (this, SDL_PRESSED, event); + break; + case NSFlagsChanged: + break; + case NSAppKitDefined: + [ NSApp sendEvent:event ]; + if ([ event subtype ] == NSApplicationActivatedEventType && (mode_flags & SDL_FULLSCREEN)) { + /* the default handling of this event seems to reset any cursor set by [NSCursor set] (used by SDL_SetCursor() in fullscreen mode) to the default system arrow cursor */ + SDL_Cursor *sdlc = SDL_GetCursor(); + if (sdlc != NULL && sdlc->wm_cursor != NULL) { + [ sdlc->wm_cursor->nscursor set ]; + } + } + break; + /* case NSApplicationDefined: break; */ + /* case NSPeriodic: break; */ + /* case NSCursorUpdate: break; */ + default: + [ NSApp sendEvent:event ]; + } + } + } while (event != nil); + + /* handle accumulated mouse moved events */ + if (dx != 0 || dy != 0) + SDL_PrivateMouseMotion (0, 1, dx, dy); + + [ pool release ]; +} + +void QZ_UpdateMouse (_THIS) +{ + NSPoint p; + QZ_GetMouseLocation (this, &p); + SDL_PrivateAppActive (QZ_IsMouseInWindow (this), SDL_APPMOUSEFOCUS); + SDL_PrivateMouseMotion (0, 0, p.x, p.y); +} diff --git a/3rdparty/SDL/src/video/quartz/SDL_QuartzGL.m b/3rdparty/SDL/src/video/quartz/SDL_QuartzGL.m new file mode 100644 index 0000000..d38dceb --- /dev/null +++ b/3rdparty/SDL/src/video/quartz/SDL_QuartzGL.m @@ -0,0 +1,292 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#include "SDL_QuartzVideo.h" + +/* + * GL_ARB_Multisample is supposed to be available in 10.1, according to Apple: + * + * http://developer.apple.com/graphicsimaging/opengl/extensions.html#GL_ARB_multisample + * + * ...but it isn't in the system headers, according to Sam: + * + * http://lists.libsdl.org/pipermail/sdl-libsdl.org/2003-December/039794.html + * + * These are normally enums and not #defines in the system headers. + * + * --ryan. + */ +#if (MAC_OS_X_VERSION_MAX_ALLOWED < 1020) +#define NSOpenGLPFASampleBuffers ((NSOpenGLPixelFormatAttribute) 55) +#define NSOpenGLPFASamples ((NSOpenGLPixelFormatAttribute) 56) +#endif + +#ifdef __powerpc__ /* we lost this in 10.6, which has no PPC support. */ +@implementation NSOpenGLContext (CGLContextAccess) +- (CGLContextObj) cglContext; +{ + return _contextAuxiliary; +} +@end +CGLContextObj QZ_GetCGLContextObj(NSOpenGLContext *nsctx) +{ + return [nsctx cglContext]; +} +#else +CGLContextObj QZ_GetCGLContextObj(NSOpenGLContext *nsctx) +{ + return (CGLContextObj) [nsctx CGLContextObj]; +} +#endif + + +/* OpenGL helper functions (used internally) */ + +int QZ_SetupOpenGL (_THIS, int bpp, Uint32 flags) { + + NSOpenGLPixelFormatAttribute attr[32]; + NSOpenGLPixelFormat *fmt; + int i = 0; + int colorBits = bpp; + + /* if a GL library hasn't been loaded at this point, load the default. */ + if (!this->gl_config.driver_loaded) { + if (QZ_GL_LoadLibrary(this, NULL) == -1) + return 0; + } + + if ( flags & SDL_FULLSCREEN ) { + + attr[i++] = NSOpenGLPFAFullScreen; + } + /* In windowed mode, the OpenGL pixel depth must match device pixel depth */ + else if ( colorBits != device_bpp ) { + + colorBits = device_bpp; + } + + attr[i++] = NSOpenGLPFAColorSize; + attr[i++] = colorBits; + + attr[i++] = NSOpenGLPFADepthSize; + attr[i++] = this->gl_config.depth_size; + + if ( this->gl_config.double_buffer ) { + attr[i++] = NSOpenGLPFADoubleBuffer; + } + + if ( this->gl_config.stereo ) { + attr[i++] = NSOpenGLPFAStereo; + } + + if ( this->gl_config.stencil_size != 0 ) { + attr[i++] = NSOpenGLPFAStencilSize; + attr[i++] = this->gl_config.stencil_size; + } + + if ( (this->gl_config.accum_red_size + + this->gl_config.accum_green_size + + this->gl_config.accum_blue_size + + this->gl_config.accum_alpha_size) > 0 ) { + attr[i++] = NSOpenGLPFAAccumSize; + attr[i++] = this->gl_config.accum_red_size + this->gl_config.accum_green_size + this->gl_config.accum_blue_size + this->gl_config.accum_alpha_size; + } + + if ( this->gl_config.multisamplebuffers != 0 ) { + attr[i++] = NSOpenGLPFASampleBuffers; + attr[i++] = this->gl_config.multisamplebuffers; + } + + if ( this->gl_config.multisamplesamples != 0 ) { + attr[i++] = NSOpenGLPFASamples; + attr[i++] = this->gl_config.multisamplesamples; + attr[i++] = NSOpenGLPFANoRecovery; + } + + if ( this->gl_config.accelerated > 0 ) { + attr[i++] = NSOpenGLPFAAccelerated; + } + + attr[i++] = NSOpenGLPFAScreenMask; + attr[i++] = CGDisplayIDToOpenGLDisplayMask (display_id); + attr[i] = 0; + + fmt = [ [ NSOpenGLPixelFormat alloc ] initWithAttributes:attr ]; + if (fmt == nil) { + SDL_SetError ("Failed creating OpenGL pixel format"); + return 0; + } + + gl_context = [ [ NSOpenGLContext alloc ] initWithFormat:fmt + shareContext:nil]; + + [ fmt release ]; + + if (gl_context == nil) { + SDL_SetError ("Failed creating OpenGL context"); + return 0; + } + + /* Synchronize QZ_GL_SwapBuffers() to vertical retrace. + * (Apple's documentation is not completely clear about what this setting + * exactly does, IMHO - for a detailed explanation see + * http://lists.apple.com/archives/mac-opengl/2006/Jan/msg00080.html ) + */ + if ( this->gl_config.swap_control >= 0 ) { + GLint value; + value = this->gl_config.swap_control; + [ gl_context setValues: &value forParameter: NSOpenGLCPSwapInterval ]; + } + + /* + * Wisdom from Apple engineer in reference to UT2003's OpenGL performance: + * "You are blowing a couple of the internal OpenGL function caches. This + * appears to be happening in the VAO case. You can tell OpenGL to up + * the cache size by issuing the following calls right after you create + * the OpenGL context. The default cache size is 16." --ryan. + */ + + #ifndef GLI_ARRAY_FUNC_CACHE_MAX + #define GLI_ARRAY_FUNC_CACHE_MAX 284 + #endif + + #ifndef GLI_SUBMIT_FUNC_CACHE_MAX + #define GLI_SUBMIT_FUNC_CACHE_MAX 280 + #endif + + { + GLint cache_max = 64; + CGLContextObj ctx = QZ_GetCGLContextObj(gl_context); + CGLSetParameter (ctx, GLI_SUBMIT_FUNC_CACHE_MAX, &cache_max); + CGLSetParameter (ctx, GLI_ARRAY_FUNC_CACHE_MAX, &cache_max); + } + + /* End Wisdom from Apple Engineer section. --ryan. */ + + return 1; +} + +void QZ_TearDownOpenGL (_THIS) { + + [ NSOpenGLContext clearCurrentContext ]; + [ gl_context clearDrawable ]; + [ gl_context release ]; +} + + +/* SDL OpenGL functions */ +static const char *DEFAULT_OPENGL_LIB_NAME = + "/System/Library/Frameworks/OpenGL.framework/Libraries/libGL.dylib"; + +int QZ_GL_LoadLibrary (_THIS, const char *location) { + if ( gl_context != NULL ) { + SDL_SetError("OpenGL context already created"); + return -1; + } + + if (opengl_library != NULL) + SDL_UnloadObject(opengl_library); + + if (location == NULL) + location = DEFAULT_OPENGL_LIB_NAME; + + opengl_library = SDL_LoadObject(location); + if (opengl_library != NULL) { + this->gl_config.driver_loaded = 1; + return 0; + } + + this->gl_config.driver_loaded = 0; + return -1; +} + +void* QZ_GL_GetProcAddress (_THIS, const char *proc) { + return SDL_LoadFunction(opengl_library, proc); +} + +int QZ_GL_GetAttribute (_THIS, SDL_GLattr attrib, int* value) { + + GLenum attr = 0; + + QZ_GL_MakeCurrent (this); + + switch (attrib) { + case SDL_GL_RED_SIZE: attr = GL_RED_BITS; break; + case SDL_GL_BLUE_SIZE: attr = GL_BLUE_BITS; break; + case SDL_GL_GREEN_SIZE: attr = GL_GREEN_BITS; break; + case SDL_GL_ALPHA_SIZE: attr = GL_ALPHA_BITS; break; + case SDL_GL_DOUBLEBUFFER: attr = GL_DOUBLEBUFFER; break; + case SDL_GL_DEPTH_SIZE: attr = GL_DEPTH_BITS; break; + case SDL_GL_STENCIL_SIZE: attr = GL_STENCIL_BITS; break; + case SDL_GL_ACCUM_RED_SIZE: attr = GL_ACCUM_RED_BITS; break; + case SDL_GL_ACCUM_GREEN_SIZE: attr = GL_ACCUM_GREEN_BITS; break; + case SDL_GL_ACCUM_BLUE_SIZE: attr = GL_ACCUM_BLUE_BITS; break; + case SDL_GL_ACCUM_ALPHA_SIZE: attr = GL_ACCUM_ALPHA_BITS; break; + case SDL_GL_STEREO: attr = GL_STEREO; break; + case SDL_GL_MULTISAMPLEBUFFERS: attr = GL_SAMPLE_BUFFERS_ARB; break; + case SDL_GL_MULTISAMPLESAMPLES: attr = GL_SAMPLES_ARB; break; + case SDL_GL_BUFFER_SIZE: + { + GLint bits = 0; + GLint component; + + /* there doesn't seem to be a single flag in OpenGL for this! */ + glGetIntegerv (GL_RED_BITS, &component); bits += component; + glGetIntegerv (GL_GREEN_BITS,&component); bits += component; + glGetIntegerv (GL_BLUE_BITS, &component); bits += component; + glGetIntegerv (GL_ALPHA_BITS, &component); bits += component; + + *value = bits; + return 0; + } + case SDL_GL_ACCELERATED_VISUAL: + { + GLint val; + /* FIXME: How do we get this information here? + [fmt getValues: &val forAttribute: NSOpenGLPFAAccelerated attr forVirtualScreen: 0]; + */ + val = (this->gl_config.accelerated != 0);; + *value = val; + return 0; + } + case SDL_GL_SWAP_CONTROL: + { + GLint val; + [ gl_context getValues: &val forParameter: NSOpenGLCPSwapInterval ]; + *value = val; + return 0; + } + } + + glGetIntegerv (attr, (GLint *)value); + return 0; +} + +int QZ_GL_MakeCurrent (_THIS) { + [ gl_context makeCurrentContext ]; + return 0; +} + +void QZ_GL_SwapBuffers (_THIS) { + [ gl_context flushBuffer ]; +} diff --git a/3rdparty/SDL/src/video/quartz/SDL_QuartzKeys.h b/3rdparty/SDL/src/video/quartz/SDL_QuartzKeys.h new file mode 100644 index 0000000..82b7859 --- /dev/null +++ b/3rdparty/SDL/src/video/quartz/SDL_QuartzKeys.h @@ -0,0 +1,146 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* These are the Macintosh key scancode constants -- from Inside Macintosh */ + +#define QZ_ESCAPE 0x35 +#define QZ_F1 0x7A +#define QZ_F2 0x78 +#define QZ_F3 0x63 +#define QZ_F4 0x76 +#define QZ_F5 0x60 +#define QZ_F6 0x61 +#define QZ_F7 0x62 +#define QZ_F8 0x64 +#define QZ_F9 0x65 +#define QZ_F10 0x6D +#define QZ_F11 0x67 +#define QZ_F12 0x6F +#define QZ_F13 0x69 +#define QZ_F14 0x6B +#define QZ_F15 0x71 +/* +#define QZ_PRINT 0x69 +#define QZ_SCROLLOCK 0x6B +#define QZ_PAUSE 0x71 +*/ +#define QZ_POWER 0x7F +#define QZ_BACKQUOTE 0x32 +#define QZ_1 0x12 +#define QZ_2 0x13 +#define QZ_3 0x14 +#define QZ_4 0x15 +#define QZ_5 0x17 +#define QZ_6 0x16 +#define QZ_7 0x1A +#define QZ_8 0x1C +#define QZ_9 0x19 +#define QZ_0 0x1D +#define QZ_MINUS 0x1B +#define QZ_EQUALS 0x18 +#define QZ_BACKSPACE 0x33 +#define QZ_INSERT 0x72 +#define QZ_HOME 0x73 +#define QZ_PAGEUP 0x74 +#define QZ_NUMLOCK 0x47 +#define QZ_KP_EQUALS 0x51 +#define QZ_KP_DIVIDE 0x4B +#define QZ_KP_MULTIPLY 0x43 +#define QZ_TAB 0x30 +#define QZ_q 0x0C +#define QZ_w 0x0D +#define QZ_e 0x0E +#define QZ_r 0x0F +#define QZ_t 0x11 +#define QZ_y 0x10 +#define QZ_u 0x20 +#define QZ_i 0x22 +#define QZ_o 0x1F +#define QZ_p 0x23 +#define QZ_LEFTBRACKET 0x21 +#define QZ_RIGHTBRACKET 0x1E +#define QZ_BACKSLASH 0x2A +#define QZ_DELETE 0x75 +#define QZ_END 0x77 +#define QZ_PAGEDOWN 0x79 +#define QZ_KP7 0x59 +#define QZ_KP8 0x5B +#define QZ_KP9 0x5C +#define QZ_KP_MINUS 0x4E +#define QZ_CAPSLOCK 0x39 +#define QZ_a 0x00 +#define QZ_s 0x01 +#define QZ_d 0x02 +#define QZ_f 0x03 +#define QZ_g 0x05 +#define QZ_h 0x04 +#define QZ_j 0x26 +#define QZ_k 0x28 +#define QZ_l 0x25 +#define QZ_SEMICOLON 0x29 +#define QZ_QUOTE 0x27 +#define QZ_RETURN 0x24 +#define QZ_KP4 0x56 +#define QZ_KP5 0x57 +#define QZ_KP6 0x58 +#define QZ_KP_PLUS 0x45 +#define QZ_LSHIFT 0x38 +#define QZ_z 0x06 +#define QZ_x 0x07 +#define QZ_c 0x08 +#define QZ_v 0x09 +#define QZ_b 0x0B +#define QZ_n 0x2D +#define QZ_m 0x2E +#define QZ_COMMA 0x2B +#define QZ_PERIOD 0x2F +#define QZ_SLASH 0x2C +#if 1 /* Panther now defines right side keys */ +#define QZ_RSHIFT 0x3C +#endif +#define QZ_UP 0x7E +#define QZ_KP1 0x53 +#define QZ_KP2 0x54 +#define QZ_KP3 0x55 +#define QZ_KP_ENTER 0x4C +#define QZ_LCTRL 0x3B +#define QZ_LALT 0x3A +#define QZ_LMETA 0x37 +#define QZ_SPACE 0x31 +#if 1 /* Panther now defines right side keys */ +#define QZ_RMETA 0x36 +#define QZ_RALT 0x3D +#define QZ_RCTRL 0x3E +#endif +#define QZ_LEFT 0x7B +#define QZ_DOWN 0x7D +#define QZ_RIGHT 0x7C +#define QZ_KP0 0x52 +#define QZ_KP_PERIOD 0x41 + +/* Wierd, these keys are on my iBook under Mac OS X */ +#define QZ_IBOOK_ENTER 0x34 +#define QZ_IBOOK_LEFT 0x3B +#define QZ_IBOOK_RIGHT 0x3C +#define QZ_IBOOK_DOWN 0x3D +#define QZ_IBOOK_UP 0x3E diff --git a/3rdparty/SDL/src/video/quartz/SDL_QuartzVideo.h b/3rdparty/SDL/src/video/quartz/SDL_QuartzVideo.h new file mode 100644 index 0000000..7506e0c --- /dev/null +++ b/3rdparty/SDL/src/video/quartz/SDL_QuartzVideo.h @@ -0,0 +1,229 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* + @file SDL_QuartzVideo.h + @author Darrell Walisser, Max Horn, et al. + + @abstract SDL video driver for Mac OS X. + + @discussion + + TODO + - Hardware Cursor support with NSCursor instead of Carbon + - Keyboard repeat/mouse speed adjust (if needed) + - Multiple monitor support (currently only main display) + - Accelerated blitting support + - Fix white OpenGL window on minimize (fixed) (update: broken again on 10.2) + - Find out what events should be sent/ignored if window is minimized + - Find a way to deal with external resolution/depth switch while app is running + - Check accuracy of QZ_SetGamma() + Problems: + - OGL not working in full screen with software renderer + - SetColors sets palette correctly but clears framebuffer + - Crash in CG after several mode switches (I think this has been fixed) + - Retained windows don't draw their title bar quite right (OS Bug) (not using retained windows) + - Cursor in 8 bit modes is screwy (might just be Radeon PCI bug) (update: not just Radeon) + - Warping cursor delays mouse events for a fraction of a second, + there is a hack around this that helps a bit +*/ + +/* Needs to be first, so QuickTime.h doesn't include glext.h (10.4) */ +#include "SDL_opengl.h" + +#include <Cocoa/Cocoa.h> +#include <Carbon/Carbon.h> +#include <OpenGL/OpenGL.h> /* For CGL functions and types */ +#include <IOKit/IOKitLib.h> /* For powersave handling */ +#include <pthread.h> + +#include "SDL_thread.h" +#include "SDL_video.h" +#include "SDL_error.h" +#include "SDL_timer.h" +#include "SDL_loadso.h" +#include "SDL_syswm.h" +#include "../SDL_sysvideo.h" +#include "../SDL_pixels_c.h" +#include "../../events/SDL_events_c.h" + + +#ifdef __powerpc__ +/* + This is a workaround to directly access NSOpenGLContext's CGL context + We need this to check for errors NSOpenGLContext doesn't support + Please note this is only used on PowerPC (Intel Macs are guaranteed to + have a better API for this, since it showed up in Mac OS X 10.3). +*/ +@interface NSOpenGLContext (CGLContextAccess) +- (CGLContextObj) cglContext; +@end +#endif + +/* use this to get the CGLContext; it handles Cocoa interface changes. */ +CGLContextObj QZ_GetCGLContextObj(NSOpenGLContext *nsctx); + + +/* Main driver structure to store required state information */ +typedef struct SDL_PrivateVideoData { + BOOL use_new_mode_apis; /* 1 == >= 10.6 APIs available */ + BOOL allow_screensaver; /* 0 == disable screensaver */ + CGDirectDisplayID display; /* 0 == main display (only support single display) */ + const void *mode; /* current mode of the display */ + const void *save_mode; /* original mode of the display */ + CGDirectPaletteRef palette; /* palette of an 8-bit display */ + NSOpenGLContext *gl_context; /* OpenGL rendering context */ + NSGraphicsContext *nsgfx_context; /* Cocoa graphics context */ + Uint32 width, height, bpp; /* frequently used data about the display */ + Uint32 flags; /* flags for current mode, for teardown purposes */ + Uint32 video_set; /* boolean; indicates if video was set correctly */ + Uint32 warp_flag; /* boolean; notify to event loop that a warp just occured */ + Uint32 warp_ticks; /* timestamp when the warp occured */ + NSWindow *window; /* Cocoa window to implement the SDL window */ + NSView *view; /* the window's view; draw 2D and OpenGL into this view */ + CGContextRef cg_context; /* CoreGraphics rendering context */ + SDL_Surface *resize_icon; /* icon for the resize badge, we have to draw it by hand */ + SDL_GrabMode current_grab_mode; /* default value is SDL_GRAB_OFF */ + SDL_Rect **client_mode_list; /* resolution list to pass back to client */ + SDLKey keymap[256]; /* Mac OS X to SDL key mapping */ + Uint32 current_mods; /* current keyboard modifiers, to track modifier state */ + NSText *field_edit; /* a field editor for keyboard composition processing */ + Uint32 last_virtual_button;/* last virtual mouse button pressed */ + io_connect_t power_connection; /* used with IOKit to detect wake from sleep */ + Uint8 expect_mouse_up; /* used to determine when to send mouse up events */ + Uint8 grab_state; /* used to manage grab behavior */ + NSPoint cursor_loc; /* saved cursor coords, for activate/deactivate when grabbed */ + BOOL cursor_should_be_visible; /* tells if cursor is supposed to be visible (SDL_ShowCursor) */ + BOOL cursor_visible; /* tells if cursor is *actually* visible or not */ + Uint8* sw_buffers[2]; /* pointers to the two software buffers for double-buffer emulation */ + SDL_Thread *thread; /* thread for async updates to the screen */ + SDL_sem *sem1, *sem2; /* synchronization for async screen updates */ + Uint8 *current_buffer; /* the buffer being copied to the screen */ + BOOL quit_thread; /* used to quit the async blitting thread */ + SInt32 system_version; /* used to dis-/enable workarounds depending on the system version */ + + void *opengl_library; /* dynamically loaded OpenGL library. */ +} SDL_PrivateVideoData; + +#define _THIS SDL_VideoDevice *this +#define display_id (this->hidden->display) +#define mode (this->hidden->mode) +#define save_mode (this->hidden->save_mode) +#define use_new_mode_apis (this->hidden->use_new_mode_apis) +#define allow_screensaver (this->hidden->allow_screensaver) +#define palette (this->hidden->palette) +#define gl_context (this->hidden->gl_context) +#define nsgfx_context (this->hidden->nsgfx_context) +#define device_width (this->hidden->width) +#define device_height (this->hidden->height) +#define device_bpp (this->hidden->bpp) +#define mode_flags (this->hidden->flags) +#define qz_window (this->hidden->window) +#define window_view (this->hidden->view) +#define cg_context (this->hidden->cg_context) +#define video_set (this->hidden->video_set) +#define warp_ticks (this->hidden->warp_ticks) +#define warp_flag (this->hidden->warp_flag) +#define resize_icon (this->hidden->resize_icon) +#define current_grab_mode (this->hidden->current_grab_mode) +#define client_mode_list (this->hidden->client_mode_list) +#define keymap (this->hidden->keymap) +#define current_mods (this->hidden->current_mods) +#define field_edit (this->hidden->field_edit) +#define last_virtual_button (this->hidden->last_virtual_button) +#define power_connection (this->hidden->power_connection) +#define expect_mouse_up (this->hidden->expect_mouse_up) +#define grab_state (this->hidden->grab_state) +#define cursor_loc (this->hidden->cursor_loc) +#define cursor_should_be_visible (this->hidden->cursor_should_be_visible) +#define cursor_visible (this->hidden->cursor_visible) +#define sw_buffers (this->hidden->sw_buffers) +#define sw_contexts (this->hidden->sw_contexts) +#define thread (this->hidden->thread) +#define sem1 (this->hidden->sem1) +#define sem2 (this->hidden->sem2) +#define current_buffer (this->hidden->current_buffer) +#define quit_thread (this->hidden->quit_thread) +#define system_version (this->hidden->system_version) +#define opengl_library (this->hidden->opengl_library) + +/* grab states - the input is in one of these states */ +enum { + QZ_UNGRABBED = 0, + QZ_VISIBLE_GRAB, + QZ_INVISIBLE_GRAB +}; + +/* grab actions - these can change the grabbed state */ +enum { + QZ_ENABLE_GRAB = 0, + QZ_DISABLE_GRAB, + QZ_HIDECURSOR, + QZ_SHOWCURSOR +}; + +/* Gamma Functions */ +int QZ_SetGamma (_THIS, float red, float green, float blue); +int QZ_GetGamma (_THIS, float *red, float *green, float *blue); +int QZ_SetGammaRamp (_THIS, Uint16 *ramp); +int QZ_GetGammaRamp (_THIS, Uint16 *ramp); + +/* OpenGL functions */ +int QZ_SetupOpenGL (_THIS, int bpp, Uint32 flags); +void QZ_TearDownOpenGL (_THIS); +void* QZ_GL_GetProcAddress (_THIS, const char *proc); +int QZ_GL_GetAttribute (_THIS, SDL_GLattr attrib, int* value); +int QZ_GL_MakeCurrent (_THIS); +void QZ_GL_SwapBuffers (_THIS); +int QZ_GL_LoadLibrary (_THIS, const char *location); + +/* Cursor and Mouse functions */ +void QZ_FreeWMCursor (_THIS, WMcursor *cursor); +WMcursor* QZ_CreateWMCursor (_THIS, Uint8 *data, Uint8 *mask, + int w, int h, int hot_x, int hot_y); +int QZ_ShowWMCursor (_THIS, WMcursor *cursor); +void QZ_WarpWMCursor (_THIS, Uint16 x, Uint16 y); +void QZ_MoveWMCursor (_THIS, int x, int y); +void QZ_CheckMouseMode (_THIS); +void QZ_UpdateMouse (_THIS); + +/* Event functions */ +void QZ_InitOSKeymap (_THIS); +void QZ_PumpEvents (_THIS); + +/* Window Manager functions */ +void QZ_SetCaption (_THIS, const char *title, const char *icon); +void QZ_SetIcon (_THIS, SDL_Surface *icon, Uint8 *mask); +int QZ_IconifyWindow (_THIS); +SDL_GrabMode QZ_GrabInput (_THIS, SDL_GrabMode grab_mode); +/*int QZ_GetWMInfo (_THIS, SDL_SysWMinfo *info);*/ + +/* Private functions (used internally) */ +void QZ_PrivateWarpCursor (_THIS, int x, int y); +void QZ_ChangeGrabState (_THIS, int action); +void QZ_RegisterForSleepNotifications (_THIS); +void QZ_PrivateGlobalToLocal (_THIS, NSPoint *p); +void QZ_PrivateCocoaToSDL (_THIS, NSPoint *p); +BOOL QZ_IsMouseInWindow (_THIS); +void QZ_DoActivate (_THIS); +void QZ_DoDeactivate (_THIS); diff --git a/3rdparty/SDL/src/video/quartz/SDL_QuartzVideo.m b/3rdparty/SDL/src/video/quartz/SDL_QuartzVideo.m new file mode 100644 index 0000000..fa04e9d --- /dev/null +++ b/3rdparty/SDL/src/video/quartz/SDL_QuartzVideo.m @@ -0,0 +1,1689 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#include "SDL_QuartzVideo.h" +#include "SDL_QuartzWindow.h" + +/* These APIs aren't just deprecated; they're gone from the headers in the + 10.7 SDK. If we're using a >= 10.7 SDK, but targeting < 10.7, then we + force these function declarations. */ +#if ((MAC_OS_X_VERSION_MIN_REQUIRED < 1070) && (MAC_OS_X_VERSION_MAX_ALLOWED >= 1070)) +CG_EXTERN void *CGDisplayBaseAddress(CGDirectDisplayID display) + CG_AVAILABLE_BUT_DEPRECATED(__MAC_10_0, __MAC_10_6, + __IPHONE_NA, __IPHONE_NA); +CG_EXTERN size_t CGDisplayBytesPerRow(CGDirectDisplayID display) + CG_AVAILABLE_BUT_DEPRECATED(__MAC_10_0, __MAC_10_6, + __IPHONE_NA, __IPHONE_NA); +#endif + + +static inline BOOL IS_LION_OR_LATER(_THIS) +{ + return (system_version >= 0x1070); +} + +static inline BOOL IS_SNOW_LEOPARD_OR_LATER(_THIS) +{ + return (system_version >= 0x1060); +} + +#if (MAC_OS_X_VERSION_MAX_ALLOWED < 1060) && !defined(__LP64__) /* Fixed in Snow Leopard */ +/* + Add methods to get at private members of NSScreen. + Since there is a bug in Apple's screen switching code + that does not update this variable when switching + to fullscreen, we'll set it manually (but only for the + main screen). +*/ +@interface NSScreen (NSScreenAccess) +- (void) setFrame:(NSRect)frame; +@end + +@implementation NSScreen (NSScreenAccess) +- (void) setFrame:(NSRect)frame; +{ + _frame = frame; +} +@end +static inline void QZ_SetFrame(_THIS, NSScreen *nsscreen, NSRect frame) +{ + if (!IS_SNOW_LEOPARD_OR_LATER(this)) { + [nsscreen setFrame:frame]; + } +} +#else +static inline void QZ_SetFrame(_THIS, NSScreen *nsscreen, NSRect frame) +{ +} +#endif + +@interface SDLTranslatorResponder : NSTextView +{ +} +- (void) doCommandBySelector:(SEL)myselector; +@end + +@implementation SDLTranslatorResponder +- (void) doCommandBySelector:(SEL) myselector {} +@end + +/* absent in 10.3.9. */ +CG_EXTERN CGImageRef CGBitmapContextCreateImage (CGContextRef); + +/* Bootstrap functions */ +static int QZ_Available (); +static SDL_VideoDevice* QZ_CreateDevice (int device_index); +static void QZ_DeleteDevice (SDL_VideoDevice *device); + +/* Initialization, Query, Setup, and Redrawing functions */ +static int QZ_VideoInit (_THIS, SDL_PixelFormat *video_format); + +static SDL_Rect** QZ_ListModes (_THIS, SDL_PixelFormat *format, + Uint32 flags); +static void QZ_UnsetVideoMode (_THIS, BOOL to_desktop, BOOL save_gl); + +static SDL_Surface* QZ_SetVideoMode (_THIS, SDL_Surface *current, + int width, int height, int bpp, + Uint32 flags); +static int QZ_ToggleFullScreen (_THIS, int on); +static int QZ_SetColors (_THIS, int first_color, + int num_colors, SDL_Color *colors); + +#if (MAC_OS_X_VERSION_MIN_REQUIRED < 1070) +static int QZ_LockDoubleBuffer (_THIS, SDL_Surface *surface); +static void QZ_UnlockDoubleBuffer (_THIS, SDL_Surface *surface); +static int QZ_ThreadFlip (_THIS); +static int QZ_FlipDoubleBuffer (_THIS, SDL_Surface *surface); +static void QZ_DoubleBufferUpdate (_THIS, int num_rects, SDL_Rect *rects); +static void QZ_DirectUpdate (_THIS, int num_rects, SDL_Rect *rects); +#endif + +static void QZ_UpdateRects (_THIS, int num_rects, SDL_Rect *rects); +static void QZ_VideoQuit (_THIS); + +static int QZ_LockHWSurface(_THIS, SDL_Surface *surface); +static void QZ_UnlockHWSurface(_THIS, SDL_Surface *surface); +static int QZ_AllocHWSurface(_THIS, SDL_Surface *surface); +static void QZ_FreeHWSurface (_THIS, SDL_Surface *surface); + +/* Bootstrap binding, enables entry point into the driver */ +VideoBootStrap QZ_bootstrap = { + "Quartz", "Mac OS X CoreGraphics", QZ_Available, QZ_CreateDevice +}; + +/* Disable compiler warnings we can't avoid. */ +#if (defined(__GNUC__) && (__GNUC__ >= 4)) +# if (MAC_OS_X_VERSION_MAX_ALLOWED <= 1070) +# pragma GCC diagnostic ignored "-Wdeprecated-declarations" +# endif +#endif + +static void QZ_ReleaseDisplayMode(_THIS, const void *moderef) +{ + /* we only own these references in the 10.6+ API. */ +#if (MAC_OS_X_VERSION_MAX_ALLOWED >= 1060) + if (use_new_mode_apis) { + CGDisplayModeRelease((CGDisplayModeRef) moderef); + } +#endif +} + +static void QZ_ReleaseDisplayModeList(_THIS, CFArrayRef mode_list) +{ + /* we only own these references in the 10.6+ API. */ +#if (MAC_OS_X_VERSION_MAX_ALLOWED >= 1060) + if (use_new_mode_apis) { + CFRelease(mode_list); + } +#endif +} + + +/* Bootstrap functions */ +static int QZ_Available () +{ + return 1; +} + +static SDL_VideoDevice* QZ_CreateDevice (int device_index) +{ +#pragma unused (device_index) + + SDL_VideoDevice *device; + SDL_PrivateVideoData *hidden; + + device = (SDL_VideoDevice*) SDL_malloc (sizeof (*device) ); + hidden = (SDL_PrivateVideoData*) SDL_malloc (sizeof (*hidden) ); + + if (device == NULL || hidden == NULL) + SDL_OutOfMemory (); + + SDL_memset (device, 0, sizeof (*device) ); + SDL_memset (hidden, 0, sizeof (*hidden) ); + + device->hidden = hidden; + + device->VideoInit = QZ_VideoInit; + device->ListModes = QZ_ListModes; + device->SetVideoMode = QZ_SetVideoMode; + device->ToggleFullScreen = QZ_ToggleFullScreen; + device->UpdateMouse = QZ_UpdateMouse; + device->SetColors = QZ_SetColors; + /* device->UpdateRects = QZ_UpdateRects; this is determined by SetVideoMode() */ + device->VideoQuit = QZ_VideoQuit; + + device->LockHWSurface = QZ_LockHWSurface; + device->UnlockHWSurface = QZ_UnlockHWSurface; + device->AllocHWSurface = QZ_AllocHWSurface; + device->FreeHWSurface = QZ_FreeHWSurface; + + device->SetGamma = QZ_SetGamma; + device->GetGamma = QZ_GetGamma; + device->SetGammaRamp = QZ_SetGammaRamp; + device->GetGammaRamp = QZ_GetGammaRamp; + + device->GL_GetProcAddress = QZ_GL_GetProcAddress; + device->GL_GetAttribute = QZ_GL_GetAttribute; + device->GL_MakeCurrent = QZ_GL_MakeCurrent; + device->GL_SwapBuffers = QZ_GL_SwapBuffers; + device->GL_LoadLibrary = QZ_GL_LoadLibrary; + + device->FreeWMCursor = QZ_FreeWMCursor; + device->CreateWMCursor = QZ_CreateWMCursor; + device->ShowWMCursor = QZ_ShowWMCursor; + device->WarpWMCursor = QZ_WarpWMCursor; + device->MoveWMCursor = QZ_MoveWMCursor; + device->CheckMouseMode = QZ_CheckMouseMode; + device->InitOSKeymap = QZ_InitOSKeymap; + device->PumpEvents = QZ_PumpEvents; + + device->SetCaption = QZ_SetCaption; + device->SetIcon = QZ_SetIcon; + device->IconifyWindow = QZ_IconifyWindow; + /*device->GetWMInfo = QZ_GetWMInfo;*/ + device->GrabInput = QZ_GrabInput; + + /* + * This is a big hassle, needing QuickDraw and QuickTime on older + * systems, and god knows what on 10.6, so we immediately fail here, + * which causes SDL to make an RGB surface and manage the YUV overlay + * in software. Sorry. Use SDL 1.3 if you want YUV rendering in a pixel + * shader. :) + */ + /*device->CreateYUVOverlay = QZ_CreateYUVOverlay;*/ + + device->free = QZ_DeleteDevice; + + return device; +} + +static void QZ_DeleteDevice (SDL_VideoDevice *device) +{ + _THIS = device; + QZ_ReleaseDisplayMode(this, save_mode); + QZ_ReleaseDisplayMode(this, mode); + SDL_free (device->hidden); + SDL_free (device); +} + +static void QZ_GetModeInfo(_THIS, const void *_mode, Uint32 *w, Uint32 *h, Uint32 *bpp) +{ + *w = *h = *bpp = 0; + if (_mode == NULL) { + return; + } + +#if (MAC_OS_X_VERSION_MAX_ALLOWED >= 1060) + if (use_new_mode_apis) { + CGDisplayModeRef vidmode = (CGDisplayModeRef) _mode; + CFStringRef fmt = CGDisplayModeCopyPixelEncoding(vidmode); + + *w = (Uint32) CGDisplayModeGetWidth(vidmode); + *h = (Uint32) CGDisplayModeGetHeight(vidmode); + + /* we only care about the 32-bit modes... */ + if (CFStringCompare(fmt, CFSTR(IO32BitDirectPixels), + kCFCompareCaseInsensitive) == kCFCompareEqualTo) { + *bpp = 32; + } + + CFRelease(fmt); + } +#endif + +#if (MAC_OS_X_VERSION_MIN_REQUIRED < 1060) + if (!use_new_mode_apis) { + CFDictionaryRef vidmode = (CFDictionaryRef) _mode; + CFNumberGetValue ( + CFDictionaryGetValue (vidmode, kCGDisplayBitsPerPixel), + kCFNumberSInt32Type, bpp); + + CFNumberGetValue ( + CFDictionaryGetValue (vidmode, kCGDisplayWidth), + kCFNumberSInt32Type, w); + + CFNumberGetValue ( + CFDictionaryGetValue (vidmode, kCGDisplayHeight), + kCFNumberSInt32Type, h); + } +#endif + + /* we only care about the 32-bit modes... */ + if (*bpp != 32) { + *bpp = 0; + } +} + +static int QZ_VideoInit (_THIS, SDL_PixelFormat *video_format) +{ + NSRect r = NSMakeRect(0.0, 0.0, 0.0, 0.0); + const char *env = NULL; + + if ( Gestalt(gestaltSystemVersion, &system_version) != noErr ) + system_version = 0; + + use_new_mode_apis = NO; + +#if (MAC_OS_X_VERSION_MAX_ALLOWED >= 1060) + use_new_mode_apis = IS_SNOW_LEOPARD_OR_LATER(this); +#endif + + /* Initialize the video settings; this data persists between mode switches */ + display_id = kCGDirectMainDisplay; + +#if 0 /* The mouse event code needs to take this into account... */ + env = getenv("SDL_VIDEO_FULLSCREEN_DISPLAY"); + if ( env ) { + int monitor = SDL_atoi(env); + CGDirectDisplayID activeDspys [3]; + CGDisplayCount dspyCnt; + CGGetActiveDisplayList (3, activeDspys, &dspyCnt); + if ( monitor >= 0 && monitor < dspyCnt ) { + display_id = activeDspys[monitor]; + } + } +#endif + +#if (MAC_OS_X_VERSION_MAX_ALLOWED >= 1060) + if (use_new_mode_apis) { + save_mode = CGDisplayCopyDisplayMode(display_id); + } +#endif + +#if (MAC_OS_X_VERSION_MIN_REQUIRED < 1060) + if (!use_new_mode_apis) { + save_mode = CGDisplayCurrentMode(display_id); + } +#endif + +#if (MAC_OS_X_VERSION_MIN_REQUIRED < 1070) + if (!IS_LION_OR_LATER(this)) { + palette = CGPaletteCreateDefaultColorPalette(); + } +#endif + + if (save_mode == NULL) { + SDL_SetError("Couldn't figure out current display mode."); + return -1; + } + + /* Allow environment override of screensaver disable. */ + env = SDL_getenv("SDL_VIDEO_ALLOW_SCREENSAVER"); + if ( env ) { + allow_screensaver = SDL_atoi(env); + } else { +#ifdef SDL_VIDEO_DISABLE_SCREENSAVER + allow_screensaver = 0; +#else + allow_screensaver = 1; +#endif + } + + /* Gather some information that is useful to know about the display */ + QZ_GetModeInfo(this, save_mode, &device_width, &device_height, &device_bpp); + if (device_bpp == 0) { + QZ_ReleaseDisplayMode(this, save_mode); + save_mode = NULL; + SDL_SetError("Unsupported display mode"); + return -1; + } + + /* Determine the current screen size */ + this->info.current_w = device_width; + this->info.current_h = device_height; + + /* Determine the default screen depth */ + video_format->BitsPerPixel = device_bpp; + + /* Set misc globals */ + current_grab_mode = SDL_GRAB_OFF; + cursor_should_be_visible = YES; + cursor_visible = YES; + current_mods = 0; + field_edit = [[SDLTranslatorResponder alloc] initWithFrame:r]; + + /* register for sleep notifications so wake from sleep generates SDL_VIDEOEXPOSE */ + QZ_RegisterForSleepNotifications (this); + + /* Fill in some window manager capabilities */ + this->info.wm_available = 1; + + return 0; +} + +static SDL_Rect** QZ_ListModes (_THIS, SDL_PixelFormat *format, Uint32 flags) +{ + CFArrayRef mode_list = NULL; /* list of available fullscreen modes */ + CFIndex num_modes; + CFIndex i; + + int list_size = 0; + + /* Any windowed mode is acceptable */ + if ( (flags & SDL_FULLSCREEN) == 0 ) + return (SDL_Rect**)-1; + + /* Free memory from previous call, if any */ + if ( client_mode_list != NULL ) { + int i; + + for (i = 0; client_mode_list[i] != NULL; i++) + SDL_free (client_mode_list[i]); + + SDL_free (client_mode_list); + client_mode_list = NULL; + } + +#if (MAC_OS_X_VERSION_MAX_ALLOWED >= 1060) + if (use_new_mode_apis) { + mode_list = CGDisplayCopyAllDisplayModes(display_id, NULL); + } +#endif + +#if (MAC_OS_X_VERSION_MIN_REQUIRED < 1060) + if (!use_new_mode_apis) { + mode_list = CGDisplayAvailableModes(display_id); + } +#endif + + num_modes = CFArrayGetCount (mode_list); + + /* Build list of modes with the requested bpp */ + for (i = 0; i < num_modes; i++) { + Uint32 width, height, bpp; + const void *onemode = CFArrayGetValueAtIndex(mode_list, i); + + QZ_GetModeInfo(this, onemode, &width, &height, &bpp); + + if (bpp && (bpp == format->BitsPerPixel)) { + int hasMode = SDL_FALSE; + int i; + + /* Check if mode is already in the list */ + for (i = 0; i < list_size; i++) { + if (client_mode_list[i]->w == width && + client_mode_list[i]->h == height) { + hasMode = SDL_TRUE; + break; + } + } + + /* Grow the list and add mode to the list */ + if ( ! hasMode ) { + SDL_Rect *rect; + + list_size++; + + if (client_mode_list == NULL) + client_mode_list = (SDL_Rect**) + SDL_malloc (sizeof(*client_mode_list) * (list_size+1) ); + else { + /* !!! FIXME: this leaks memory if SDL_realloc() fails! */ + client_mode_list = (SDL_Rect**) + SDL_realloc (client_mode_list, sizeof(*client_mode_list) * (list_size+1)); + } + + rect = (SDL_Rect*) SDL_malloc (sizeof(**client_mode_list)); + + if (client_mode_list == NULL || rect == NULL) { + QZ_ReleaseDisplayModeList(this, mode_list); + SDL_OutOfMemory (); + return NULL; + } + + rect->x = rect->y = 0; + rect->w = width; + rect->h = height; + + client_mode_list[list_size-1] = rect; + client_mode_list[list_size] = NULL; + } + } + } + + QZ_ReleaseDisplayModeList(this, mode_list); + + /* Sort list largest to smallest (by area) */ + { + int i, j; + for (i = 0; i < list_size; i++) { + for (j = 0; j < list_size-1; j++) { + + int area1, area2; + area1 = client_mode_list[j]->w * client_mode_list[j]->h; + area2 = client_mode_list[j+1]->w * client_mode_list[j+1]->h; + + if (area1 < area2) { + SDL_Rect *tmp = client_mode_list[j]; + client_mode_list[j] = client_mode_list[j+1]; + client_mode_list[j+1] = tmp; + } + } + } + } + + return client_mode_list; +} + +static SDL_bool QZ_WindowPosition(_THIS, int *x, int *y) +{ + const char *window = getenv("SDL_VIDEO_WINDOW_POS"); + if ( window ) { + if ( sscanf(window, "%d,%d", x, y) == 2 ) { + return SDL_TRUE; + } + } + return SDL_FALSE; +} + +static CGError QZ_SetDisplayMode(_THIS, const void *vidmode) +{ +#if (MAC_OS_X_VERSION_MAX_ALLOWED >= 1060) + if (use_new_mode_apis) { + return CGDisplaySetDisplayMode(display_id, (CGDisplayModeRef) vidmode, NULL); + } +#endif + +#if (MAC_OS_X_VERSION_MIN_REQUIRED < 1060) + if (!use_new_mode_apis) { + return CGDisplaySwitchToMode(display_id, (CFDictionaryRef) vidmode); + } +#endif + + return kCGErrorFailure; +} + +static inline CGError QZ_RestoreDisplayMode(_THIS) +{ + return QZ_SetDisplayMode(this, save_mode); +} + +static void QZ_UnsetVideoMode (_THIS, BOOL to_desktop, BOOL save_gl) +{ + /* Reset values that may change between switches */ + this->info.blit_fill = 0; + this->FillHWRect = NULL; + this->UpdateRects = NULL; + this->LockHWSurface = NULL; + this->UnlockHWSurface = NULL; + + if (cg_context) { + CGContextFlush (cg_context); + CGContextRelease (cg_context); + cg_context = nil; + } + + /* Release fullscreen resources */ + if ( mode_flags & SDL_FULLSCREEN ) { + + NSRect screen_rect; + + /* Release double buffer stuff */ +#if (MAC_OS_X_VERSION_MIN_REQUIRED < 1070) + if ( !IS_LION_OR_LATER(this) && (mode_flags & SDL_DOUBLEBUF) ) { + quit_thread = YES; + SDL_SemPost (sem1); + SDL_WaitThread (thread, NULL); + SDL_DestroySemaphore (sem1); + SDL_DestroySemaphore (sem2); + SDL_free (sw_buffers[0]); + } +#endif + + /* If we still have a valid window, close it. */ + if ( qz_window ) { + NSCAssert([ qz_window delegate ] == nil, @"full screen window shouldn't have a delegate"); /* if that should ever change, we'd have to release it here */ + [ qz_window close ]; /* includes release because [qz_window isReleasedWhenClosed] */ + qz_window = nil; + window_view = nil; + } + /* + Release the OpenGL context + Do this first to avoid trash on the display before fade + */ + if ( mode_flags & SDL_OPENGL ) { + if (!save_gl) { + QZ_TearDownOpenGL (this); + } + + #ifdef __powerpc__ /* we only use this for pre-10.3 compatibility. */ + CGLSetFullScreen (NULL); + #endif + } + if (to_desktop) { + /* !!! FIXME: keep an eye on this. + * This API is officially unavailable for 64-bit binaries. + * It happens to work, as of 10.7, but we're going to see if + * we can just simply do without it on newer OSes... + */ + #if (MAC_OS_X_VERSION_MIN_REQUIRED < 1070) && !defined(__LP64__) + if ( !IS_LION_OR_LATER(this) ) { + ShowMenuBar (); + } + #endif + + /* Restore original screen resolution/bpp */ + QZ_RestoreDisplayMode (this); + CGReleaseAllDisplays (); + /* + Reset the main screen's rectangle + See comment in QZ_SetVideoFullscreen for why we do this + */ + screen_rect = NSMakeRect(0,0,device_width,device_height); + QZ_SetFrame(this, [ NSScreen mainScreen ], screen_rect); + } + } + /* Release window mode resources */ + else { + id delegate = [ qz_window delegate ]; + [ qz_window close ]; /* includes release because [qz_window isReleasedWhenClosed] */ + if (delegate != nil) [ delegate release ]; + qz_window = nil; + window_view = nil; + + /* Release the OpenGL context */ + if ( mode_flags & SDL_OPENGL ) { + if (!save_gl) { + QZ_TearDownOpenGL (this); + } + } + } + + /* Signal successful teardown */ + video_set = SDL_FALSE; +} + +static const void *QZ_BestMode(_THIS, const int bpp, const int w, const int h) +{ + const void *best = NULL; + + if (bpp == 0) { + return NULL; + } + +#if (MAC_OS_X_VERSION_MAX_ALLOWED >= 1060) + if (use_new_mode_apis) { + /* apparently, we have to roll our own now. :/ */ + CFArrayRef mode_list = CGDisplayCopyAllDisplayModes(display_id, NULL); + if (mode_list != NULL) { + const CFIndex num_modes = CFArrayGetCount(mode_list); + CFIndex i; + for (i = 0; i < num_modes; i++) { + const void *vidmode = CFArrayGetValueAtIndex(mode_list, i); + Uint32 thisw, thish, thisbpp; + QZ_GetModeInfo(this, vidmode, &thisw, &thish, &thisbpp); + + /* We only care about exact matches, apparently. */ + if ((thisbpp == bpp) && (thisw == w) && (thish == h)) { + best = vidmode; + break; /* got it! */ + } + } + CGDisplayModeRetain((CGDisplayModeRef) best); /* NULL is ok */ + CFRelease(mode_list); + } + } +#endif + +#if (MAC_OS_X_VERSION_MIN_REQUIRED < 1060) + if (!use_new_mode_apis) { + boolean_t exact = 0; + best = CGDisplayBestModeForParameters(display_id, bpp, w, h, &exact); + if (!exact) { + best = NULL; + } + } +#endif + + return best; +} + +static SDL_Surface* QZ_SetVideoFullScreen (_THIS, SDL_Surface *current, int width, + int height, int bpp, Uint32 flags, + const BOOL save_gl) +{ + const BOOL isLion = IS_LION_OR_LATER(this); + NSRect screen_rect; + CGError error; + NSRect contentRect; + CGDisplayFadeReservationToken fade_token = kCGDisplayFadeReservationInvalidToken; + + current->flags = SDL_FULLSCREEN; + current->w = width; + current->h = height; + + contentRect = NSMakeRect (0, 0, width, height); + + /* Fade to black to hide resolution-switching flicker (and garbage + that is displayed by a destroyed OpenGL context, if applicable) */ + if ( CGAcquireDisplayFadeReservation (5, &fade_token) == kCGErrorSuccess ) { + CGDisplayFade (fade_token, 0.3, kCGDisplayBlendNormal, kCGDisplayBlendSolidColor, 0.0, 0.0, 0.0, TRUE); + } + + /* Destroy any previous mode */ + if (video_set == SDL_TRUE) + QZ_UnsetVideoMode (this, FALSE, save_gl); + + /* Sorry, QuickDraw was ripped out. */ + if (getenv("SDL_NSWindowPointer") || getenv("SDL_NSQuickDrawViewPointer")) { + SDL_SetError ("Embedded QuickDraw windows are no longer supported"); + goto ERR_NO_MATCH; + } + + QZ_ReleaseDisplayMode(this, mode); /* NULL is okay. */ + + /* See if requested mode exists */ + mode = QZ_BestMode(this, bpp, width, height); + + /* Require an exact match to the requested mode */ + if ( mode == NULL ) { + SDL_SetError ("Failed to find display resolution: %dx%dx%d", width, height, bpp); + goto ERR_NO_MATCH; + } + + /* Put up the blanking window (a window above all other windows) */ + if (getenv ("SDL_SINGLEDISPLAY")) + error = CGDisplayCapture (display_id); + else + error = CGCaptureAllDisplays (); + + if ( CGDisplayNoErr != error ) { + SDL_SetError ("Failed capturing display"); + goto ERR_NO_CAPTURE; + } + + /* Do the physical switch */ + if ( CGDisplayNoErr != QZ_SetDisplayMode(this, mode) ) { + SDL_SetError ("Failed switching display resolution"); + goto ERR_NO_SWITCH; + } + +#if (MAC_OS_X_VERSION_MIN_REQUIRED < 1070) + if ( !isLion ) { + current->pixels = (Uint32*) CGDisplayBaseAddress (display_id); + current->pitch = CGDisplayBytesPerRow (display_id); + + current->flags |= SDL_HWSURFACE; + current->flags |= SDL_PREALLOC; + /* current->hwdata = (void *) CGDisplayGetDrawingContext (display_id); */ + + this->UpdateRects = QZ_DirectUpdate; + this->LockHWSurface = QZ_LockHWSurface; + this->UnlockHWSurface = QZ_UnlockHWSurface; + + /* Setup double-buffer emulation */ + if ( flags & SDL_DOUBLEBUF ) { + + /* + Setup a software backing store for reasonable results when + double buffering is requested (since a single-buffered hardware + surface looks hideous). + + The actual screen blit occurs in a separate thread to allow + other blitting while waiting on the VBL (and hence results in higher framerates). + */ + this->LockHWSurface = NULL; + this->UnlockHWSurface = NULL; + this->UpdateRects = NULL; + + current->flags |= (SDL_HWSURFACE|SDL_DOUBLEBUF); + this->UpdateRects = QZ_DoubleBufferUpdate; + this->LockHWSurface = QZ_LockDoubleBuffer; + this->UnlockHWSurface = QZ_UnlockDoubleBuffer; + this->FlipHWSurface = QZ_FlipDoubleBuffer; + + current->pixels = SDL_malloc (current->pitch * current->h * 2); + if (current->pixels == NULL) { + SDL_OutOfMemory (); + goto ERR_DOUBLEBUF; + } + + sw_buffers[0] = current->pixels; + sw_buffers[1] = (Uint8*)current->pixels + current->pitch * current->h; + + quit_thread = NO; + sem1 = SDL_CreateSemaphore (0); + sem2 = SDL_CreateSemaphore (1); + thread = SDL_CreateThread ((int (*)(void *))QZ_ThreadFlip, this); + } + + if ( CGDisplayCanSetPalette (display_id) ) + current->flags |= SDL_HWPALETTE; + } +#endif + + /* Check if we should recreate the window */ + if (qz_window == nil) { + /* Manually create a window, avoids having a nib file resource */ + qz_window = [ [ SDL_QuartzWindow alloc ] + initWithContentRect:contentRect + styleMask:(isLion ? NSBorderlessWindowMask : 0) + backing:NSBackingStoreBuffered + defer:NO ]; + + if (qz_window != nil) { + [ qz_window setAcceptsMouseMovedEvents:YES ]; + [ qz_window setViewsNeedDisplay:NO ]; + if (isLion) { + [ qz_window setContentView: [ [ [ SDL_QuartzView alloc ] init ] autorelease ] ]; + } + } + } + /* We already have a window, just change its size */ + else { + [ qz_window setContentSize:contentRect.size ]; + current->flags |= (SDL_NOFRAME|SDL_RESIZABLE) & mode_flags; + [ window_view setFrameSize:contentRect.size ]; + } + + /* Setup OpenGL for a fullscreen context */ + if (flags & SDL_OPENGL) { + + if ( ! save_gl ) { + if ( ! QZ_SetupOpenGL (this, bpp, flags) ) { + goto ERR_NO_GL; + } + } + + /* Initialize the NSView and add it to our window. The presence of a valid window and + view allow the cursor to be changed whilst in fullscreen.*/ + window_view = [ [ NSView alloc ] initWithFrame:contentRect ]; + + if ( isLion ) { + [ window_view setAutoresizingMask: NSViewWidthSizable | NSViewHeightSizable ]; + } + + [ [ qz_window contentView ] addSubview:window_view ]; + + /* Apparently Lion checks some version flag set by the linker + and changes API behavior. Annoying. */ + if ( isLion ) { + [ qz_window setLevel:CGShieldingWindowLevel() ]; + [ gl_context setView: window_view ]; + //[ gl_context setFullScreen ]; + [ gl_context update ]; + } + +#if (MAC_OS_X_VERSION_MIN_REQUIRED < 1070) + if ( !isLion ) { + CGLError err; + CGLContextObj ctx; + + [ qz_window setLevel:NSNormalWindowLevel ]; + ctx = QZ_GetCGLContextObj (gl_context); + err = CGLSetFullScreen (ctx); + + if (err) { + SDL_SetError ("Error setting OpenGL fullscreen: %s", CGLErrorString(err)); + goto ERR_NO_GL; + } + } +#endif + + [ window_view release ]; + [ gl_context makeCurrentContext]; + + glClear (GL_COLOR_BUFFER_BIT); + + [ gl_context flushBuffer ]; + + current->flags |= SDL_OPENGL; + } else if (isLion) { /* For 2D, we build a CGBitmapContext */ + CGColorSpaceRef cgColorspace; + + /* Only recreate the view if it doesn't already exist */ + if (window_view == nil) { + window_view = [ [ NSView alloc ] initWithFrame:contentRect ]; + [ window_view setAutoresizingMask: NSViewWidthSizable | NSViewHeightSizable ]; + [ [ qz_window contentView ] addSubview:window_view ]; + [ window_view release ]; + } + + cgColorspace = CGColorSpaceCreateDeviceRGB(); + current->pitch = 4 * current->w; + current->pixels = SDL_malloc (current->h * current->pitch); + + cg_context = CGBitmapContextCreate (current->pixels, current->w, current->h, + 8, current->pitch, cgColorspace, + kCGImageAlphaNoneSkipFirst); + CGColorSpaceRelease (cgColorspace); + + current->flags |= SDL_SWSURFACE; + current->flags |= SDL_ASYNCBLIT; + current->hwdata = (void *) cg_context; + + /* Force this window to draw above _everything_. */ + [ qz_window setLevel:CGShieldingWindowLevel() ]; + + this->UpdateRects = QZ_UpdateRects; + this->LockHWSurface = QZ_LockHWSurface; + this->UnlockHWSurface = QZ_UnlockHWSurface; + } + + if (isLion) { + [ qz_window setHasShadow:NO]; + [ qz_window setOpaque:YES]; + [ qz_window makeKeyAndOrderFront:nil ]; + } + + /* !!! FIXME: keep an eye on this. + * This API is officially unavailable for 64-bit binaries. + * It happens to work, as of 10.7, but we're going to see if + * we can just simply do without it on newer OSes... + */ + #if (MAC_OS_X_VERSION_MIN_REQUIRED < 1070) && !defined(__LP64__) + if ( !isLion ) { + /* If we don't hide menu bar, it will get events and interrupt the program */ + HideMenuBar (); + } + #endif + + /* Fade in again (asynchronously) */ + if ( fade_token != kCGDisplayFadeReservationInvalidToken ) { + CGDisplayFade (fade_token, 0.5, kCGDisplayBlendSolidColor, kCGDisplayBlendNormal, 0.0, 0.0, 0.0, FALSE); + CGReleaseDisplayFadeReservation(fade_token); + } + + /* + There is a bug in Cocoa where NSScreen doesn't synchronize + with CGDirectDisplay, so the main screen's frame is wrong. + As a result, coordinate translation produces incorrect results. + We can hack around this bug by setting the screen rect + ourselves. This hack should be removed if/when the bug is fixed. + */ + screen_rect = NSMakeRect(0,0,width,height); + QZ_SetFrame(this, [ NSScreen mainScreen ], screen_rect); + + /* Save the flags to ensure correct tear-down */ + mode_flags = current->flags; + + /* Set app state, hide cursor if necessary, ... */ + QZ_DoActivate(this); + + return current; + + /* Since the blanking window covers *all* windows (even force quit) correct recovery is crucial */ +ERR_NO_GL: goto ERR_DOUBLEBUF; /* this goto is to stop a compiler warning on newer SDKs. */ +ERR_DOUBLEBUF: QZ_RestoreDisplayMode(this); +ERR_NO_SWITCH: CGReleaseAllDisplays (); +ERR_NO_CAPTURE: +ERR_NO_MATCH: if ( fade_token != kCGDisplayFadeReservationInvalidToken ) { + CGDisplayFade (fade_token, 0.5, kCGDisplayBlendSolidColor, kCGDisplayBlendNormal, 0.0, 0.0, 0.0, FALSE); + CGReleaseDisplayFadeReservation (fade_token); + } + return NULL; +} + +static SDL_Surface* QZ_SetVideoWindowed (_THIS, SDL_Surface *current, int width, + int height, int *bpp, Uint32 flags, + const BOOL save_gl) +{ + unsigned int style; + NSRect contentRect; + int center_window = 1; + int origin_x, origin_y; + CGDisplayFadeReservationToken fade_token = kCGDisplayFadeReservationInvalidToken; + + current->flags = 0; + current->w = width; + current->h = height; + + contentRect = NSMakeRect (0, 0, width, height); + + /* + Check if we should completely destroy the previous mode + - If it is fullscreen + - If it has different noframe or resizable attribute + - If it is OpenGL (since gl attributes could be different) + - If new mode is OpenGL, but previous mode wasn't + */ + if (video_set == SDL_TRUE) { + if (mode_flags & SDL_FULLSCREEN) { + /* Fade to black to hide resolution-switching flicker (and garbage + that is displayed by a destroyed OpenGL context, if applicable) */ + if (CGAcquireDisplayFadeReservation (5, &fade_token) == kCGErrorSuccess) { + CGDisplayFade (fade_token, 0.3, kCGDisplayBlendNormal, kCGDisplayBlendSolidColor, 0.0, 0.0, 0.0, TRUE); + } + QZ_UnsetVideoMode (this, TRUE, save_gl); + } + else if ( ((mode_flags ^ flags) & (SDL_NOFRAME|SDL_RESIZABLE)) || + (mode_flags & SDL_OPENGL) || + (flags & SDL_OPENGL) ) { + QZ_UnsetVideoMode (this, TRUE, save_gl); + } + } + + /* Sorry, QuickDraw was ripped out. */ + if (getenv("SDL_NSWindowPointer") || getenv("SDL_NSQuickDrawViewPointer")) { + SDL_SetError ("Embedded QuickDraw windows are no longer supported"); + if (fade_token != kCGDisplayFadeReservationInvalidToken) { + CGDisplayFade (fade_token, 0.5, kCGDisplayBlendSolidColor, kCGDisplayBlendNormal, 0.0, 0.0, 0.0, FALSE); + CGReleaseDisplayFadeReservation (fade_token); + } + return NULL; + } + + /* Check if we should recreate the window */ + if (qz_window == nil) { + + /* Set the window style based on input flags */ + if ( flags & SDL_NOFRAME ) { + style = NSBorderlessWindowMask; + current->flags |= SDL_NOFRAME; + } else { + style = NSTitledWindowMask; + style |= (NSMiniaturizableWindowMask | NSClosableWindowMask); + if ( flags & SDL_RESIZABLE ) { + style |= NSResizableWindowMask; + current->flags |= SDL_RESIZABLE; + } + } + + /* Manually create a window, avoids having a nib file resource */ + qz_window = [ [ SDL_QuartzWindow alloc ] + initWithContentRect:contentRect + styleMask:style + backing:NSBackingStoreBuffered + defer:NO ]; + + if (qz_window == nil) { + SDL_SetError ("Could not create the Cocoa window"); + if (fade_token != kCGDisplayFadeReservationInvalidToken) { + CGDisplayFade (fade_token, 0.5, kCGDisplayBlendSolidColor, kCGDisplayBlendNormal, 0.0, 0.0, 0.0, FALSE); + CGReleaseDisplayFadeReservation (fade_token); + } + return NULL; + } + + /*[ qz_window setReleasedWhenClosed:YES ];*/ /* no need to set this as it's the default for NSWindows */ + QZ_SetCaption(this, this->wm_title, this->wm_icon); + [ qz_window setAcceptsMouseMovedEvents:YES ]; + [ qz_window setViewsNeedDisplay:NO ]; + + if ( QZ_WindowPosition(this, &origin_x, &origin_y) ) { + /* have to flip the Y value (NSPoint is lower left corner origin) */ + [ qz_window setFrameTopLeftPoint:NSMakePoint((float) origin_x, (float) (this->info.current_h - origin_y))]; + center_window = 0; + } else if ( center_window ) { + [ qz_window center ]; + } + + [ qz_window setDelegate: + [ [ SDL_QuartzWindowDelegate alloc ] init ] ]; + [ qz_window setContentView: [ [ [ SDL_QuartzView alloc ] init ] autorelease ] ]; + } + /* We already have a window, just change its size */ + else { + [ qz_window setContentSize:contentRect.size ]; + current->flags |= (SDL_NOFRAME|SDL_RESIZABLE) & mode_flags; + [ window_view setFrameSize:contentRect.size ]; + } + + /* For OpenGL, we bind the context to a subview */ + if ( flags & SDL_OPENGL ) { + + if ( ! save_gl ) { + if ( ! QZ_SetupOpenGL (this, *bpp, flags) ) { + if (fade_token != kCGDisplayFadeReservationInvalidToken) { + CGDisplayFade (fade_token, 0.5, kCGDisplayBlendSolidColor, kCGDisplayBlendNormal, 0.0, 0.0, 0.0, FALSE); + CGReleaseDisplayFadeReservation (fade_token); + } + return NULL; + } + } + + window_view = [ [ NSView alloc ] initWithFrame:contentRect ]; + [ window_view setAutoresizingMask: NSViewWidthSizable | NSViewHeightSizable ]; + [ [ qz_window contentView ] addSubview:window_view ]; + [ gl_context setView: window_view ]; + [ window_view release ]; + [ gl_context makeCurrentContext]; + [ qz_window makeKeyAndOrderFront:nil ]; + current->flags |= SDL_OPENGL; + } + /* For 2D, we build a CGBitmapContext */ + else { + CGColorSpaceRef cgColorspace; + + /* Only recreate the view if it doesn't already exist */ + if (window_view == nil) { + + window_view = [ [ NSView alloc ] initWithFrame:contentRect ]; + [ window_view setAutoresizingMask: NSViewWidthSizable | NSViewHeightSizable ]; + [ [ qz_window contentView ] addSubview:window_view ]; + [ window_view release ]; + [ qz_window makeKeyAndOrderFront:nil ]; + } + + cgColorspace = CGColorSpaceCreateDeviceRGB(); + current->pitch = 4 * current->w; + current->pixels = SDL_malloc (current->h * current->pitch); + + cg_context = CGBitmapContextCreate (current->pixels, current->w, current->h, + 8, current->pitch, cgColorspace, + kCGImageAlphaNoneSkipFirst); + CGColorSpaceRelease (cgColorspace); + + current->flags |= SDL_SWSURFACE; + current->flags |= SDL_ASYNCBLIT; + current->hwdata = (void *) cg_context; + + this->UpdateRects = QZ_UpdateRects; + this->LockHWSurface = QZ_LockHWSurface; + this->UnlockHWSurface = QZ_UnlockHWSurface; + } + + /* Save flags to ensure correct teardown */ + mode_flags = current->flags; + + /* Fade in again (asynchronously) if we came from a fullscreen mode and faded to black */ + if (fade_token != kCGDisplayFadeReservationInvalidToken) { + CGDisplayFade (fade_token, 0.5, kCGDisplayBlendSolidColor, kCGDisplayBlendNormal, 0.0, 0.0, 0.0, FALSE); + CGReleaseDisplayFadeReservation (fade_token); + } + + return current; +} + + +static SDL_Surface* QZ_SetVideoModeInternal (_THIS, SDL_Surface *current, + int width, int height, int bpp, + Uint32 flags, BOOL save_gl) +{ + const BOOL isLion = IS_LION_OR_LATER(this); + + current->flags = 0; + current->pixels = NULL; + + /* Setup full screen video */ + if ( flags & SDL_FULLSCREEN ) { + if ( isLion ) { + bpp = 32; + } + current = QZ_SetVideoFullScreen (this, current, width, height, bpp, flags, save_gl ); + if (current == NULL) + return NULL; + } + /* Setup windowed video */ + else { + /* Force bpp to 32 */ + bpp = 32; + current = QZ_SetVideoWindowed (this, current, width, height, &bpp, flags, save_gl ); + if (current == NULL) + return NULL; + } + + if (qz_window != nil) { + nsgfx_context = [NSGraphicsContext graphicsContextWithWindow:qz_window]; + [NSGraphicsContext setCurrentContext:nsgfx_context]; + } + + /* Setup the new pixel format */ + { + int amask = 0, + rmask = 0, + gmask = 0, + bmask = 0; + + switch (bpp) { + case 16: /* (1)-5-5-5 RGB */ + amask = 0; + rmask = 0x7C00; + gmask = 0x03E0; + bmask = 0x001F; + break; + case 24: + SDL_SetError ("24bpp is not available"); + return NULL; + case 32: /* (8)-8-8-8 ARGB */ + amask = 0x00000000; + if ( (!isLion) && (flags & SDL_FULLSCREEN) ) { + rmask = 0x00FF0000; + gmask = 0x0000FF00; + bmask = 0x000000FF; + } else { +#if SDL_BYTEORDER == SDL_LIL_ENDIAN + rmask = 0x0000FF00; + gmask = 0x00FF0000; + bmask = 0xFF000000; +#else + rmask = 0x00FF0000; + gmask = 0x0000FF00; + bmask = 0x000000FF; +#endif + break; + } + } + + if ( ! SDL_ReallocFormat (current, bpp, + rmask, gmask, bmask, amask ) ) { + SDL_SetError ("Couldn't reallocate pixel format"); + return NULL; + } + } + + /* Signal successful completion (used internally) */ + video_set = SDL_TRUE; + + return current; +} + +static SDL_Surface* QZ_SetVideoMode(_THIS, SDL_Surface *current, + int width, int height, int bpp, + Uint32 flags) +{ + /* Don't throw away the GL context if we can just resize the current one. */ +#if 0 /* !!! FIXME: half-finished side project. Reenable this if you ever debug the corner cases. */ + const BOOL save_gl = ( (video_set == SDL_TRUE) && ((flags & SDL_OPENGL) == (current->flags & SDL_OPENGL)) && (bpp == current->format->BitsPerPixel) ); +#else + const BOOL save_gl = NO; +#endif + + NSOpenGLContext *glctx = gl_context; + SDL_Surface* retval = NULL; + + if (save_gl) { + [glctx retain]; /* just so we don't lose this when killing old views, etc */ + } + + retval = QZ_SetVideoModeInternal (this, current, width, height, bpp, flags, save_gl); + + if (save_gl) { + [glctx release]; /* something else should own this now, or we legitimately release it. */ + } + + return retval; +} + + +static int QZ_ToggleFullScreen (_THIS, int on) +{ + return 0; +} + +static int QZ_SetColors (_THIS, int first_color, int num_colors, + SDL_Color *colors) +{ +#if (MAC_OS_X_VERSION_MIN_REQUIRED < 1070) + /* we shouldn't have an 8-bit mode on Lion! */ + if (!IS_LION_OR_LATER(this)) { + CGTableCount index; + CGDeviceColor color; + + for (index = first_color; index < first_color+num_colors; index++) { + + /* Clamp colors between 0.0 and 1.0 */ + color.red = colors->r / 255.0; + color.blue = colors->b / 255.0; + color.green = colors->g / 255.0; + + colors++; + + CGPaletteSetColorAtIndex (palette, color, index); + } + + return ( CGDisplayNoErr == CGDisplaySetPalette (display_id, palette) ); + } +#endif + + return 0; +} + +#if (MAC_OS_X_VERSION_MIN_REQUIRED < 1070) +static int QZ_LockDoubleBuffer (_THIS, SDL_Surface *surface) +{ + return 1; +} + +static void QZ_UnlockDoubleBuffer (_THIS, SDL_Surface *surface) +{ +} + +/* The VBL delay is based on code by Ian R Ollmann's RezLib <iano@cco.caltech.edu> */ +static AbsoluteTime QZ_SecondsToAbsolute ( double seconds ) +{ + union + { + UInt64 i; + Nanoseconds ns; + } temp; + + temp.i = seconds * 1000000000.0; + + return NanosecondsToAbsolute ( temp.ns ); +} + +static int QZ_ThreadFlip (_THIS) +{ + Uint8 *src, *dst; + int skip, len, h; + + /* + Give this thread the highest scheduling priority possible, + in the hopes that it will immediately run after the VBL delay + */ + { + pthread_t current_thread; + int policy; + struct sched_param param; + + current_thread = pthread_self (); + pthread_getschedparam (current_thread, &policy, ¶m); + policy = SCHED_RR; + param.sched_priority = sched_get_priority_max (policy); + pthread_setschedparam (current_thread, policy, ¶m); + } + + while (1) { + + SDL_SemWait (sem1); + if (quit_thread) + return 0; + + /* + * We have to add SDL_VideoSurface->offset here, since we might be a + * smaller surface in the center of the framebuffer (you asked for + * a fullscreen resolution smaller than the hardware could supply + * so SDL is centering it in a bigger resolution)... + */ + dst = ((Uint8 *)((size_t)CGDisplayBaseAddress (display_id))) + SDL_VideoSurface->offset; + src = current_buffer + SDL_VideoSurface->offset; + len = SDL_VideoSurface->w * SDL_VideoSurface->format->BytesPerPixel; + h = SDL_VideoSurface->h; + skip = SDL_VideoSurface->pitch; + + /* Wait for the VBL to occur (estimated since we don't have a hardware interrupt) */ + { + + /* The VBL delay is based on Ian Ollmann's RezLib <iano@cco.caltech.edu> */ + double refreshRate; + double linesPerSecond; + double target; + double position; + double adjustment; + AbsoluteTime nextTime; + CFNumberRef refreshRateCFNumber; + + refreshRateCFNumber = CFDictionaryGetValue (mode, kCGDisplayRefreshRate); + if ( NULL == refreshRateCFNumber ) { + SDL_SetError ("Mode has no refresh rate"); + goto ERROR; + } + + if ( 0 == CFNumberGetValue (refreshRateCFNumber, kCFNumberDoubleType, &refreshRate) ) { + SDL_SetError ("Error getting refresh rate"); + goto ERROR; + } + + if ( 0 == refreshRate ) { + + SDL_SetError ("Display has no refresh rate, using 60hz"); + + /* ok, for LCD's we'll emulate a 60hz refresh, which may or may not look right */ + refreshRate = 60.0; + } + + linesPerSecond = refreshRate * h; + target = h; + + /* Figure out the first delay so we start off about right */ + position = CGDisplayBeamPosition (display_id); + if (position > target) + position = 0; + + adjustment = (target - position) / linesPerSecond; + + nextTime = AddAbsoluteToAbsolute (UpTime (), QZ_SecondsToAbsolute (adjustment)); + + MPDelayUntil (&nextTime); + } + + + /* On error, skip VBL delay */ + ERROR: + + /* TODO: use CGContextDrawImage here too! Create two CGContextRefs the same way we + create two buffers, replace current_buffer with current_context and set it + appropriately in QZ_FlipDoubleBuffer. */ + while ( h-- ) { + + SDL_memcpy (dst, src, len); + src += skip; + dst += skip; + } + + /* signal flip completion */ + SDL_SemPost (sem2); + } + + return 0; +} + +static int QZ_FlipDoubleBuffer (_THIS, SDL_Surface *surface) +{ + /* wait for previous flip to complete */ + SDL_SemWait (sem2); + + current_buffer = surface->pixels; + + if (surface->pixels == sw_buffers[0]) + surface->pixels = sw_buffers[1]; + else + surface->pixels = sw_buffers[0]; + + /* signal worker thread to do the flip */ + SDL_SemPost (sem1); + + return 0; +} + +static void QZ_DoubleBufferUpdate (_THIS, int num_rects, SDL_Rect *rects) +{ + /* perform a flip if someone calls updaterects on a doublebuferred surface */ + this->FlipHWSurface (this, SDL_VideoSurface); +} + +static void QZ_DirectUpdate (_THIS, int num_rects, SDL_Rect *rects) +{ +#pragma unused(this,num_rects,rects) +} +#endif + +/* Resize icon, BMP format */ +static const unsigned char QZ_ResizeIcon[] = { + 0x42,0x4d,0x31,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x36,0x00,0x00,0x00,0x28,0x00, + 0x00,0x00,0x0d,0x00,0x00,0x00,0x0d,0x00,0x00,0x00,0x01,0x00,0x18,0x00,0x00,0x00, + 0x00,0x00,0xfb,0x01,0x00,0x00,0x13,0x0b,0x00,0x00,0x13,0x0b,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x0b,0xff,0xff, + 0xff,0xda,0xda,0xda,0x87,0x87,0x87,0xe8,0xe8,0xe8,0xff,0xff,0xff,0xda,0xda,0xda, + 0x87,0x87,0x87,0xe8,0xe8,0xe8,0xff,0xff,0xff,0xda,0xda,0xda,0x87,0x87,0x87,0xe8, + 0xe8,0xe8,0xff,0xff,0xff,0x0b,0xff,0xff,0xff,0xff,0xff,0xff,0xda,0xda,0xda,0x87, + 0x87,0x87,0xe8,0xe8,0xe8,0xff,0xff,0xff,0xda,0xda,0xda,0x87,0x87,0x87,0xe8,0xe8, + 0xe8,0xff,0xff,0xff,0xda,0xda,0xda,0x87,0x87,0x87,0xff,0xff,0xff,0x0b,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xd5,0xd5,0xd5,0x87,0x87,0x87,0xe8,0xe8,0xe8, + 0xff,0xff,0xff,0xda,0xda,0xda,0x87,0x87,0x87,0xe8,0xe8,0xe8,0xff,0xff,0xff,0xda, + 0xda,0xda,0xff,0xff,0xff,0x0b,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xd7,0xd7,0xd7,0x87,0x87,0x87,0xe8,0xe8,0xe8,0xff,0xff,0xff,0xda,0xda, + 0xda,0x87,0x87,0x87,0xe8,0xe8,0xe8,0xff,0xff,0xff,0xff,0xff,0xff,0x0b,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xd7,0xd7,0xd7, + 0x87,0x87,0x87,0xe8,0xe8,0xe8,0xff,0xff,0xff,0xda,0xda,0xda,0x87,0x87,0x87,0xe8, + 0xe8,0xe8,0xff,0xff,0xff,0x0b,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xd7,0xd7,0xd7,0x87,0x87,0x87,0xe8,0xe8, + 0xe8,0xff,0xff,0xff,0xdc,0xdc,0xdc,0x87,0x87,0x87,0xff,0xff,0xff,0x0b,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xd9,0xd9,0xd9,0x87,0x87,0x87,0xe8,0xe8,0xe8,0xff,0xff,0xff,0xdc, + 0xdc,0xdc,0xff,0xff,0xff,0x0b,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xdb,0xdb, + 0xdb,0x87,0x87,0x87,0xe8,0xe8,0xe8,0xff,0xff,0xff,0xff,0xff,0xff,0x0b,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xdb,0xdb,0xdb,0x87,0x87,0x87,0xe8, + 0xe8,0xe8,0xff,0xff,0xff,0x0b,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xdc,0xdc,0xdc,0x87,0x87,0x87,0xff,0xff,0xff,0x0b,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xdc, + 0xdc,0xdc,0xff,0xff,0xff,0x0b,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x0b +}; + +static void QZ_DrawResizeIcon (_THIS) +{ + /* Check if we should draw the resize icon */ + if (SDL_VideoSurface->flags & SDL_RESIZABLE) { + + SDL_Rect icon_rect; + + /* Create the icon image */ + if (resize_icon == NULL) { + + SDL_RWops *rw; + SDL_Surface *tmp; + + rw = SDL_RWFromConstMem (QZ_ResizeIcon, sizeof(QZ_ResizeIcon)); + tmp = SDL_LoadBMP_RW (rw, SDL_TRUE); + + resize_icon = SDL_ConvertSurface (tmp, SDL_VideoSurface->format, SDL_SRCCOLORKEY); + SDL_SetColorKey (resize_icon, SDL_SRCCOLORKEY, 0xFFFFFF); + + SDL_FreeSurface (tmp); + } + + icon_rect.x = SDL_VideoSurface->w - 13; + icon_rect.y = SDL_VideoSurface->h - 13; + icon_rect.w = 13; + icon_rect.h = 13; + + SDL_BlitSurface (resize_icon, NULL, SDL_VideoSurface, &icon_rect); + } +} + +static void QZ_UpdateRects (_THIS, int numRects, SDL_Rect *rects) +{ + if (SDL_VideoSurface->flags & SDL_OPENGLBLIT) { + QZ_GL_SwapBuffers (this); + } + else if ( [ qz_window isMiniaturized ] ) { + + /* Do nothing if miniaturized */ + } + + else { + NSGraphicsContext *ctx = [NSGraphicsContext currentContext]; + if (ctx != nsgfx_context) { /* uhoh, you might be rendering from another thread... */ + [NSGraphicsContext setCurrentContext:nsgfx_context]; + ctx = nsgfx_context; + } + CGContextRef cgc = (CGContextRef) [ctx graphicsPort]; + QZ_DrawResizeIcon (this); + CGContextFlush (cg_context); + CGImageRef image = CGBitmapContextCreateImage (cg_context); + CGRect rectangle = CGRectMake (0,0,[window_view frame].size.width,[window_view frame].size.height); + + CGContextDrawImage (cgc, rectangle, image); + CGImageRelease(image); + CGContextFlush (cgc); + } +} + +static void QZ_VideoQuit (_THIS) +{ + CGDisplayFadeReservationToken fade_token = kCGDisplayFadeReservationInvalidToken; + + /* Restore gamma settings */ + CGDisplayRestoreColorSyncSettings (); + + /* Ensure the cursor will be visible and working when we quit */ + CGDisplayShowCursor (display_id); + CGAssociateMouseAndMouseCursorPosition (1); + + if (mode_flags & SDL_FULLSCREEN) { + /* Fade to black to hide resolution-switching flicker (and garbage + that is displayed by a destroyed OpenGL context, if applicable) */ + if (CGAcquireDisplayFadeReservation (5, &fade_token) == kCGErrorSuccess) { + CGDisplayFade (fade_token, 0.3, kCGDisplayBlendNormal, kCGDisplayBlendSolidColor, 0.0, 0.0, 0.0, TRUE); + } + QZ_UnsetVideoMode (this, TRUE, FALSE); + if (fade_token != kCGDisplayFadeReservationInvalidToken) { + CGDisplayFade (fade_token, 0.5, kCGDisplayBlendSolidColor, kCGDisplayBlendNormal, 0.0, 0.0, 0.0, FALSE); + CGReleaseDisplayFadeReservation (fade_token); + } + } + else + QZ_UnsetVideoMode (this, TRUE, FALSE); + +#if (MAC_OS_X_VERSION_MIN_REQUIRED < 1070) + if (!IS_LION_OR_LATER(this)) { + CGPaletteRelease(palette); + } +#endif + + if (opengl_library) { + SDL_UnloadObject(opengl_library); + opengl_library = NULL; + } + this->gl_config.driver_loaded = 0; + + if (field_edit) { + [field_edit release]; + field_edit = NULL; + } +} + +static int QZ_LockHWSurface(_THIS, SDL_Surface *surface) +{ + return 1; +} + +static void QZ_UnlockHWSurface(_THIS, SDL_Surface *surface) +{ +} + +static int QZ_AllocHWSurface(_THIS, SDL_Surface *surface) +{ + return(-1); /* unallowed (no HWSURFACE support here). */ +} + +static void QZ_FreeHWSurface (_THIS, SDL_Surface *surface) +{ +} + +/* Gamma functions */ +int QZ_SetGamma (_THIS, float red, float green, float blue) +{ + const CGGammaValue min = 0.0, max = 1.0; + + if (red == 0.0) + red = FLT_MAX; + else + red = 1.0 / red; + + if (green == 0.0) + green = FLT_MAX; + else + green = 1.0 / green; + + if (blue == 0.0) + blue = FLT_MAX; + else + blue = 1.0 / blue; + + if ( CGDisplayNoErr == CGSetDisplayTransferByFormula + (display_id, min, max, red, min, max, green, min, max, blue) ) { + + return 0; + } + else { + + return -1; + } +} + +int QZ_GetGamma (_THIS, float *red, float *green, float *blue) +{ + CGGammaValue dummy; + if ( CGDisplayNoErr == CGGetDisplayTransferByFormula + (display_id, &dummy, &dummy, red, + &dummy, &dummy, green, &dummy, &dummy, blue) ) + + return 0; + else + return -1; +} + +int QZ_SetGammaRamp (_THIS, Uint16 *ramp) +{ + const uint32_t tableSize = 255; + CGGammaValue redTable[tableSize]; + CGGammaValue greenTable[tableSize]; + CGGammaValue blueTable[tableSize]; + + int i; + + /* Extract gamma values into separate tables, convert to floats between 0.0 and 1.0 */ + for (i = 0; i < 256; i++) + redTable[i % 256] = ramp[i] / 65535.0; + + for (i=256; i < 512; i++) + greenTable[i % 256] = ramp[i] / 65535.0; + + for (i=512; i < 768; i++) + blueTable[i % 256] = ramp[i] / 65535.0; + + if ( CGDisplayNoErr == CGSetDisplayTransferByTable + (display_id, tableSize, redTable, greenTable, blueTable) ) + return 0; + else + return -1; +} + +int QZ_GetGammaRamp (_THIS, Uint16 *ramp) +{ + const uint32_t tableSize = 255; + CGGammaValue redTable[tableSize]; + CGGammaValue greenTable[tableSize]; + CGGammaValue blueTable[tableSize]; + uint32_t actual; + int i; + + if ( CGDisplayNoErr != CGGetDisplayTransferByTable + (display_id, tableSize, redTable, greenTable, blueTable, &actual) || + actual != tableSize) + + return -1; + + /* Pack tables into one array, with values from 0 to 65535 */ + for (i = 0; i < 256; i++) + ramp[i] = redTable[i % 256] * 65535.0; + + for (i=256; i < 512; i++) + ramp[i] = greenTable[i % 256] * 65535.0; + + for (i=512; i < 768; i++) + ramp[i] = blueTable[i % 256] * 65535.0; + + return 0; +} + diff --git a/3rdparty/SDL/src/video/quartz/SDL_QuartzWM.h b/3rdparty/SDL/src/video/quartz/SDL_QuartzWM.h new file mode 100644 index 0000000..0b0767e --- /dev/null +++ b/3rdparty/SDL/src/video/quartz/SDL_QuartzWM.h @@ -0,0 +1,27 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Sam Lantinga + slouken@libsdl.org +*/ + +struct WMcursor { + NSCursor *nscursor; +}; + +void QZ_UpdateCursor(_THIS); diff --git a/3rdparty/SDL/src/video/quartz/SDL_QuartzWM.m b/3rdparty/SDL/src/video/quartz/SDL_QuartzWM.m new file mode 100644 index 0000000..d526424 --- /dev/null +++ b/3rdparty/SDL/src/video/quartz/SDL_QuartzWM.m @@ -0,0 +1,444 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#include "SDL_QuartzVideo.h" +#include "SDL_QuartzWM.h" + + +void QZ_FreeWMCursor (_THIS, WMcursor *cursor) { + + if ( cursor != NULL ) { + [ cursor->nscursor release ]; + free (cursor); + } +} + +WMcursor* QZ_CreateWMCursor (_THIS, Uint8 *data, Uint8 *mask, + int w, int h, int hot_x, int hot_y) { + WMcursor *cursor; + NSBitmapImageRep *imgrep; + NSImage *img; + unsigned char *planes[5]; + int i; + NSAutoreleasePool *pool; + + pool = [ [ NSAutoreleasePool alloc ] init ]; + + /* Allocate the cursor memory */ + cursor = (WMcursor *)SDL_malloc(sizeof(WMcursor)); + if (cursor == NULL) goto outOfMemory; + + /* create the image representation and get the pointers to its storage */ + imgrep = [ [ [ NSBitmapImageRep alloc ] initWithBitmapDataPlanes: NULL pixelsWide: w pixelsHigh: h bitsPerSample: 1 samplesPerPixel: 2 hasAlpha: YES isPlanar: YES colorSpaceName: NSDeviceWhiteColorSpace bytesPerRow: (w+7)/8 bitsPerPixel: 0 ] autorelease ]; + if (imgrep == nil) goto outOfMemory; + [ imgrep getBitmapDataPlanes: planes ]; + + /* copy data and mask, extending the mask to all black pixels because the inversion effect doesn't work with Cocoa's alpha-blended cursors */ + for (i = 0; i < (w+7)/8*h; i++) { + planes[0][i] = data[i] ^ 0xFF; + planes[1][i] = mask[i] | data[i]; + } + + /* create image and cursor */ + img = [ [ [ NSImage alloc ] initWithSize: NSMakeSize(w, h) ] autorelease ]; + if (img == nil) goto outOfMemory; + [ img addRepresentation: imgrep ]; + if (system_version < 0x1030) { /* on 10.2, cursors must be 16*16 */ + if (w > 16 || h > 16) { /* too big: scale it down */ + [ img setScalesWhenResized: YES ]; + hot_x = hot_x*16/w; + hot_y = hot_y*16/h; + } + else { /* too small (or just right): extend it (from the bottom left corner, so hot_y must be adjusted) */ + hot_y += 16 - h; + } + [ img setSize: NSMakeSize(16, 16) ]; + } + cursor->nscursor = [ [ NSCursor alloc ] initWithImage: img hotSpot: NSMakePoint(hot_x, hot_y) ]; + if (cursor->nscursor == nil) goto outOfMemory; + + [ pool release ]; + return(cursor); + +outOfMemory: + [ pool release ]; + if (cursor != NULL) SDL_free(cursor); + SDL_OutOfMemory(); + return(NULL); +} + +void QZ_UpdateCursor (_THIS) { + BOOL state; + + if (cursor_should_be_visible || !(SDL_GetAppState() & SDL_APPMOUSEFOCUS)) { + state = YES; + } else { + state = NO; + } + if (state != cursor_visible) { + if (state) { + [ NSCursor unhide ]; + } else { + [ NSCursor hide ]; + } + cursor_visible = state; + } +} + +BOOL QZ_IsMouseInWindow (_THIS) { + if (qz_window == nil || (mode_flags & SDL_FULLSCREEN)) return YES; /*fullscreen*/ + else { + NSPoint p = [ qz_window mouseLocationOutsideOfEventStream ]; + p.y -= 1.0f; /* Apparently y goes from 1 to h, not from 0 to h-1 (i.e. the "location of the mouse" seems to be defined as "the location of the top left corner of the mouse pointer's hot pixel" */ + return NSPointInRect(p, [ window_view frame ]); + } +} + +int QZ_ShowWMCursor (_THIS, WMcursor *cursor) { + + if ( cursor == NULL) { + if ( cursor_should_be_visible ) { + cursor_should_be_visible = NO; + QZ_ChangeGrabState (this, QZ_HIDECURSOR); + } + QZ_UpdateCursor(this); + } + else { + if ( qz_window != nil && !(mode_flags & SDL_FULLSCREEN) ) { + [ qz_window invalidateCursorRectsForView: [ qz_window contentView ] ]; + } + if ( ! cursor_should_be_visible ) { + cursor_should_be_visible = YES; + QZ_ChangeGrabState (this, QZ_SHOWCURSOR); + } + [ cursor->nscursor performSelectorOnMainThread:@selector(set) withObject:nil waitUntilDone:NO ]; + QZ_UpdateCursor(this); + } + + return 1; +} + +/* + Coordinate conversion functions, for convenience + Cocoa sets the origin at the lower left corner of the window/screen + SDL, CoreGraphics/WindowServer, and QuickDraw use the origin at the upper left corner + The routines were written so they could be called before SetVideoMode() has finished; + this might have limited usefulness at the moment, but the extra cost is trivial. +*/ + +/* Convert Cocoa screen coordinate to Cocoa window coordinate */ +void QZ_PrivateGlobalToLocal (_THIS, NSPoint *p) { + + if ( ! CGDisplayIsCaptured (display_id) ) + *p = [ qz_window convertScreenToBase:*p ]; +} + + +/* Convert Cocoa window coordinate to Cocoa screen coordinate */ +void QZ_PrivateLocalToGlobal (_THIS, NSPoint *p) { + + if ( ! CGDisplayIsCaptured (display_id) ) + *p = [ qz_window convertBaseToScreen:*p ]; +} + +/* Convert SDL coordinate to Cocoa coordinate */ +void QZ_PrivateSDLToCocoa (_THIS, NSPoint *p) { + + if ( CGDisplayIsCaptured (display_id) ) { /* capture signals fullscreen */ + + p->y = CGDisplayPixelsHigh (display_id) - p->y; + } + else { + + *p = [ window_view convertPoint:*p toView: nil ]; + p->y = [window_view frame].size.height - p->y; + } +} + +/* Convert Cocoa coordinate to SDL coordinate */ +void QZ_PrivateCocoaToSDL (_THIS, NSPoint *p) { + + if ( CGDisplayIsCaptured (display_id) ) { /* capture signals fullscreen */ + + p->y = CGDisplayPixelsHigh (display_id) - p->y; + } + else { + + *p = [ window_view convertPoint:*p fromView: nil ]; + p->y = [window_view frame].size.height - p->y; + } +} + +/* Convert SDL coordinate to window server (CoreGraphics) coordinate */ +CGPoint QZ_PrivateSDLToCG (_THIS, NSPoint *p) { + + CGPoint cgp; + + if ( ! CGDisplayIsCaptured (display_id) ) { /* not captured => not fullscreen => local coord */ + + int height; + + QZ_PrivateSDLToCocoa (this, p); + QZ_PrivateLocalToGlobal (this, p); + + height = CGDisplayPixelsHigh (display_id); + p->y = height - p->y; + } + + cgp.x = p->x; + cgp.y = p->y; + + return cgp; +} + +#if 0 /* Dead code */ +/* Convert window server (CoreGraphics) coordinate to SDL coordinate */ +void QZ_PrivateCGToSDL (_THIS, NSPoint *p) { + + if ( ! CGDisplayIsCaptured (display_id) ) { /* not captured => not fullscreen => local coord */ + + int height; + + /* Convert CG Global to Cocoa Global */ + height = CGDisplayPixelsHigh (display_id); + p->y = height - p->y; + + QZ_PrivateGlobalToLocal (this, p); + QZ_PrivateCocoaToSDL (this, p); + } +} +#endif /* Dead code */ + +void QZ_PrivateWarpCursor (_THIS, int x, int y) { + NSPoint p; + CGPoint cgp; + + p = NSMakePoint (x, y); + cgp = QZ_PrivateSDLToCG (this, &p); + + /* this is the magic call that fixes cursor "freezing" after warp */ + CGAssociateMouseAndMouseCursorPosition (0); + CGWarpMouseCursorPosition (cgp); + if (grab_state != QZ_INVISIBLE_GRAB) { /* can't leave it disassociated? */ + CGAssociateMouseAndMouseCursorPosition (1); + } + SDL_PrivateAppActive (QZ_IsMouseInWindow (this), SDL_APPMOUSEFOCUS); +} + +void QZ_WarpWMCursor (_THIS, Uint16 x, Uint16 y) { + + /* Only allow warping when in foreground */ + if ( ! [ NSApp isActive ] ) + return; + + /* Do the actual warp */ + if (grab_state != QZ_INVISIBLE_GRAB) QZ_PrivateWarpCursor (this, x, y); + + /* Generate the mouse moved event */ + SDL_PrivateMouseMotion (0, 0, x, y); +} + +void QZ_MoveWMCursor (_THIS, int x, int y) { } +void QZ_CheckMouseMode (_THIS) { } + +void QZ_SetCaption (_THIS, const char *title, const char *icon) { + + if ( qz_window != nil ) { + NSString *string; + if ( title != NULL ) { + string = [ [ NSString alloc ] initWithUTF8String:title ]; + [ qz_window setTitle:string ]; + [ string release ]; + } + if ( icon != NULL ) { + string = [ [ NSString alloc ] initWithUTF8String:icon ]; + [ qz_window setMiniwindowTitle:string ]; + [ string release ]; + } + } +} + +void QZ_SetIcon (_THIS, SDL_Surface *icon, Uint8 *mask) +{ + NSBitmapImageRep *imgrep; + NSImage *img; + SDL_Surface *mergedSurface; + NSAutoreleasePool *pool; + Uint8 *pixels; + SDL_bool iconSrcAlpha; + Uint8 iconAlphaValue; + int i, j, maskPitch, index; + + pool = [ [ NSAutoreleasePool alloc ] init ]; + + imgrep = [ [ [ NSBitmapImageRep alloc ] initWithBitmapDataPlanes: NULL pixelsWide: icon->w pixelsHigh: icon->h bitsPerSample: 8 samplesPerPixel: 4 hasAlpha: YES isPlanar: NO colorSpaceName: NSDeviceRGBColorSpace bytesPerRow: 4*icon->w bitsPerPixel: 32 ] autorelease ]; + if (imgrep == nil) goto freePool; + pixels = [ imgrep bitmapData ]; + SDL_memset(pixels, 0, 4*icon->w*icon->h); /* make the background, which will survive in colorkeyed areas, completely transparent */ + +#if SDL_BYTEORDER == SDL_BIG_ENDIAN +#define BYTEORDER_DEPENDENT_RGBA_MASKS 0xFF000000, 0x00FF0000, 0x0000FF00, 0x000000FF +#else +#define BYTEORDER_DEPENDENT_RGBA_MASKS 0x000000FF, 0x0000FF00, 0x00FF0000, 0xFF000000 +#endif + mergedSurface = SDL_CreateRGBSurfaceFrom(pixels, icon->w, icon->h, 32, 4*icon->w, BYTEORDER_DEPENDENT_RGBA_MASKS); + if (mergedSurface == NULL) goto freePool; + + /* blit, with temporarily cleared SRCALPHA flag because we want to copy, not alpha-blend */ + iconSrcAlpha = ((icon->flags & SDL_SRCALPHA) != 0); + iconAlphaValue = icon->format->alpha; + SDL_SetAlpha(icon, 0, 255); + SDL_BlitSurface(icon, NULL, mergedSurface, NULL); + if (iconSrcAlpha) SDL_SetAlpha(icon, SDL_SRCALPHA, iconAlphaValue); + + SDL_FreeSurface(mergedSurface); + + /* apply mask, source alpha, and premultiply color values by alpha */ + maskPitch = (icon->w+7)/8; + for (i = 0; i < icon->h; i++) { + for (j = 0; j < icon->w; j++) { + index = i*4*icon->w + j*4; + if (!(mask[i*maskPitch + j/8] & (128 >> j%8))) { + pixels[index + 3] = 0; + } + else { + if (iconSrcAlpha) { + if (icon->format->Amask == 0) pixels[index + 3] = icon->format->alpha; + } + else { + pixels[index + 3] = 255; + } + } + if (pixels[index + 3] < 255) { + pixels[index + 0] = (Uint16)pixels[index + 0]*pixels[index + 3]/255; + pixels[index + 1] = (Uint16)pixels[index + 1]*pixels[index + 3]/255; + pixels[index + 2] = (Uint16)pixels[index + 2]*pixels[index + 3]/255; + } + } + } + + img = [ [ [ NSImage alloc ] initWithSize: NSMakeSize(icon->w, icon->h) ] autorelease ]; + if (img == nil) goto freePool; + [ img addRepresentation: imgrep ]; + [ NSApp setApplicationIconImage:img ]; + +freePool: + [ pool release ]; +} + +int QZ_IconifyWindow (_THIS) { + + if ( ! [ qz_window isMiniaturized ] ) { + [ qz_window miniaturize:nil ]; + if ( ! [ qz_window isMiniaturized ] ) { + SDL_SetError ("window iconification failed"); + return 0; + } + return 1; + } + else { + SDL_SetError ("window already iconified"); + return 0; + } +} + +/* +int QZ_GetWMInfo (_THIS, SDL_SysWMinfo *info) { + info->nsWindowPtr = qz_window; + return 0; +}*/ + +void QZ_ChangeGrabState (_THIS, int action) { + + /* + Figure out what the next state should be based on the action. + Ignore actions that can't change the current state. + */ + if ( grab_state == QZ_UNGRABBED ) { + if ( action == QZ_ENABLE_GRAB ) { + if ( cursor_should_be_visible ) + grab_state = QZ_VISIBLE_GRAB; + else + grab_state = QZ_INVISIBLE_GRAB; + } + } + else if ( grab_state == QZ_VISIBLE_GRAB ) { + if ( action == QZ_DISABLE_GRAB ) + grab_state = QZ_UNGRABBED; + else if ( action == QZ_HIDECURSOR ) + grab_state = QZ_INVISIBLE_GRAB; + } + else { + assert( grab_state == QZ_INVISIBLE_GRAB ); + + if ( action == QZ_DISABLE_GRAB ) + grab_state = QZ_UNGRABBED; + else if ( action == QZ_SHOWCURSOR ) + grab_state = QZ_VISIBLE_GRAB; + } + + /* now apply the new state */ + if (grab_state == QZ_UNGRABBED) { + + CGAssociateMouseAndMouseCursorPosition (1); + } + else if (grab_state == QZ_VISIBLE_GRAB) { + + CGAssociateMouseAndMouseCursorPosition (1); + } + else { + assert( grab_state == QZ_INVISIBLE_GRAB ); + + QZ_PrivateWarpCursor (this, SDL_VideoSurface->w / 2, SDL_VideoSurface->h / 2); + CGAssociateMouseAndMouseCursorPosition (0); + } +} + +SDL_GrabMode QZ_GrabInput (_THIS, SDL_GrabMode grab_mode) { + + int doGrab = grab_mode & SDL_GRAB_ON; + /*int fullscreen = grab_mode & SDL_GRAB_FULLSCREEN;*/ + + if ( this->screen == NULL ) { + SDL_SetError ("QZ_GrabInput: screen is NULL"); + return SDL_GRAB_OFF; + } + + if ( ! video_set ) { + /*SDL_SetError ("QZ_GrabInput: video is not set, grab will take effect on mode switch"); */ + current_grab_mode = grab_mode; + return grab_mode; /* Will be set later on mode switch */ + } + + if ( grab_mode != SDL_GRAB_QUERY ) { + if ( doGrab ) + QZ_ChangeGrabState (this, QZ_ENABLE_GRAB); + else + QZ_ChangeGrabState (this, QZ_DISABLE_GRAB); + + current_grab_mode = doGrab ? SDL_GRAB_ON : SDL_GRAB_OFF; + QZ_UpdateCursor(this); + } + + return current_grab_mode; +} diff --git a/3rdparty/SDL/src/video/quartz/SDL_QuartzWindow.h b/3rdparty/SDL/src/video/quartz/SDL_QuartzWindow.h new file mode 100644 index 0000000..d19375b --- /dev/null +++ b/3rdparty/SDL/src/video/quartz/SDL_QuartzWindow.h @@ -0,0 +1,51 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#if (MAC_OS_X_VERSION_MAX_ALLOWED < 1050) +typedef unsigned int NSUInteger; +#endif + +/* Subclass of NSWindow to fix genie effect and support resize events */ +@interface SDL_QuartzWindow : NSWindow +{ + BOOL watchForMouseUp; +} + +- (void)miniaturize:(id)sender; +- (void)display; +- (void)setFrame:(NSRect)frameRect display:(BOOL)flag; +- (void)appDidHide:(NSNotification*)note; +- (void)appWillUnhide:(NSNotification*)note; +- (void)appDidUnhide:(NSNotification*)note; +- (id)initWithContentRect:(NSRect)contentRect styleMask:(NSUInteger)styleMask backing:(NSBackingStoreType)backingType defer:(BOOL)flag; +@end + +/* Delegate for our NSWindow to send SDLQuit() on close */ +@interface SDL_QuartzWindowDelegate : NSObject +- (BOOL)windowShouldClose:(id)sender; +@end + +/* Subclass of NSView to set cursor rectangle */ +@interface SDL_QuartzView : NSView +- (void)resetCursorRects; +@end diff --git a/3rdparty/SDL/src/video/quartz/SDL_QuartzWindow.m b/3rdparty/SDL/src/video/quartz/SDL_QuartzWindow.m new file mode 100644 index 0000000..375833f --- /dev/null +++ b/3rdparty/SDL/src/video/quartz/SDL_QuartzWindow.m @@ -0,0 +1,231 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#include "SDL_QuartzVideo.h" +#include "SDL_QuartzWM.h" +#include "SDL_QuartzWindow.h" + +/* + This function makes the *SDL region* of the window 100% opaque. + The genie effect uses the alpha component. Otherwise, + it doesn't seem to matter what value it has. +*/ +static void QZ_SetPortAlphaOpaque () { + + SDL_Surface *surface = current_video->screen; + int bpp; + + bpp = surface->format->BitsPerPixel; + + if (bpp == 32) { + + Uint32 *pixels = (Uint32*) surface->pixels; + Uint32 rowPixels = surface->pitch / 4; + Uint32 i, j; + + for (i = 0; i < surface->h; i++) + for (j = 0; j < surface->w; j++) { + + pixels[ (i * rowPixels) + j ] |= 0xFF000000; + } + } +} + +@implementation SDL_QuartzWindow + +/* we override these methods to fix the miniaturize animation/dock icon bug */ +- (void)miniaturize:(id)sender +{ + if (SDL_VideoSurface->flags & SDL_OPENGL) { + + /* + Future: Grab framebuffer and put into NSImage + [ qz_window setMiniwindowImage:image ]; + */ + } + else { + + /* make the alpha channel opaque so anim won't have holes in it */ + QZ_SetPortAlphaOpaque (); + } + + /* window is hidden now */ + SDL_PrivateAppActive (0, SDL_APPACTIVE); + + [ super miniaturize:sender ]; +} + +- (void)display +{ + /* + This method fires just before the window deminaturizes from the Dock. + + We'll save the current visible surface, let the window manager redraw any + UI elements, and restore the SDL surface. This way, no expose event + is required, and the deminiaturize works perfectly. + */ + SDL_VideoDevice *this = (SDL_VideoDevice*)current_video; + + /* make sure pixels are fully opaque */ + if (! ( SDL_VideoSurface->flags & SDL_OPENGL ) ) + QZ_SetPortAlphaOpaque (); + + /* save current visible SDL surface */ + [ self cacheImageInRect:[ window_view frame ] ]; + + /* let the window manager redraw controls, border, etc */ + [ super display ]; + + /* restore visible SDL surface */ + [ self restoreCachedImage ]; + + /* window is visible again */ + SDL_PrivateAppActive (1, SDL_APPACTIVE); +} + +- (void)setFrame:(NSRect)frameRect display:(BOOL)flag +{ + + /* + If the video surface is NULL, this originated from QZ_SetVideoMode, + so don't send the resize event. + */ + SDL_VideoDevice *this = (SDL_VideoDevice*)current_video; + + if (this && SDL_VideoSurface == NULL) { + + [ super setFrame:frameRect display:flag ]; + } + else if (this && qz_window) { + + NSRect newViewFrame; + + [ super setFrame:frameRect display:flag ]; + + newViewFrame = [ window_view frame ]; + + SDL_PrivateResize (newViewFrame.size.width, newViewFrame.size.height); + } +} + +/* QZ_DoActivate() calls a low-level CoreGraphics routine to adjust + the cursor position, if input is being grabbed. If app activation is + triggered by a mouse click in the title bar, then the window manager + gets confused and thinks we're dragging the window. The solution + below postpones the activate event to avoid this scenario. */ +- (void)becomeKeyWindow +{ + NSEvent *event = [self currentEvent]; + if ([event type] == NSLeftMouseDown && [event window] == self) + watchForMouseUp = YES; + else + [super becomeKeyWindow]; +} + +- (void)sendEvent:(NSEvent *)event +{ + [super sendEvent:event]; + if (watchForMouseUp && [event type] == NSLeftMouseUp) + { + watchForMouseUp = NO; + [super becomeKeyWindow]; + } +} + +- (void)appDidHide:(NSNotification*)note +{ + SDL_PrivateAppActive (0, SDL_APPACTIVE); +} + +- (void)appWillUnhide:(NSNotification*)note +{ + SDL_VideoDevice *this = (SDL_VideoDevice*)current_video; + + if ( this ) { + + /* make sure pixels are fully opaque */ + if (! ( SDL_VideoSurface->flags & SDL_OPENGL ) ) + QZ_SetPortAlphaOpaque (); + + /* save current visible SDL surface */ + [ self cacheImageInRect:[ window_view frame ] ]; + } +} + +- (void)appDidUnhide:(NSNotification*)note +{ + /* restore cached image, since it may not be current, post expose event too */ + [ self restoreCachedImage ]; + + /*SDL_PrivateExpose ();*/ + + SDL_PrivateAppActive (1, SDL_APPACTIVE); +} + +- (id)initWithContentRect:(NSRect)contentRect styleMask:(NSUInteger)styleMask backing:(NSBackingStoreType)backingType defer:(BOOL)flag +{ + /* Make our window subclass receive these application notifications */ + [ [ NSNotificationCenter defaultCenter ] addObserver:self + selector:@selector(appDidHide:) name:NSApplicationDidHideNotification object:NSApp ]; + + [ [ NSNotificationCenter defaultCenter ] addObserver:self + selector:@selector(appDidUnhide:) name:NSApplicationDidUnhideNotification object:NSApp ]; + + [ [ NSNotificationCenter defaultCenter ] addObserver:self + selector:@selector(appWillUnhide:) name:NSApplicationWillUnhideNotification object:NSApp ]; + + return [ super initWithContentRect:contentRect styleMask:styleMask backing:backingType defer:flag ]; +} + +@end + +@implementation SDL_QuartzWindowDelegate +- (BOOL)windowShouldClose:(id)sender +{ + SDL_PrivateQuit(); + return NO; +} + +- (void)windowDidBecomeKey:(NSNotification *)aNotification +{ + QZ_DoActivate (current_video); +} + +- (void)windowDidResignKey:(NSNotification *)aNotification +{ + QZ_DoDeactivate (current_video); +} + +@end + +@implementation SDL_QuartzView + +- (void)resetCursorRects +{ + SDL_Cursor *sdlc = SDL_GetCursor(); + if (sdlc != NULL && sdlc->wm_cursor != NULL) { + [self addCursorRect: [self visibleRect] cursor: sdlc->wm_cursor->nscursor]; + } +} + +@end diff --git a/3rdparty/SDL/src/video/riscos/SDL_riscosASM.S b/3rdparty/SDL/src/video/riscos/SDL_riscosASM.S new file mode 100644 index 0000000..fae32f8 --- /dev/null +++ b/3rdparty/SDL/src/video/riscos/SDL_riscosASM.S @@ -0,0 +1,116 @@ +; +; SDL - Simple DirectMedia Layer +; Copyright (C) 1997-2012 Sam Lantinga +; +; This library is free software; you can redistribute it and/or +; modify it under the terms of the GNU Library General Public +; License as published by the Free Software Foundation; either +; version 2 of the License, or (at your option) any later version. +; +; This library 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 +; Library General Public License for more details. +; +; You should have received a copy of the GNU Library General Public +; License along with this library; if not, write to the Free +; Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +; +; Sam Lantinga +; slouken@libsdl.org +; +; Assembler routines for RISC OS display +; + + AREA |C$$CODE| + + EXPORT |RISCOS_Put32| + +; Display 32bpp to 32bpp, 1:1 +; +; Code provided by Adrain Lees +; +; entry a1 -> destination +; a2 = dest width in pixels +; a3 = dest line length in bytes +; a4 = dest height in scanlines +; arg5 -> source +; arg6 = byte offset from end of source line to start of next + +Arg5 * 10*4 +Arg6 * Arg5+4 + +RISCOS_Put32 ROUT + STMFD sp!,{a2,v1-v6,sl,fp,lr} + LDR ip,[sp,#Arg5] + MOV lr,a1 + B ucp64lp + +00 ;tail strip of 1-15 pixels + + LDR v1,[ip],#4 +01 SUBS a2,a2,#1 + STR v1,[lr],#4 + LDRHI v1,[ip],#4 + BHI %01 + B %02 + +ucp64end ADDS a2,a2,#16 + BNE %00 + +02 SUBS a4,a4,#1 ;height-- + LDRHI v1,[sp,#Arg6] + LDRHI a2,[sp] ;reload width + BLS %03 + + ;move to start of next scanline + + ADD lr,a1,a3 + ADD a1,a1,a3 + ADD ip,ip,v1 + +ucp64lp SUBS a2,a2,#16 + BLO ucp64end + + PLD [ip,#64] + + LDR v1,[ip],#4 + LDR v2,[ip],#4 + LDR v3,[ip],#4 + LDR v4,[ip],#4 + LDR v5,[ip],#4 + LDR v6,[ip],#4 + LDR sl,[ip],#4 + LDR fp,[ip],#4 + STR v1,[lr],#4 + STR v2,[lr],#4 + STR v3,[lr],#4 + STR v4,[lr],#4 + STR v5,[lr],#4 + STR v6,[lr],#4 + STR sl,[lr],#4 + STR fp,[lr],#4 + + PLD [ip,#64] + + LDR v1,[ip],#4 + LDR v2,[ip],#4 + LDR v3,[ip],#4 + LDR v4,[ip],#4 + LDR v5,[ip],#4 + LDR v6,[ip],#4 + LDR sl,[ip],#4 + LDR fp,[ip],#4 + STR v1,[lr],#4 + STR v2,[lr],#4 + STR v3,[lr],#4 + STR v4,[lr],#4 + STR v5,[lr],#4 + STR v6,[lr],#4 + STR sl,[lr],#4 + STR fp,[lr],#4 + + B ucp64lp + +03 LDMFD sp!,{a2,v1-v6,sl,fp,pc} + diff --git a/3rdparty/SDL/src/video/riscos/SDL_riscosFullScreenVideo.c b/3rdparty/SDL/src/video/riscos/SDL_riscosFullScreenVideo.c new file mode 100644 index 0000000..b8c3cf7 --- /dev/null +++ b/3rdparty/SDL/src/video/riscos/SDL_riscosFullScreenVideo.c @@ -0,0 +1,777 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* + File added by Alan Buckley (alan_baa@hotmail.com) for RISC OS compatability + 27 March 2003 + + Implements RISC OS full screen display. +*/ + +#include "SDL_video.h" +#include "SDL_mouse.h" +#include "../SDL_sysvideo.h" +#include "../SDL_pixels_c.h" +#include "../../events/SDL_events_c.h" + +#include "SDL_riscostask.h" +#include "SDL_riscosvideo.h" +#include "SDL_riscosevents_c.h" +#include "SDL_riscosmouse_c.h" + +#include "kernel.h" +#include "swis.h" +#include "unixlib/os.h" +#include "unixlib/local.h" + +/* Private structures */ +typedef struct tagScreenModeBlock +{ + int flags; // mode selector flags, bit 0 = 1, bit 1-7 format specifier, 8-31 reserved + int x_pixels; + int y_pixels; + int pixel_depth; // 2^pixel_depth = bpp,i.e. 0 = 1, 1 = 2, 4 = 16, 5 = 32 + int frame_rate; // -1 use first match + int mode_vars[5]; // array of index, value pairs terminated by -1 +} SCREENMODEBLOCK; + + +/* Helper functions */ +void FULLSCREEN_SetDeviceMode(_THIS); +int FULLSCREEN_SetMode(int width, int height, int bpp); +void FULLSCREEN_SetupBanks(_THIS); + +/* SDL video device functions for fullscreen mode */ +static int FULLSCREEN_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors); +static int FULLSCREEN_FlipHWSurface(_THIS, SDL_Surface *surface); +void FULLSCREEN_SetWMCaption(_THIS, const char *title, const char *icon); +extern int RISCOS_GetWmInfo(_THIS, SDL_SysWMinfo *info); + +/* UpdateRects variants */ +static void FULLSCREEN_UpdateRects(_THIS, int numrects, SDL_Rect *rects); +static void FULLSCREEN_UpdateRectsMemCpy(_THIS, int numrects, SDL_Rect *rects); +static void FULLSCREEN_UpdateRects8bpp(_THIS, int numrects, SDL_Rect *rects); +static void FULLSCREEN_UpdateRects16bpp(_THIS, int numrects, SDL_Rect *rects); +static void FULLSCREEN_UpdateRects32bpp(_THIS, int numrects, SDL_Rect *rects); +static void FULLSCREEN_UpdateRectsOS(_THIS, int numrects, SDL_Rect *rects); + +/* Local helper functions */ +static int cmpmodes(const void *va, const void *vb); +static int FULLSCREEN_AddMode(_THIS, int bpp, int w, int h); +void FULLSCREEN_SetWriteBank(int bank); +void FULLSCREEN_SetDisplayBank(int bank); +static void FULLSCREEN_DisableEscape(); +static void FULLSCREEN_EnableEscape(); +void FULLSCREEN_BuildModeList(_THIS); + +/* Following variable is set up in riskosTask.c */ +extern int riscos_backbuffer; /* Create a back buffer in system memory for full screen mode */ + +/* Following is used to create a sprite back buffer */ +extern unsigned char *WIMP_CreateBuffer(int width, int height, int bpp); + +/* Fast assembler copy */ +extern void RISCOS_Put32(void *to, int pixels, int pitch, int rows, void *from, int src_skip_bytes); + +SDL_Surface *FULLSCREEN_SetVideoMode(_THIS, SDL_Surface *current, + int width, int height, int bpp, Uint32 flags) +{ + _kernel_swi_regs regs; + Uint32 Rmask = 0; + Uint32 Gmask = 0; + Uint32 Bmask = 0; + int create_back_buffer = riscos_backbuffer; + + switch(bpp) + { + case 8: + flags |= SDL_HWPALETTE; + break; + + case 15: + case 16: + Bmask = 0x00007c00; + Gmask = 0x000003e0; + Rmask = 0x0000001f; + break; + + case 32: + Bmask = 0x00ff0000; + Gmask = 0x0000ff00; + Rmask = 0x000000ff; + break; + + default: + SDL_SetError("Pixel depth not supported"); + return NULL; + break; + } + + if (FULLSCREEN_SetMode(width, height, bpp) == 0) + { + SDL_SetError("Couldn't set requested mode"); + return (NULL); + } + +/* printf("Setting mode %dx%d\n", width, height); */ + + /* Allocate the new pixel format for the screen */ + if ( ! SDL_ReallocFormat(current, bpp, Rmask, Gmask, Bmask, 0) ) { + RISCOS_RestoreWimpMode(); + SDL_SetError("Couldn't allocate new pixel format for requested mode"); + return(NULL); + } + + /* Set up the new mode framebuffer */ + current->w = width; + this->hidden->height = current->h = height; + + regs.r[0] = -1; /* -1 for current screen mode */ + + /* Get screen width in bytes */ + regs.r[1] = 6; // Screen Width in bytes + _kernel_swi(OS_ReadModeVariable, ®s, ®s); + + current->pitch = regs.r[2]; + + if (flags & SDL_DOUBLEBUF) + { + regs.r[0] = 2; /* Screen area */ + _kernel_swi(OS_ReadDynamicArea, ®s, ®s); + + /* Reg 1 has amount of memory currently used for display */ + regs.r[0] = 2; /* Screen area */ + regs.r[1] = (current->pitch * height * 2) - regs.r[1]; + if (_kernel_swi(OS_ChangeDynamicArea, ®s, ®s) != NULL) + { + /* Can't allocate enough screen memory for double buffer */ + flags &= ~SDL_DOUBLEBUF; + } + } + + current->flags = flags | SDL_FULLSCREEN | SDL_HWSURFACE | SDL_PREALLOC; + + + /* Need to set display banks here for double buffering */ + if (flags & SDL_DOUBLEBUF) + { + FULLSCREEN_SetWriteBank(0); + FULLSCREEN_SetDisplayBank(1); + + create_back_buffer = 0; /* Don't need a back buffer for a double buffered display */ + } + + FULLSCREEN_SetupBanks(this); + + if (create_back_buffer) + { + /* If not double buffered we may need to create a memory + ** back buffer to simulate processing on other OSes. + ** This is turned on by setting the enviromental variable + ** SDL$<name>$BackBuffer >= 1 + */ + if (riscos_backbuffer == 3) + this->hidden->bank[0] = WIMP_CreateBuffer(width, height, bpp); + else + this->hidden->bank[0] = SDL_malloc(height * current->pitch); + if (this->hidden->bank[0] == 0) + { + RISCOS_RestoreWimpMode(); + SDL_SetError("Couldnt allocate memory for back buffer"); + return (NULL); + } + /* Surface updated in programs is now a software surface */ + current->flags &= ~SDL_HWSURFACE; + } + + /* Store address of allocated screen bank to be freed later */ + if (this->hidden->alloc_bank) SDL_free(this->hidden->alloc_bank); + if (create_back_buffer) + { + this->hidden->alloc_bank = this->hidden->bank[0]; + if (riscos_backbuffer == 3) + { + this->hidden->bank[0] += 60; /* Start of sprite data */ + if (bpp == 8) this->hidden->bank[0] += 2048; /* 8bpp sprite have palette first */ + } + } else + this->hidden->alloc_bank = 0; + + // Clear both banks to black + SDL_memset(this->hidden->bank[0], 0, height * current->pitch); + SDL_memset(this->hidden->bank[1], 0, height * current->pitch); + + this->hidden->current_bank = 0; + current->pixels = this->hidden->bank[0]; + + /* Have to set the screen here, so SetDeviceMode will pick it up */ + this->screen = current; + + /* Reset device functions for the wimp */ + FULLSCREEN_SetDeviceMode(this); + +/* FULLSCREEN_DisableEscape(); */ + + /* We're done */ + return(current); +} + +/* Reset any device functions that have been changed because we have run in WIMP mode */ +void FULLSCREEN_SetDeviceMode(_THIS) +{ + /* Update rects is different if we have a backbuffer */ + + if (riscos_backbuffer && (this->screen->flags & SDL_DOUBLEBUF) == 0) + { + switch(riscos_backbuffer) + { + case 2: /* ARM code full word copy */ + switch(this->screen->format->BytesPerPixel) + { + case 1: /* 8bpp modes */ + this->UpdateRects = FULLSCREEN_UpdateRects8bpp; + break; + case 2: /* 15/16bpp modes */ + this->UpdateRects = FULLSCREEN_UpdateRects16bpp; + break; + case 4: /* 32 bpp modes */ + this->UpdateRects = FULLSCREEN_UpdateRects32bpp; + break; + + default: /* Just default to the memcpy routine */ + this->UpdateRects = FULLSCREEN_UpdateRectsMemCpy; + break; + } + break; + + case 3: /* Use OS sprite plot routine */ + this->UpdateRects = FULLSCREEN_UpdateRectsOS; + break; + + default: /* Old but safe memcpy */ + this->UpdateRects = FULLSCREEN_UpdateRectsMemCpy; + break; + } + } else + this->UpdateRects = FULLSCREEN_UpdateRects; /* Default do nothing implementation */ + + this->SetColors = FULLSCREEN_SetColors; + + this->FlipHWSurface = FULLSCREEN_FlipHWSurface; + + this->SetCaption = FULLSCREEN_SetWMCaption; + this->SetIcon = NULL; + this->IconifyWindow = NULL; + + this->ShowWMCursor = RISCOS_ShowWMCursor; + this->WarpWMCursor = FULLSCREEN_WarpWMCursor; + + this->PumpEvents = FULLSCREEN_PumpEvents; +} + +/* Query for the list of available video modes */ +void FULLSCREEN_BuildModeList(_THIS) +{ + _kernel_swi_regs regs; + char *enumInfo = NULL; + char *enum_ptr; + int *blockInfo; + int j; + int num_modes; + + /* Find out how much space we need */ + regs.r[0] = 2; /* Reason code */ + regs.r[2] = 0; /* Number of modes to skip */ + regs.r[6] = 0; /* pointer to block or 0 for count */ + regs.r[7] = 0; /* Size of block in bytes */ + _kernel_swi(OS_ScreenMode, ®s, ®s); + + num_modes = -regs.r[2]; + + /* Video memory should be in r[5] */ + this->info.video_mem = regs.r[5]/1024; + + enumInfo = (unsigned char *)SDL_malloc(-regs.r[7]); + if (enumInfo == NULL) + { + SDL_OutOfMemory(); + return; + } + /* Read mode information into block */ + regs.r[2] = 0; + regs.r[6] = (int)enumInfo; + regs.r[7] = -regs.r[7]; + _kernel_swi(OS_ScreenMode, ®s, ®s); + + enum_ptr = enumInfo; + + for (j =0; j < num_modes;j++) + { + blockInfo = (int *)enum_ptr; + if ((blockInfo[1] & 255) == 1) /* We understand this format */ + { + switch(blockInfo[4]) + { + case 3: /* 8 bits per pixel */ + FULLSCREEN_AddMode(this, 8, blockInfo[2], blockInfo[3]); + break; + case 4: /* 15 bits per pixel */ + FULLSCREEN_AddMode(this, 15, blockInfo[2], blockInfo[3]); + break; + case 5: /* 32 bits per pixel */ + FULLSCREEN_AddMode(this, 32, blockInfo[2], blockInfo[3]); + break; + } + } + + enum_ptr += blockInfo[0]; + } + + SDL_free(enumInfo); + + /* Sort the mode lists */ + for ( j=0; j<NUM_MODELISTS; ++j ) { + if ( SDL_nummodes[j] > 0 ) { + SDL_qsort(SDL_modelist[j], SDL_nummodes[j], sizeof *SDL_modelist[j], cmpmodes); + } + } +} + +static int FULLSCREEN_FlipHWSurface(_THIS, SDL_Surface *surface) +{ + _kernel_swi_regs regs; + regs.r[0] = 19; + + FULLSCREEN_SetDisplayBank(this->hidden->current_bank); + this->hidden->current_bank ^= 1; + FULLSCREEN_SetWriteBank(this->hidden->current_bank); + surface->pixels = this->hidden->bank[this->hidden->current_bank]; + + /* Wait for Vsync */ + _kernel_swi(OS_Byte, ®s, ®s); + + return(0); +} + +/* Nothing to do if we are writing direct to hardware */ +static void FULLSCREEN_UpdateRects(_THIS, int numrects, SDL_Rect *rects) +{ +} + +/* Safe but slower Memory copy from our allocated back buffer */ +static void FULLSCREEN_UpdateRectsMemCpy(_THIS, int numrects, SDL_Rect *rects) +{ + int j; + char *to, *from; + int pitch = this->screen->pitch; + int row; + int xmult = this->screen->format->BytesPerPixel; + for (j = 0; j < numrects; j++) + { + from = this->hidden->bank[0] + rects->x * xmult + rects->y * pitch; + to = this->hidden->bank[1] + rects->x * xmult + rects->y * pitch; + for (row = 0; row < rects->h; row++) + { + SDL_memcpy(to, from, rects->w * xmult); + from += pitch; + to += pitch; + } + rects++; + } +} + +/* Use optimized assembler memory copy. Deliberately copies extra columns if + necessary to ensure the rectangle is word aligned. */ +static void FULLSCREEN_UpdateRects8bpp(_THIS, int numrects, SDL_Rect *rects) +{ + int j; + char *to, *from; + int pitch = this->screen->pitch; + int width_bytes; + int src_skip_bytes; + + for (j = 0; j < numrects; j++) + { + from = this->hidden->bank[0] + rects->x + rects->y * pitch; + to = this->hidden->bank[1] + rects->x + rects->y * pitch; + width_bytes = rects->w; + if ((int)from & 3) + { + int extra = ((int)from & 3); + from -= extra; + to -= extra; + width_bytes += extra; + } + if (width_bytes & 3) width_bytes += 4 - (width_bytes & 3); + src_skip_bytes = pitch - width_bytes; + + RISCOS_Put32(to, (width_bytes >> 2), pitch, (int)rects->h, from, src_skip_bytes); + rects++; + } +} + +/* Use optimized assembler memory copy. Deliberately copies extra columns if + necessary to ensure the rectangle is word aligned. */ +static void FULLSCREEN_UpdateRects16bpp(_THIS, int numrects, SDL_Rect *rects) +{ + int j; + char *to, *from; + int pitch = this->screen->pitch; + int width_bytes; + int src_skip_bytes; + + for (j = 0; j < numrects; j++) + { + from = this->hidden->bank[0] + (rects->x << 1) + rects->y * pitch; + to = this->hidden->bank[1] + (rects->x << 1) + rects->y * pitch; + width_bytes = (((int)rects->w) << 1); + if ((int)from & 3) + { + from -= 2; + to -= 2; + width_bytes += 2; + } + if (width_bytes & 3) width_bytes += 2; + src_skip_bytes = pitch - width_bytes; + + RISCOS_Put32(to, (width_bytes >> 2), pitch, (int)rects->h, from, src_skip_bytes); + rects++; + } +} + +/* Use optimized assembler memory copy. 32 bpp modes are always word aligned */ +static void FULLSCREEN_UpdateRects32bpp(_THIS, int numrects, SDL_Rect *rects) +{ + int j; + char *to, *from; + int pitch = this->screen->pitch; + int width; + + for (j = 0; j < numrects; j++) + { + from = this->hidden->bank[0] + (rects->x << 2) + rects->y * pitch; + to = this->hidden->bank[1] + (rects->x << 2) + rects->y * pitch; + width = (int)rects->w ; + + RISCOS_Put32(to, width, pitch, (int)rects->h, from, pitch - (width << 2)); + rects++; + } +} + +/* Use operating system sprite plots. Currently this is much slower than the + other variants however accelerated sprite plotting can be seen on the horizon + so this prepares for it. */ +static void FULLSCREEN_UpdateRectsOS(_THIS, int numrects, SDL_Rect *rects) +{ + _kernel_swi_regs regs; + _kernel_oserror *err; + int j; + int y; + + regs.r[0] = 28 + 512; + regs.r[1] = (unsigned int)this->hidden->alloc_bank; + regs.r[2] = (unsigned int)this->hidden->alloc_bank+16; + regs.r[5] = 0; + + for (j = 0; j < numrects; j++) + { + y = this->screen->h - rects->y; /* top of clipping region */ + _kernel_oswrch(24); /* Set graphics clip region */ + _kernel_oswrch((rects->x << this->hidden->xeig) & 0xFF); /* left */ + _kernel_oswrch(((rects->x << this->hidden->xeig) >> 8) & 0xFF); + _kernel_oswrch(((y - rects->h) << this->hidden->yeig) & 0xFF); /* bottom */ + _kernel_oswrch((((y - rects->h) << this->hidden->yeig)>> 8) & 0xFF); + _kernel_oswrch(((rects->x + rects->w - 1) << this->hidden->xeig) & 0xFF); /* right */ + _kernel_oswrch((((rects->x + rects->w - 1)<< this->hidden->xeig) >> 8) & 0xFF); + _kernel_oswrch(((y-1) << this->hidden->yeig) & 0xFF); /* top */ + _kernel_oswrch((((y-1) << this->hidden->yeig) >> 8) & 0xFF); + + regs.r[3] = 0; + regs.r[4] = 0; + + if ((err = _kernel_swi(OS_SpriteOp, ®s, ®s)) != 0) + { + printf("OS_SpriteOp failed \n%s\n",err->errmess); + } + + rects++; + + /* Reset to full screen clipping */ + _kernel_oswrch(24); /* Set graphics clip region */ + _kernel_oswrch(0); /* left */ + _kernel_oswrch(0); + _kernel_oswrch(0); /* bottom */ + _kernel_oswrch(0); + _kernel_oswrch(((this->screen->w-1) << this->hidden->xeig) & 0xFF); /* right */ + _kernel_oswrch((((this->screen->w-1) << this->hidden->xeig) >> 8) & 0xFF); + _kernel_oswrch(((this->screen->h-1) << this->hidden->yeig) & 0xFF); /* top */ + _kernel_oswrch((((this->screen->h-1) << this->hidden->yeig) >> 8) & 0xFF); + } +} + + +int FULLSCREEN_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors) +{ + _kernel_swi_regs regs; + int palette[256]; + + regs.r[0] = -1; + regs.r[1] = -1; + regs.r[2] = (int)palette; + regs.r[3] = 1024; + regs.r[4] = 0; + _kernel_swi(ColourTrans_ReadPalette, ®s, ®s); + + while(ncolors--) + { + palette[firstcolor] = ((colors->b) << 24) | ((colors->g) << 16) | ((colors->r) << 8); + firstcolor++; + colors++; + } + + regs.r[0] = -1; + regs.r[1] = -1; + regs.r[2] = (int)palette; + regs.r[3] = 0; + regs.r[4] = 0; + _kernel_swi(ColourTrans_WritePalette, ®s, ®s); + + return(1); +} + + +static int cmpmodes(const void *va, const void *vb) +{ + SDL_Rect *a = *(SDL_Rect **)va; + SDL_Rect *b = *(SDL_Rect **)vb; + if(a->w == b->w) + return b->h - a->h; + else + return b->w - a->w; +} + +static int FULLSCREEN_AddMode(_THIS, int bpp, int w, int h) +{ + SDL_Rect *mode; + int i, index; + int next_mode; + + /* Check to see if we already have this mode */ + if ( bpp < 8 ) { /* Not supported */ + return(0); + } + index = ((bpp+7)/8)-1; + for ( i=0; i<SDL_nummodes[index]; ++i ) { + mode = SDL_modelist[index][i]; + if ( (mode->w == w) && (mode->h == h) ) { + return(0); + } + } + + /* Set up the new video mode rectangle */ + mode = (SDL_Rect *)SDL_malloc(sizeof *mode); + if ( mode == NULL ) { + SDL_OutOfMemory(); + return(-1); + } + mode->x = 0; + mode->y = 0; + mode->w = w; + mode->h = h; + + /* Allocate the new list of modes, and fill in the new mode */ + next_mode = SDL_nummodes[index]; + SDL_modelist[index] = (SDL_Rect **) + SDL_realloc(SDL_modelist[index], (1+next_mode+1)*sizeof(SDL_Rect *)); + if ( SDL_modelist[index] == NULL ) { + SDL_OutOfMemory(); + SDL_nummodes[index] = 0; + SDL_free(mode); + return(-1); + } + SDL_modelist[index][next_mode] = mode; + SDL_modelist[index][next_mode+1] = NULL; + SDL_nummodes[index]++; + + return(0); +} + +void FULLSCREEN_SetWriteBank(int bank) +{ + _kernel_swi_regs regs; + regs.r[0] = 112; + regs.r[1] = bank+1; + _kernel_swi(OS_Byte, ®s, ®s); +} + +void FULLSCREEN_SetDisplayBank(int bank) +{ + _kernel_swi_regs regs; + regs.r[0] = 113; + regs.r[1] = bank+1; + _kernel_swi(OS_Byte, ®s, ®s); +} + + +/** Disable special escape key processing */ +static void FULLSCREEN_DisableEscape() +{ + _kernel_swi_regs regs; + regs.r[0] = 229; + regs.r[1] = 1; + regs.r[2] = 0; + _kernel_swi(OS_Byte, ®s, ®s); + +} + +/** Enable special escape key processing */ +static void FULLSCREEN_EnableEscape() +{ + _kernel_swi_regs regs; + regs.r[0] = 229; + regs.r[1] = 0; + regs.r[2] = 0; + _kernel_swi(OS_Byte, ®s, ®s); + +} + +/** Store caption in case this is called before we create a window */ +void FULLSCREEN_SetWMCaption(_THIS, const char *title, const char *icon) +{ + SDL_strlcpy(this->hidden->title, title, SDL_arraysize(this->hidden->title)); +} + +/* Set screen mode +* +* Returns 1 if mode is set ok, otherwise 0 +*/ + +int FULLSCREEN_SetMode(int width, int height, int bpp) +{ + SCREENMODEBLOCK smb; + _kernel_swi_regs regs; + + smb.flags = 1; + smb.x_pixels = width; + smb.y_pixels = height; + smb.mode_vars[0] = -1; + + switch(bpp) + { + case 8: + smb.pixel_depth = 3; + /* Note: Need to set ModeFlags to 128 and NColour variables to 255 get full 8 bit palette */ + smb.mode_vars[0] = 0; smb.mode_vars[1] = 128; /* Mode flags */ + smb.mode_vars[2] = 3; smb.mode_vars[3] = 255; /* NColour (number of colours -1) */ + smb.mode_vars[4] = -1; /* End of list */ + break; + + case 15: + case 16: + smb.pixel_depth = 4; + break; + + case 32: + smb.pixel_depth = 5; + break; + + default: + SDL_SetError("Pixel depth not supported"); + return 0; + break; + } + + smb.frame_rate = -1; + + regs.r[0] = 0; + regs.r[1] = (int)&smb; + + if (_kernel_swi(OS_ScreenMode, ®s, ®s) != 0) + { + SDL_SetError("Couldn't set requested mode"); + return 0; + } + + /* Turn cursor off*/ + _kernel_oswrch(23);_kernel_oswrch(1);_kernel_oswrch(0); + _kernel_oswrch(0);_kernel_oswrch(0);_kernel_oswrch(0); + _kernel_oswrch(0);_kernel_oswrch(0);_kernel_oswrch(0); + _kernel_oswrch(0);_kernel_oswrch(0); + + return 1; +} + +/* Get Start addresses for the screen banks */ +void FULLSCREEN_SetupBanks(_THIS) +{ + _kernel_swi_regs regs; + int block[5]; + block[0] = 148; /* Write screen start */ + block[1] = 149; /* Display screen start */ + block[2] = 4; /* X eig factor */ + block[3] = 5; /* Y eig factor */ + block[4] = -1; /* End of list of variables to request */ + + regs.r[0] = (int)block; + regs.r[1] = (int)block; + _kernel_swi(OS_ReadVduVariables, ®s, ®s); + + this->hidden->bank[0] = (void *)block[0]; + this->hidden->bank[1] = (void *)block[1]; + this->hidden->xeig = block[2]; + this->hidden->yeig = block[3]; +} + +/* Toggle to full screen mode from the WIMP */ + +int FULLSCREEN_ToggleFromWimp(_THIS) +{ + int width = this->screen->w; + int height = this->screen->h; + int bpp = this->screen->format->BitsPerPixel; + + RISCOS_StoreWimpMode(); + if (FULLSCREEN_SetMode(width, height, bpp)) + { + char *buffer = this->hidden->alloc_bank; /* This is start of sprite data */ + /* Support back buffer mode only */ + if (riscos_backbuffer == 0) riscos_backbuffer = 1; + + FULLSCREEN_SetupBanks(this); + + this->hidden->bank[0] = buffer + 60; /* Start of sprite data */ + if (bpp == 8) this->hidden->bank[0] += 2048; /* 8bpp sprite have palette first */ + + this->hidden->current_bank = 0; + this->screen->pixels = this->hidden->bank[0]; + + /* Copy back buffer to screen memory */ + SDL_memcpy(this->hidden->bank[1], this->hidden->bank[0], width * height * this->screen->format->BytesPerPixel); + + FULLSCREEN_SetDeviceMode(this); + return 1; + } else + RISCOS_RestoreWimpMode(); + + return 0; +} diff --git a/3rdparty/SDL/src/video/riscos/SDL_riscosevents.c b/3rdparty/SDL/src/video/riscos/SDL_riscosevents.c new file mode 100644 index 0000000..5487507 --- /dev/null +++ b/3rdparty/SDL/src/video/riscos/SDL_riscosevents.c @@ -0,0 +1,549 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* + File added by Alan Buckley (alan_baa@hotmail.com) for RISC OS compatability + 27 March 2003 + + Implements keyboard setup, event pump and keyboard and mouse polling +*/ + + +#include "SDL.h" +#include "../../timer/SDL_timer_c.h" +#include "../../events/SDL_sysevents.h" +#include "../../events/SDL_events_c.h" +#include "../SDL_cursor_c.h" +#include "SDL_riscosvideo.h" +#include "SDL_riscosevents_c.h" + +#include "memory.h" +#include "stdlib.h" +#include "ctype.h" + +#include "kernel.h" +#include "swis.h" + +/* The translation table from a RISC OS internal key numbers to a SDL keysym */ +static SDLKey RO_keymap[SDLK_LAST]; + +/* RISC OS Key codes */ +#define ROKEY_SHIFT 0 +#define ROKEY_CTRL 1 +#define ROKEY_ALT 2 +/* Left shift is first key we will check for */ +#define ROKEY_LEFT_SHIFT 3 + +/* Need to ignore mouse buttons as they are processed separately */ +#define ROKEY_LEFT_MOUSE 9 +#define ROKEY_CENTRE_MOUSE 10 +#define ROKEY_RIGHT_MOUSE 11 + +/* No key has been pressed return value*/ +#define ROKEY_NONE 255 + +/* Id of last key in keyboard */ +#define ROKEY_LAST_KEY 124 + +/* Size of array for all keys */ +#define ROKEYBD_ARRAYSIZE 125 + +static char RO_pressed[ROKEYBD_ARRAYSIZE]; + +static SDL_keysym *TranslateKey(int intkey, SDL_keysym *keysym, int pressed); + +void RISCOS_PollMouse(_THIS); +void RISCOS_PollKeyboard(); + +void RISCOS_PollMouseHelper(_THIS, int fullscreen); + +#if SDL_THREADS_DISABLED +extern void DRenderer_FillBuffers(); + +/* Timer running function */ +extern void RISCOS_CheckTimer(); + +#endif + +void FULLSCREEN_PumpEvents(_THIS) +{ + /* Current implementation requires keyboard and mouse polling */ + RISCOS_PollKeyboard(); + RISCOS_PollMouse(this); +#if SDL_THREADS_DISABLED +// DRenderer_FillBuffers(); + if (SDL_timer_running) RISCOS_CheckTimer(); +#endif +} + + +void RISCOS_InitOSKeymap(_THIS) +{ + int i; + + /* Map the VK keysyms */ + for ( i=0; i<SDL_arraysize(RO_keymap); ++i ) + RO_keymap[i] = SDLK_UNKNOWN; + + RO_keymap[3] = SDLK_LSHIFT; + RO_keymap[4] = SDLK_LCTRL; + RO_keymap[5] = SDLK_LALT; + RO_keymap[6] = SDLK_RSHIFT; + RO_keymap[7] = SDLK_RCTRL; + RO_keymap[8] = SDLK_RALT; + RO_keymap[16] = SDLK_q; + RO_keymap[17] = SDLK_3; + RO_keymap[18] = SDLK_4; + RO_keymap[19] = SDLK_5; + RO_keymap[20] = SDLK_F4; + RO_keymap[21] = SDLK_8; + RO_keymap[22] = SDLK_F7; + RO_keymap[23] = SDLK_MINUS, + RO_keymap[25] = SDLK_LEFT; + RO_keymap[26] = SDLK_KP6; + RO_keymap[27] = SDLK_KP7; + RO_keymap[28] = SDLK_F11; + RO_keymap[29] = SDLK_F12; + RO_keymap[30] = SDLK_F10; + RO_keymap[31] = SDLK_SCROLLOCK; + RO_keymap[32] = SDLK_PRINT; + RO_keymap[33] = SDLK_w; + RO_keymap[34] = SDLK_e; + RO_keymap[35] = SDLK_t; + RO_keymap[36] = SDLK_7; + RO_keymap[37] = SDLK_i; + RO_keymap[38] = SDLK_9; + RO_keymap[39] = SDLK_0; + RO_keymap[41] = SDLK_DOWN; + RO_keymap[42] = SDLK_KP8; + RO_keymap[43] = SDLK_KP9; + RO_keymap[44] = SDLK_BREAK; + RO_keymap[45] = SDLK_BACKQUOTE; +/* RO_keymap[46] = SDLK_currency; TODO: Figure out if this has a value */ + RO_keymap[47] = SDLK_BACKSPACE; + RO_keymap[48] = SDLK_1; + RO_keymap[49] = SDLK_2; + RO_keymap[50] = SDLK_d; + RO_keymap[51] = SDLK_r; + RO_keymap[52] = SDLK_6; + RO_keymap[53] = SDLK_u; + RO_keymap[54] = SDLK_o; + RO_keymap[55] = SDLK_p; + RO_keymap[56] = SDLK_LEFTBRACKET; + RO_keymap[57] = SDLK_UP; + RO_keymap[58] = SDLK_KP_PLUS; + RO_keymap[59] = SDLK_KP_MINUS; + RO_keymap[60] = SDLK_KP_ENTER; + RO_keymap[61] = SDLK_INSERT; + RO_keymap[62] = SDLK_HOME; + RO_keymap[63] = SDLK_PAGEUP; + RO_keymap[64] = SDLK_CAPSLOCK; + RO_keymap[65] = SDLK_a; + RO_keymap[66] = SDLK_x; + RO_keymap[67] = SDLK_f; + RO_keymap[68] = SDLK_y; + RO_keymap[69] = SDLK_j; + RO_keymap[70] = SDLK_k; + RO_keymap[72] = SDLK_SEMICOLON; + RO_keymap[73] = SDLK_RETURN; + RO_keymap[74] = SDLK_KP_DIVIDE; + RO_keymap[76] = SDLK_KP_PERIOD; + RO_keymap[77] = SDLK_NUMLOCK; + RO_keymap[78] = SDLK_PAGEDOWN; + RO_keymap[79] = SDLK_QUOTE; + RO_keymap[81] = SDLK_s; + RO_keymap[82] = SDLK_c; + RO_keymap[83] = SDLK_g; + RO_keymap[84] = SDLK_h; + RO_keymap[85] = SDLK_n; + RO_keymap[86] = SDLK_l; + RO_keymap[87] = SDLK_SEMICOLON; + RO_keymap[88] = SDLK_RIGHTBRACKET; + RO_keymap[89] = SDLK_DELETE; + RO_keymap[90] = SDLK_KP_MINUS; + RO_keymap[91] = SDLK_KP_MULTIPLY; + RO_keymap[93] = SDLK_EQUALS; + RO_keymap[94] = SDLK_BACKSLASH; + RO_keymap[96] = SDLK_TAB; + RO_keymap[97] = SDLK_z; + RO_keymap[98] = SDLK_SPACE; + RO_keymap[99] = SDLK_v; + RO_keymap[100] = SDLK_b; + RO_keymap[101] = SDLK_m; + RO_keymap[102] = SDLK_COMMA; + RO_keymap[103] = SDLK_PERIOD; + RO_keymap[104] = SDLK_SLASH; + RO_keymap[105] = SDLK_END; + RO_keymap[106] = SDLK_KP0; + RO_keymap[107] = SDLK_KP1; + RO_keymap[108] = SDLK_KP3; + RO_keymap[112] = SDLK_ESCAPE; + RO_keymap[113] = SDLK_F1; + RO_keymap[114] = SDLK_F2; + RO_keymap[115] = SDLK_F3; + RO_keymap[116] = SDLK_F5; + RO_keymap[117] = SDLK_F6; + RO_keymap[118] = SDLK_F8; + RO_keymap[119] = SDLK_F9; + RO_keymap[120] = SDLK_HASH; + RO_keymap[121] = SDLK_RIGHT; + RO_keymap[122] = SDLK_KP4; + RO_keymap[123] = SDLK_KP5; + RO_keymap[124] = SDLK_KP2; + + SDL_memset(RO_pressed, 0, ROKEYBD_ARRAYSIZE); +} + + +/* Variable for mouse relative processing */ +int mouse_relative = 0; + +/* Check to see if we need to enter or leave mouse relative mode */ + +void RISCOS_CheckMouseMode(_THIS) +{ + /* If the mouse is hidden and input is grabbed, we use relative mode */ + if ( !(SDL_cursorstate & CURSOR_VISIBLE) && + (this->input_grab != SDL_GRAB_OFF) ) { + mouse_relative = 1; + } else { + mouse_relative = 0; + } +} + + +void RISCOS_PollMouse(_THIS) +{ + RISCOS_PollMouseHelper(this, 1); +} + +extern int mouseInWindow; + +void WIMP_PollMouse(_THIS) +{ + /* Only poll when mouse is over the window */ + if (!mouseInWindow) return; + + RISCOS_PollMouseHelper(this, 0); +} + +/* Static variables so only changes are reported */ +static Sint16 last_x = -1, last_y = -1; +static int last_buttons = 0; + +/* Share routine between WIMP and FULLSCREEN for polling mouse and + passing on events */ +void RISCOS_PollMouseHelper(_THIS, int fullscreen) +{ + _kernel_swi_regs regs; + static int starting = 1; + + if (_kernel_swi(OS_Mouse, ®s, ®s) == NULL) + { + Sint16 new_x = regs.r[0]; /* Initialy get as OS units */ + Sint16 new_y = regs.r[1]; + + /* Discard mouse events until they let go of the mouse after starting */ + if (starting && regs.r[2] != 0) + return; + else + starting = 0; + + if (new_x != last_x || new_y != last_y || last_buttons != regs.r[2]) + { + /* Something changed so generate appropriate events */ + int topLeftX, topLeftY; /* Top left OS units */ + int x, y; /* Mouse position in SDL pixels */ + + if (fullscreen) + { + topLeftX = 0; + topLeftY = (this->hidden->height << this->hidden->yeig) - 1; + } else + { + int window_state[9]; + + /* Get current window state */ + window_state[0] = this->hidden->window_handle; + regs.r[1] = (unsigned int)window_state; + _kernel_swi(Wimp_GetWindowState, ®s, ®s); + + topLeftX = window_state[1]; + topLeftY = window_state[4]; + } + + /* Convert co-ordinates to workspace */ + x = new_x - topLeftX; + y = topLeftY - new_y; /* Y goes from top of window/screen */ + + /* Convert OS units to pixels */ + x >>= this->hidden->xeig; + y >>= this->hidden->yeig; + + if (last_x != new_x || last_y != new_y) + { + if (mouse_relative) + { + int centre_x = SDL_VideoSurface->w/2; + int centre_y = SDL_VideoSurface->h/2; + + if (centre_x != x || centre_y != y) + { + if (SDL_VideoSurface) SDL_PrivateMouseMotion(0,1,x - centre_x, y - centre_y); + last_x = topLeftX + (centre_x << this->hidden->xeig); + last_y = topLeftY - (centre_y << this->hidden->yeig); + + /* Re-centre the mouse pointer, so we still get relative + movement when the mouse is at the edge of the window + or screen. + */ + { + unsigned char block[5]; + + block[0] = 3; /* OSWORD move pointer sub-reason code */ + block[1] = last_x & 0xFF; + block[2] = (last_x >> 8) & 0xFF; + block[3] = last_y & 0xFF; + block[4] = (last_y >> 8) & 0xFF; + + regs.r[0] = 21; /* OSWORD pointer stuff code */ + regs.r[1] = (int)block; + _kernel_swi(OS_Word, ®s, ®s); + } + } + } else + { + last_x = new_x; + last_y = new_y; + SDL_PrivateMouseMotion(0,0,x,y); + } + } + + if (last_buttons != regs.r[2]) + { + int changed = last_buttons ^ regs.r[2]; + last_buttons = regs.r[2]; + if (changed & 4) SDL_PrivateMouseButton((last_buttons & 4) ? SDL_PRESSED : SDL_RELEASED, SDL_BUTTON_LEFT, 0, 0); + if (changed & 2) SDL_PrivateMouseButton((last_buttons & 2) ? SDL_PRESSED : SDL_RELEASED, SDL_BUTTON_MIDDLE, 0, 0); + if (changed & 1) SDL_PrivateMouseButton((last_buttons & 1) ? SDL_PRESSED : SDL_RELEASED, SDL_BUTTON_RIGHT, 0, 0); + } + } + } +} + +void RISCOS_PollKeyboard() +{ + int which_key = ROKEY_LEFT_SHIFT; + int j; + int min_key, max_key; + SDL_keysym key; + + /* Scan the keyboard to see what is pressed */ + while (which_key <= ROKEY_LAST_KEY) + { + which_key = (_kernel_osbyte(121, which_key, 0) & 0xFF); + if (which_key != ROKEY_NONE) + { + switch(which_key) + { + /* Skip over mouse keys */ + case ROKEY_LEFT_MOUSE: + case ROKEY_CENTRE_MOUSE: + case ROKEY_RIGHT_MOUSE: + which_key = ROKEY_RIGHT_MOUSE; + break; + + /* Ignore keys that cause 2 internal number to be generated */ + case 71: case 24: case 87: case 40: + break; + + /* Ignore break as it can be latched on */ + case 44: + break; + + default: + RO_pressed[which_key] += 2; + break; + } + which_key++; + } + } + + /* Generate key released messages */ + min_key = ROKEY_LAST_KEY+1; + max_key = ROKEY_LEFT_SHIFT; + + for (j = ROKEY_LEFT_SHIFT; j <= ROKEY_LAST_KEY; j++) + { + if (RO_pressed[j]) + { + if (RO_pressed[j] == 1) + { + RO_pressed[j] = 0; + SDL_PrivateKeyboard(SDL_RELEASED, TranslateKey(j,&key,0)); + } else + { + if (j < min_key) min_key = j; + if (j > max_key) max_key = j; + } + } + } + + /* Generate key pressed messages */ + for (j = min_key; j <= max_key; j++) + { + if (RO_pressed[j]) + { + if (RO_pressed[j] == 2) + { + SDL_PrivateKeyboard(SDL_PRESSED,TranslateKey(j,&key,1)); + } + RO_pressed[j] = 1; + } + } +} + +static SDL_keysym *TranslateKey(int intkey, SDL_keysym *keysym, int pressed) +{ + /* Set the keysym information */ + keysym->scancode = (unsigned char) intkey; + keysym->sym = RO_keymap[intkey]; + keysym->mod = KMOD_NONE; + keysym->unicode = 0; + if ( pressed && SDL_TranslateUNICODE ) + { + int state; + int ch; + + state = (_kernel_osbyte(202, 0, 255) & 0xFF); + + /*TODO: Take into account other keyboard layouts */ + + ch = keysym->sym; /* This should handle most unshifted keys */ + + if (intkey < 9 || ch == SDLK_UNKNOWN) + { + ch = 0; + + } else if (state & 64) /* Control on */ + { + ch = ch & 31; + + } else + { + int topOfKey = 0; + if (state & 8) /* Shift on */ + { + topOfKey = 1; + } + + if ((state & 16) == 0) /* Caps lock is on */ + { + if (ch >= SDLK_a && ch <= SDLK_z) + { + if ((state & 128) == 0) /* Shift Enable off */ + { + /* All letter become upper case */ + topOfKey = 1; + } else + { + /* Shift+Letters gives lower case */ + topOfKey = 1 - topOfKey; + } + } + } + + if (topOfKey) + { + /* Key produced with shift held down */ + + /* Letters just give upper case version */ + if (ch >= SDLK_a && ch <= SDLK_z) ch = toupper(ch); + else + { + switch(ch) + { + case SDLK_HASH: ch = '~'; break; + case SDLK_QUOTE: ch = '@'; break; + case SDLK_COMMA: ch = '<'; break; + case SDLK_MINUS: ch = '_'; break; + case SDLK_PERIOD: ch = '>'; break; + case SDLK_SLASH: ch = '?'; break; + + case SDLK_0: ch = ')'; break; + case SDLK_1: ch = '!'; break; + case SDLK_2: ch = '"'; break; + case SDLK_3: ch = ''; break; + case SDLK_4: ch = '$'; break; + case SDLK_5: ch = '%'; break; + case SDLK_6: ch = '^'; break; + case SDLK_7: ch = '&'; break; + case SDLK_8: ch = '*'; break; + case SDLK_9: ch = '('; break; + + case SDLK_SEMICOLON: ch = ':'; break; + case SDLK_EQUALS: ch = '+'; break; + case SDLK_LEFTBRACKET: ch = '{'; break; + case SDLK_BACKSLASH: ch = '|'; break; + case SDLK_RIGHTBRACKET: ch = '}'; break; + case SDLK_BACKQUOTE: ch = ''; break; + + default: + ch = 0; /* Map to zero character if we don't understand it */ + break; + } + } + + } else if (ch > 126) + { + /* SDL key code < 126 map directly onto their Unicode equivalents */ + /* Keypad 0 to 9 maps to numeric equivalent */ + if (ch >= SDLK_KP0 && ch <= SDLK_KP9) ch = ch - SDLK_KP0 + '0'; + else + { + /* Following switch maps other keys that produce an Ascii value */ + switch(ch) + { + case SDLK_KP_PERIOD: ch = '.'; break; + case SDLK_KP_DIVIDE: ch = '/'; break; + case SDLK_KP_MULTIPLY: ch = '*'; break; + case SDLK_KP_MINUS: ch = '-'; break; + case SDLK_KP_PLUS: ch = '+'; break; + case SDLK_KP_EQUALS: ch = '='; break; + + default: + /* If we don't know what it is set the Unicode to 0 */ + ch = 0; + break; + } + } + } + } + + keysym->unicode = ch; + } + return(keysym); +} + +/* end of SDL_riscosevents.c ... */ + diff --git a/3rdparty/SDL/src/video/riscos/SDL_riscosevents_c.h b/3rdparty/SDL/src/video/riscos/SDL_riscosevents_c.h new file mode 100644 index 0000000..189b3c0 --- /dev/null +++ b/3rdparty/SDL/src/video/riscos/SDL_riscosevents_c.h @@ -0,0 +1,34 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#include "SDL_riscosvideo.h" + +/* Variables and functions exported by SDL_sysevents.c to other parts + of the native video subsystem (SDL_sysvideo.c) +*/ +extern void RISCOS_InitOSKeymap(_THIS); +extern void FULLSCREEN_PumpEvents(_THIS); +extern void WIMP_PumpEvents(_THIS); + +/* end of SDL_nullevents_c.h ... */ + diff --git a/3rdparty/SDL/src/video/riscos/SDL_riscosmouse.c b/3rdparty/SDL/src/video/riscos/SDL_riscosmouse.c new file mode 100644 index 0000000..b4a0bff --- /dev/null +++ b/3rdparty/SDL/src/video/riscos/SDL_riscosmouse.c @@ -0,0 +1,371 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* + File added by Alan Buckley (alan_baa@hotmail.com) for RISC OS compatability + 27 March 2003 + + Implements mouse cursor shape definitions and positioning +*/ + +#include "SDL_mouse.h" +#include "../../events/SDL_events_c.h" + +#include "SDL_riscosmouse_c.h" + +#include "kernel.h" +#include "swis.h" + +static WMcursor *current_cursor = NULL; +static WMcursor *defined_cursor = NULL; + +extern int mouseInWindow; + +/* Area to save cursor palette colours changed by SDL. + Actual values will be read before we change to the SDL cursor */ +static Uint8 wimp_cursor_palette[2][5] = { + {1, 25, 255, 255, 255}, + {3, 25, 255, 255, 255} +}; + +static int cursor_palette_saved = 0; + +void WIMP_SaveCursorPalette(); +void WIMP_RestoreWimpCursor(); +void WIMP_SetSDLCursorPalette(); + + +void RISCOS_FreeWMCursor(_THIS, WMcursor *cursor) +{ + SDL_free(cursor->data); + SDL_free(cursor); +} + +WMcursor *RISCOS_CreateWMCursor(_THIS, + Uint8 *data, Uint8 *mask, int w, int h, int hot_x, int hot_y) +{ + WMcursor *cursor; + Uint8 *cursor_data; + Uint8 *ptr; + int i,j,k; + int data_byte, mask_byte; + + /* Check to make sure the cursor size is okay */ + if ( (w > 32) || (h > 32) ) { + SDL_SetError("Only with width and height <= 32 pixels are allowed"); + return(NULL); + } + + /* Allocate the cursor */ + cursor = (WMcursor *)SDL_malloc(sizeof(*cursor)); + if ( cursor == NULL ) { + SDL_SetError("Out of memory"); + return(NULL); + } + + /* Note: SDL says width must be a multiple of 8 */ + cursor_data = SDL_malloc(w/4 * h); + if (cursor_data == NULL) + { + SDL_free(cursor); + SDL_SetError("Out of memory"); + return(NULL); + } + + cursor->w = w; + cursor->h = h; + cursor->hot_x = hot_x; + cursor->hot_y = hot_y; + cursor->data = cursor_data; + + +/* Data / Mask Resulting pixel on screen + 0 / 1 White + 1 / 1 Black + 0 / 0 Transparent + 1 / 0 Inverted color if possible, black if not. +*/ + ptr = cursor_data; + + for ( i=0; i<h; ++i ) + { + for (j = 0; j < w/8; ++j) + { + data_byte = *data; + mask_byte = *mask; + *ptr++ = 0; /* Sets whole byte transparent */ + *ptr = 0; + for (k = 0; k < 8; k++) + { + (*ptr) <<= 2; + if (data_byte & 1) *ptr |= 3; /* Black or inverted */ + else if(mask_byte & 1) *ptr |= 1; /* White */ + if ((k&3) == 3) ptr--; + data_byte >>= 1; + mask_byte >>= 1; + } + + ptr+=3; + data++; + mask++; + } + } + + return(cursor); +} + +int RISCOS_ShowWMCursor(_THIS, WMcursor *cursor) +{ + current_cursor = cursor; + + if (cursor == NULL) + { + _kernel_osbyte(106,0,0); + defined_cursor = NULL; + } else + { + WMcursor *old_cursor = defined_cursor; + + if (cursor != defined_cursor) + { + Uint8 cursor_def[10]; + + cursor_def[0] = 0; + cursor_def[1] = 2; /* Use shape number 2 */ + cursor_def[2] = cursor->w/4; /* Width in bytes */ + cursor_def[3] = cursor->h; /* Height (h) in pixels */ + cursor_def[4] = cursor->hot_x; /* ActiveX in pixels from left */ + cursor_def[5] = cursor->hot_y; /* ActiveY in pixels from top */ + cursor_def[6] = ((int)(cursor->data) & 0xFF); /* Least significant byte of pointer to data */ + cursor_def[7] = ((int)(cursor->data) >> 8) & 0xFF; /* ... */ + cursor_def[8] = ((int)(cursor->data) >> 16) & 0xFF; /* ... */ + cursor_def[9] = ((int)(cursor->data) >> 24) & 0xFF; /* Most significant byte of pointer to data */ + + if (_kernel_osword(21, (int *)cursor_def) != 0) + { + SDL_SetError("RISCOS couldn't create the cursor to show"); + return(0); + } + defined_cursor = cursor; + } + + if (old_cursor == NULL) + { + /* First time or reshow in window, so save/setup palette */ + if (!cursor_palette_saved) + { + WIMP_SaveCursorPalette(); + } + WIMP_SetSDLCursorPalette(); + } + + _kernel_osbyte(106, 2, 0); + } + + return(1); +} + +void FULLSCREEN_WarpWMCursor(_THIS, Uint16 x, Uint16 y) +{ + Uint8 move_block[5]; + int eig_block[3]; + _kernel_swi_regs regs; + int os_x, os_y; + + eig_block[0] = 4; /* X eig factor */ + eig_block[1] = 5; /* Y eig factor */ + eig_block[2] = -1; /* End of list of variables to request */ + + regs.r[0] = (int)eig_block; + regs.r[1] = (int)eig_block; + _kernel_swi(OS_ReadVduVariables, ®s, ®s); + + os_x = x << eig_block[0]; + os_y = y << eig_block[1]; + + move_block[0] = 3; /* Move cursor */ + move_block[1] = os_x & 0xFF; + move_block[2] = (os_x >> 8) & 0xFF; + move_block[3] = os_y & 0xFF; + move_block[4] = (os_y >> 8) & 0xFF; + + _kernel_osword(21, (int *)move_block); + SDL_PrivateMouseMotion(0, 0, x, y); +} + + +/* Reshow cursor when mouse re-enters the window */ +void WIMP_ReshowCursor(_THIS) +{ + defined_cursor = NULL; + cursor_palette_saved = 0; + RISCOS_ShowWMCursor(this, current_cursor); +} + +void WIMP_WarpWMCursor(_THIS, Uint16 x, Uint16 y) +{ + _kernel_swi_regs regs; + int window_state[9]; + char block[5]; + int osX, osY; + + window_state[0] = this->hidden->window_handle; + regs.r[1] = (unsigned int)window_state; + _kernel_swi(Wimp_GetWindowState, ®s, ®s); + + osX = (x << this->hidden->xeig) + window_state[1]; + osY = window_state[4] - (y << this->hidden->yeig); + + block[0] = 3; + block[1] = osX & 0xFF; + block[2] = (osX >> 8) & 0xFF; + block[3] = osY & 0xFF; + block[4] = (osY >> 8) & 0xFF; + + regs.r[0] = 21; + regs.r[1] = (int)block; + _kernel_swi(OS_Word, ®s, ®s); + SDL_PrivateMouseMotion(0, 0, x, y); +} + +int WIMP_ShowWMCursor(_THIS, WMcursor *cursor) +{ + if (mouseInWindow) return RISCOS_ShowWMCursor(this, cursor); + else current_cursor = cursor; + + return 1; +} + +SDL_GrabMode RISCOS_GrabInput(_THIS, SDL_GrabMode mode) +{ + /* In fullscreen mode we don't need to do anything */ + if (mode < SDL_GRAB_FULLSCREEN) + { + _kernel_swi_regs regs; + unsigned char block[9]; + block[0] = 1; /* Define mouse cursor bounding block */ + + if ( mode == SDL_GRAB_OFF ) + { + /* Clip to whole screen */ + + int r = (this->hidden->screen_width << this->hidden->xeig) - 1; + int t = (this->hidden->screen_height << this->hidden->yeig) - 1; + + block[1] = 0; block[2] = 0; /* Left*/ + block[3] = 0; block[4] = 0; /* Bottom */ + block[5] = r & 0xFF; block[6] = (r >> 8) & 0xFF; /* Right */ + block[7] = t & 0xFF; block[8] = (t >> 8) & 0xFF; /* Top */ + } else + { + /* Clip to window */ + unsigned char window_state[36]; + + *((int *)window_state) = this->hidden->window_handle; + regs.r[1] = (unsigned int)window_state; + _kernel_swi(Wimp_GetWindowState, ®s, ®s); + + block[1] = window_state[4]; + block[2] = window_state[5]; + block[3] = window_state[8]; + block[4] = window_state[9]; + block[5] = window_state[12]; + block[6] = window_state[13]; + block[7] = window_state[16]; + block[8] = window_state[17]; + + } + + regs.r[0] = 21; /* OS word code */ + regs.r[1] = (int)block; + _kernel_swi(OS_Word, ®s, ®s); + } + + return mode; +} + +/* Save mouse cursor palette to be restore when we are no longer + defining a cursor */ + +void WIMP_SaveCursorPalette() +{ + _kernel_swi_regs regs; + int colour; + + for (colour = 0; colour < 2; colour++) + { + regs.r[0] = (int)wimp_cursor_palette[colour][0]; + regs.r[1] = 25; + /* Read settings with OS_ReadPalette */ + if (_kernel_swi(0x2f, ®s, ®s) == NULL) + { + wimp_cursor_palette[colour][2] = (unsigned char)((regs.r[2] >> 8) & 0xFF); + wimp_cursor_palette[colour][3] = (unsigned char)((regs.r[2] >> 16) & 0xFF); + wimp_cursor_palette[colour][4] = (unsigned char)((regs.r[2] >> 24) & 0xFF); + } + } + + cursor_palette_saved = 1; +} + +/* Restore the WIMP's cursor when we leave the SDL window */ +void WIMP_RestoreWimpCursor() +{ + int colour; + + /* Reset to pointer shape 1 */ + _kernel_osbyte(106, 1, 0); + + /* Reset pointer colours */ + if (cursor_palette_saved) + { + for (colour = 0; colour < 2; colour++) + { + _kernel_osword(12, (int *)wimp_cursor_palette[colour]); + } + } + cursor_palette_saved = 0; +} + +/* Set palette used for SDL mouse cursors */ +void WIMP_SetSDLCursorPalette() +{ + /* First time set up the mouse colours */ + Uint8 block[5]; + + /* Set up colour 1 as white */ + block[0] = 1; /* Colour to change 1 - 3 */ + block[1] = 25; /* Set pointer colour */ + block[2] = 255; /* red component*/ + block[3] = 255; /* green component */ + block[4] = 255; /* blue component*/ + _kernel_osword(12, (int *)block); + + /* Set colour 3 to back */ + block[0] = 3; /* Colour to change 1 - 3 */ + block[1] = 25; /* Set pointer colour*/ + block[2] = 0; /* red component*/ + block[3] = 0; /* green component */ + block[4] = 0; /* blue component*/ + _kernel_osword(12, (int *)block); +} diff --git a/3rdparty/SDL/src/video/riscos/SDL_riscosmouse_c.h b/3rdparty/SDL/src/video/riscos/SDL_riscosmouse_c.h new file mode 100644 index 0000000..9019cb4 --- /dev/null +++ b/3rdparty/SDL/src/video/riscos/SDL_riscosmouse_c.h @@ -0,0 +1,44 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#include "SDL_riscosvideo.h" + +/* The implementation dependent data for the window manager cursor */ +struct WMcursor { + int w; + int h; + int hot_x; + int hot_y; + Uint8 *data; +}; + +/* Functions to be exported */ +void RISCOS_FreeWMCursor(_THIS, WMcursor *cursor); +WMcursor *RISCOS_CreateWMCursor(_THIS, Uint8 *data, Uint8 *mask, int w, int h, int hot_x, int hot_y); + +int RISCOS_ShowWMCursor(_THIS, WMcursor *cursor); +void FULLSCREEN_WarpWMCursor(_THIS, Uint16 x, Uint16 y); + +int WIMP_ShowWMCursor(_THIS, WMcursor *cursor); +void WIMP_WarpWMCursor(_THIS, Uint16 x, Uint16 y); + diff --git a/3rdparty/SDL/src/video/riscos/SDL_riscossprite.c b/3rdparty/SDL/src/video/riscos/SDL_riscossprite.c new file mode 100644 index 0000000..70b2f91 --- /dev/null +++ b/3rdparty/SDL/src/video/riscos/SDL_riscossprite.c @@ -0,0 +1,265 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* + File added by Alan Buckley (alan_baa@hotmail.com) for RISC OS compatability + 27 March 2003 + + Implements Sprite plotting code for wimp display.window +*/ + +#include "kernel.h" +#include "swis.h" + +#include "SDL_stdinc.h" +#include "SDL_riscosvideo.h" + +extern void WIMP_ReadModeInfo(_THIS); + +void WIMP_PaletteChanged(_THIS); + + +/* Create sprite buffer for screen */ + +unsigned char *WIMP_CreateBuffer(int width, int height, int bpp) +{ + int size; + char sprite_name[12] = "display"; + unsigned char *buffer; + _kernel_swi_regs regs; + int bytesPerPixel; + int bytesPerRow; + int offsetToSpriteData = 60; + + switch(bpp) + { + case 32: bytesPerPixel = 4; break; + case 16: bytesPerPixel = 2; break; + case 8: + bytesPerPixel = 1; + offsetToSpriteData += 2048; /* Add in size of palette */ + break; + default: + return NULL; + break; + } + + bytesPerRow = bytesPerPixel * width; + + if ((bytesPerRow & 3) != 0) + { + bytesPerRow += 4 - (bytesPerRow & 3); + } + size = bytesPerRow * height; + + buffer = SDL_malloc( (size_t) size + offsetToSpriteData ); + if (!buffer) return NULL; + + /* Initialise a sprite area */ + + *(unsigned int *)buffer = size + offsetToSpriteData; + *(unsigned int *)(buffer + 8) = 16; + + regs.r[0] = 256+9; + regs.r[1] = (unsigned int)buffer; + _kernel_swi(OS_SpriteOp, ®s, ®s); + + regs.r[0] = 256+15; + regs.r[1] = (unsigned int)buffer; + regs.r[2] = (unsigned int)&sprite_name; + regs.r[3] = 0; /* Palette flag: 0 = no palette */ + regs.r[4] = width; + regs.r[5] = height; + if (bpp == 8) + { + /* Use old style mode number */ + regs.r[6] = 28; /* 8bpp 90x90dpi */ + } else + { + regs.r[6] = (((bpp == 16) ? 5 : 6) << 27) /* Type 6 = 32bpp sprite, 5 = 16bpp sprite */ + | (90 << 14) /* Vertical dpi */ + | (90 << 1) /* Horizontal dpi */ + | 1; /* Marker to distinguish between mode selectors and sprite modes */ + } + if (_kernel_swi(OS_SpriteOp, ®s, ®s) == NULL) + { + if (bpp == 8) + { + /* Modify sprite to take into account 256 colour palette */ + int *sprite = (int *)(buffer + 16); + /* Adjust sprite offsets */ + sprite[0] += 2048; + sprite[8] += 2048; + sprite[9] += 2048; + /* Adjust sprite area next free pointer */ + (*(int *)(buffer+12)) += 2048; + + /* Don't need to set up palette as SDL sets up the default + 256 colour palette */ +/* { + int *pal = sprite + 11; + unsigned int j; + unsigned int entry; + for (j = 0; j < 255; j++) + { + entry = (j << 24) | (j << 16) | (j << 8); + *pal++ = entry; + *pal++ = entry; + } + } +*/ + } + } else + { + SDL_free(buffer); + buffer = NULL; + } + + return buffer; +} + + +/* Setup translation buffers for the sprite plotting */ + +void WIMP_SetupPlotInfo(_THIS) +{ + _kernel_swi_regs regs; + int *sprite = ((int *)this->hidden->bank[1])+4; + + regs.r[0] = (unsigned int)this->hidden->bank[1]; + regs.r[1] = (unsigned int)sprite; + regs.r[2] = -1; /* Current mode */ + regs.r[3] = -1; /* Current palette */ + regs.r[4] = 0; /* Get size of buffer */ + regs.r[5] = 1|2|16; /* R1 - pointer to sprite and can use full palette words */ + regs.r[6] = 0; + regs.r[7] = 0; + + if (this->hidden->pixtrans) SDL_free(this->hidden->pixtrans); + this->hidden->pixtrans = 0; + + /* Get the size required for the buffer */ + _kernel_swi(ColourTrans_GenerateTable, ®s, ®s); + if (regs.r[4]) + { + this->hidden->pixtrans = SDL_malloc(regs.r[4]); + + regs.r[4] = (unsigned int)this->hidden->pixtrans; + /* Actually read the buffer */ + _kernel_swi(ColourTrans_GenerateTable, ®s, ®s); + } +} + +/* Plot the sprite in the given context */ +void WIMP_PlotSprite(_THIS, int x, int y) +{ + _kernel_swi_regs regs; + _kernel_oserror *err; + + regs.r[0] = 52 + 512; + regs.r[1] = (unsigned int)this->hidden->bank[1]; + regs.r[2] = (unsigned int)this->hidden->bank[1]+16; + regs.r[3] = x; + regs.r[4] = y; + regs.r[5] = 0|32; /* Overwrite screen and pixtrans contains wide colour entries */ + regs.r[6] = 0; /* No scale factors i.e. 1:1 */ + regs.r[7] = (int)this->hidden->pixtrans; + + if ((err = _kernel_swi(OS_SpriteOp, ®s, ®s)) != 0) + { + int *p = (int *)this->hidden->pixtrans; + printf("OS_SpriteOp failed \n%s\n",err->errmess); + printf("pixtrans %d\n", (int)this->hidden->pixtrans); + printf("%x %x %x\n", p[0], p[1], p[2]); + } +} + + +/* Wimp mode has changes so update colour mapping and pixel sizes + of windows and the sprites they plot */ + +void WIMP_ModeChanged(_THIS) +{ + int oldXeig = this->hidden->xeig; + int oldYeig = this->hidden->yeig; + + WIMP_ReadModeInfo(this); + + if (oldXeig == this->hidden->xeig && oldYeig == this->hidden->yeig) + { + /* Only need to update the palette */ + WIMP_PaletteChanged(this); + } else + { + _kernel_swi_regs regs; + int window_state[9]; + int extent[4]; + int currWidth, currHeight; + int newWidth, newHeight; + + /* Need to resize windows and update the palette */ + WIMP_SetupPlotInfo(this); + + + window_state[0] = this->hidden->window_handle; + regs.r[1] = (unsigned int)window_state; + _kernel_swi(Wimp_GetWindowState, ®s, ®s); + + currWidth = window_state[3] - window_state[1]; + currHeight = window_state[4] - window_state[2]; + + newWidth = (currWidth >> oldXeig) << this->hidden->xeig; + newHeight = (currHeight >> oldYeig) << this->hidden->yeig; + /* Need to avoid extent getting too small for visible part + of window */ + extent[0] = 0; + if (currHeight <= newHeight) + { + extent[1] = -newHeight; + } else + { + extent[1] = -currHeight; + } + if (currWidth <= newWidth) + { + extent[2] = newWidth; + } else + { + extent[2] = currWidth; + } + extent[3] = 0; + + regs.r[0] = this->hidden->window_handle; + regs.r[1] = (int)extent; + _kernel_swi(Wimp_SetExtent, ®s, ®s); + + /*TODO: May need to set flag to resize window on next open */ + } +} + +/* Palette has changed so update palettes used for windows sprites */ + +void WIMP_PaletteChanged(_THIS) +{ + WIMP_SetupPlotInfo(this); +} diff --git a/3rdparty/SDL/src/video/riscos/SDL_riscostask.c b/3rdparty/SDL/src/video/riscos/SDL_riscostask.c new file mode 100644 index 0000000..67dc3e2 --- /dev/null +++ b/3rdparty/SDL/src/video/riscos/SDL_riscostask.c @@ -0,0 +1,350 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* + This file added by Alan Buckley (alan_baa@hotmail.com) to support RISC OS + 26 March 2003 + + File includes routines for: + Setting up as a WIMP Task + Reading information about the current desktop + Storing information before a switch to full screen + Restoring desktop after switching to full screen +*/ + +#include "kernel.h" +#include "swis.h" + +#include "SDL_stdinc.h" +#include "SDL_riscostask.h" + +#if !SDL_THREADS_DISABLED +#include <pthread.h> +pthread_t main_thread; +#endif + +/* RISC OS variables */ + +static int task_handle = 0; +static int wimp_version = 0; + +/* RISC OS variables to help compatability with certain programs */ +int riscos_backbuffer = 0; /* Create a back buffer in system memory for full screen mode */ +int riscos_closeaction = 1; /* Close icon action */ + +static int stored_mode = -1; /* -1 when in desktop, mode number or pointer when full screen */ + +extern int mouseInWindow; /* Mouse is in WIMP window */ + +/* Local function */ + +static int RISCOS_GetTaskName(char *task_name, size_t maxlen); + +/* Uncomment next line to copy mode changes/restores to stderr */ +/* #define DUMP_MODE */ +#ifdef DUMP_MODE +#include "stdio.h" +static void dump_mode() +{ + fprintf(stderr, "mode %d\n", stored_mode); + if (stored_mode < -1 || stored_mode >= 256) + { + int blockSize = 0; + int *storeBlock = (int *)stored_mode; + + while(blockSize < 5 || storeBlock[blockSize] != -1) + { + fprintf(stderr, " %d\n", storeBlock[blockSize++]); + } + } +} +#endif + +/****************************************************************** + + Initialise as RISC OS Wimp task + +*******************************************************************/ + +int RISCOS_InitTask() +{ + char task_name[32]; + _kernel_swi_regs regs; + int messages[4]; + + if (RISCOS_GetTaskName(task_name, SDL_arraysize(task_name)) == 0) return 0; + + messages[0] = 9; /* Palette changed */ + messages[1] = 0x400c1; /* Mode changed */ + messages[2] = 8; /* Pre quit */ + messages[2] = 0; + + regs.r[0] = (unsigned int)360; /* Minimum version 3.6 */ + regs.r[1] = (unsigned int)0x4b534154; + regs.r[2] = (unsigned int)task_name; + regs.r[3] = (unsigned int)messages; + + if (_kernel_swi(Wimp_Initialise, ®s, ®s) == 0) + { + wimp_version = regs.r[0]; + task_handle = regs.r[1]; + return 1; + } + +#if !SDL_THREADS_DISABLED + main_thread = pthread_self(); +#endif + + return 0; +} + +/********************************************************************* + + Close down application on exit. + +**********************************************************************/ + +void RISCOS_ExitTask() +{ + _kernel_swi_regs regs; + + if (stored_mode == -1) + { + /* Ensure cursor is put back to standard pointer shape if + we have been running in a window */ + _kernel_osbyte(106,1,0); + } + + /* Ensure we end up back in the wimp */ + RISCOS_RestoreWimpMode(); + + /* Neatly exit the task */ + regs.r[0] = task_handle; + regs.r[1] = (unsigned int)0x4b534154; + _kernel_swi(Wimp_CloseDown, ®s, ®s); + task_handle = 0; +} + +/************************************************************************** + + Get the name of the task for the desktop. + + Param: task_name - name of task 32 characters. + + Returns: 1 is successful, otherwise 0 + + Notes: Works by getting using OS_GetEnv to get the command line + used to run the program and then parsing a name from it + as follows. + + 1. Use name after final period if not !RunImage + 2. If name is !RunImage then process item before the period + in front of !RunImage. + 3. If directory name use that + 4. if in form <XXX$Dir> use the XXX. + + Finally once this value has been retrieved use it unless + there is a variable set up in the form SDL$<name>$TaskName + in which case the value of this variable will be used. + + Now also gets other RISC OS configuration varibles + SDL$<name>$BackBuffer - set to 1 to use a system memory backbuffer in fullscreen mode + so updates wait until a call to SDL_UpdateRects. (default 0) + This is required for programmes where they have assumed this is + always the case which is contrary to the documentation. + SDL$<name>$CloseAction + 0 Don't show close icon + 1 Show close icon + +***************************************************************************/ + +int RISCOS_GetTaskName(char *task_name, size_t maxlen) +{ + _kernel_swi_regs regs; + + task_name[0] = 0; + + /* Figure out a sensible task name */ + if (_kernel_swi(OS_GetEnv, ®s, ®s) == 0) + { + char *command_line = (char *)regs.r[0]; + size_t len = SDL_strlen(command_line)+1; + char *buffer = SDL_stack_alloc(char, len); + char *env_var; + char *p; + + SDL_strlcpy(buffer, command_line, len); + p = SDL_strchr(buffer, ' '); + if (p) *p = 0; + p = SDL_strrchr(buffer, '.'); + if (p == 0) p = buffer; + if (stricmp(p+1,"!RunImage") == 0) + { + *p = 0; + p = SDL_strrchr(buffer, '.'); + if (p == 0) p = buffer; + } + if (*p == '.') p++; + if (*p == '!') p++; /* Skip "!" at beginning of application directories */ + + if (*p == '<') + { + // Probably in the form <appname$Dir> + char *q = SDL_strchr(p, '$'); + if (q == 0) q = SDL_strchr(p,'>'); /* Use variable name if not */ + if (q) *q = 0; + p++; /* Move over the < */ + } + + if (*p) + { + /* Read variables that effect the RISC OS SDL engine for this task */ + len = SDL_strlen(p) + 18; /* 18 is larger than the biggest variable name */ + env_var = SDL_stack_alloc(char, len); + if (env_var) + { + char *env_val; + + /* See if a variable of form SDL$<dirname>$TaskName exists */ + + SDL_strlcpy(env_var, "SDL$", len); + SDL_strlcat(env_var, p, len); + SDL_strlcat(env_var, "$TaskName", len); + + env_val = SDL_getenv(env_var); + if (env_val) SDL_strlcpy(task_name, env_val, maxlen); + + SDL_strlcpy(env_var, "SDL$", len); + SDL_strlcat(env_var, p, len); + SDL_strlcat(env_var, "$BackBuffer", len); + + env_val = SDL_getenv(env_var); + if (env_val) riscos_backbuffer = atoi(env_val); + + SDL_strlcpy(env_var, "SDL$", len); + SDL_strlcat(env_var, p, len); + SDL_strlcat(env_var, "$CloseAction", len); + + env_val = SDL_getenv(env_var); + if (env_val && SDL_strcmp(env_val,"0") == 0) riscos_closeaction = 0; + + SDL_stack_free(env_var); + } + + if (!*task_name) SDL_strlcpy(task_name, p, maxlen); + } + + SDL_stack_free(buffer); + } + + if (task_name[0] == 0) SDL_strlcpy(task_name, "SDL Task", maxlen); + + return 1; +} + +/***************************************************************** + + Store the current desktop screen mode if we are in the desktop. + +******************************************************************/ + +void RISCOS_StoreWimpMode() +{ + _kernel_swi_regs regs; + + /* Don't store if in full screen mode */ + if (stored_mode != -1) return; + + regs.r[0] = 1; + _kernel_swi(OS_ScreenMode, ®s, ®s); + if (regs.r[1] >= 0 && regs.r[1] < 256) stored_mode = regs.r[1]; + else + { + int blockSize = 0; + int *retBlock = (int *)regs.r[1]; + int *storeBlock; + int j; + + while(blockSize < 5 || retBlock[blockSize] != -1) blockSize++; + blockSize++; + storeBlock = (int *)SDL_malloc(blockSize * sizeof(int)); + retBlock = (int *)regs.r[1]; + for ( j = 0; j < blockSize; j++) + storeBlock[j] = retBlock[j]; + + stored_mode = (int)storeBlock; + } +#if DUMP_MODE + fprintf(stderr, "Stored "); dump_mode(); +#endif +} + +/***************************************************************** + + Restore desktop screen mode if we are in full screen mode. + +*****************************************************************/ + +void RISCOS_RestoreWimpMode() +{ + _kernel_swi_regs regs; + + /* Only need to restore if we are in full screen mode */ + if (stored_mode == -1) return; + +#if DUMP_MODE + fprintf(stderr, "Restored"); dump_mode(); +#endif + + regs.r[0] = stored_mode; + _kernel_swi(Wimp_SetMode, ®s, ®s); + if (stored_mode < 0 || stored_mode > 256) + { + SDL_free((int *)stored_mode); + } + stored_mode = -1; + + /* Flush keyboard buffer to dump the keystrokes we've already polled */ + regs.r[0] = 21; + regs.r[1] = 0; /* Keyboard buffer number */ + _kernel_swi(OS_Byte, ®s, ®s); + + mouseInWindow = 0; + +} + +/********************************************************************* + + Get version of Wimp running when task was initialised. + +*********************************************************************/ + +int RISCOS_GetWimpVersion() +{ + return wimp_version; +} + +int RISCOS_GetTaskHandle() +{ + return task_handle; +} diff --git a/3rdparty/SDL/src/video/riscos/SDL_riscostask.h b/3rdparty/SDL/src/video/riscos/SDL_riscostask.h new file mode 100644 index 0000000..5744afa --- /dev/null +++ b/3rdparty/SDL/src/video/riscos/SDL_riscostask.h @@ -0,0 +1,39 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* + This file added by Alan Buckley (alan_baa@hotmail.com) to support RISC OS + 26 March 2003 +*/ + +/* Task initialisation/Clean up */ + +extern int RISCOS_InitTask(); +extern void RISCOS_ExitTask(); +extern int RISCOS_GetWimpVersion(); +extern int RISCOS_GetTaskHandle(); + + +/* Wimp mode saveing/restoring */ +extern void RISCOS_StoreWimpMode(); +extern void RISCOS_RestoreWimpMode(); diff --git a/3rdparty/SDL/src/video/riscos/SDL_riscosvideo.c b/3rdparty/SDL/src/video/riscos/SDL_riscosvideo.c new file mode 100644 index 0000000..bae5e37 --- /dev/null +++ b/3rdparty/SDL/src/video/riscos/SDL_riscosvideo.c @@ -0,0 +1,316 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* + File added by Alan Buckley (alan_baa@hotmail.com) for RISC OS compatability + 23 March 2003 + + Implements RISC OS display device management. + Routines for full screen and wimp modes are split + into other source files. +*/ + +#include "SDL_video.h" +#include "SDL_mouse.h" +#include "SDL_syswm.h" +#include "../SDL_sysvideo.h" +#include "../SDL_pixels_c.h" +#include "../../events/SDL_events_c.h" + +#include "SDL_riscostask.h" +#include "SDL_riscosvideo.h" +#include "SDL_riscosevents_c.h" +#include "SDL_riscosmouse_c.h" + +#include "kernel.h" +#include "swis.h" + +#define RISCOSVID_DRIVER_NAME "riscos" + +/* Initialization/Query functions */ +static int RISCOS_VideoInit(_THIS, SDL_PixelFormat *vformat); +static void RISCOS_VideoQuit(_THIS); + +static SDL_Rect **RISCOS_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags); +static SDL_Surface *RISCOS_SetVideoMode(_THIS, SDL_Surface *current, int width, int height, int bpp, Uint32 flags); + +int RISCOS_GetWmInfo(_THIS, SDL_SysWMinfo *info); + +int RISCOS_ToggleFullScreen(_THIS, int fullscreen); +/* Mouse checking */ +void RISCOS_CheckMouseMode(_THIS); +extern SDL_GrabMode RISCOS_GrabInput(_THIS, SDL_GrabMode mode); + +/* Fullscreen mode functions */ +extern SDL_Surface *FULLSCREEN_SetVideoMode(_THIS, SDL_Surface *current, int width, int height, int bpp, Uint32 flags); +extern void FULLSCREEN_BuildModeList(_THIS); +extern void FULLSCREEN_SetDeviceMode(_THIS); +extern int FULLSCREEN_ToggleFromWimp(_THIS); + +/* Wimp mode functions */ +extern SDL_Surface *WIMP_SetVideoMode(_THIS, SDL_Surface *current, int width, int height, int bpp, Uint32 flags); +extern void WIMP_DeleteWindow(_THIS); +extern int WIMP_ToggleFromFullScreen(_THIS); + +/* Hardware surface functions - common to WIMP and FULLSCREEN */ +static int RISCOS_AllocHWSurface(_THIS, SDL_Surface *surface); +static int RISCOS_LockHWSurface(_THIS, SDL_Surface *surface); +static void RISCOS_UnlockHWSurface(_THIS, SDL_Surface *surface); +static void RISCOS_FreeHWSurface(_THIS, SDL_Surface *surface); + +/* RISC OS driver bootstrap functions */ + +static int RISCOS_Available(void) +{ + return(1); +} + +static void RISCOS_DeleteDevice(SDL_VideoDevice *device) +{ + SDL_free(device->hidden); + SDL_free(device); +} + +static SDL_VideoDevice *RISCOS_CreateDevice(int devindex) +{ + SDL_VideoDevice *device; + + /* Initialize all variables that we clean on shutdown */ + device = (SDL_VideoDevice *)SDL_malloc(sizeof(SDL_VideoDevice)); + if ( device ) { + SDL_memset(device, 0, (sizeof *device)); + device->hidden = (struct SDL_PrivateVideoData *) + SDL_malloc((sizeof *device->hidden)); + } + if ( (device == NULL) || (device->hidden == NULL) ) { + SDL_OutOfMemory(); + if ( device ) { + SDL_free(device); + } + return(0); + } + SDL_memset(device->hidden, 0, (sizeof *device->hidden)); + + /* Set the function pointers */ + device->VideoInit = RISCOS_VideoInit; + device->VideoQuit = RISCOS_VideoQuit; + + device->ListModes = RISCOS_ListModes; + device->SetVideoMode = RISCOS_SetVideoMode; + device->CreateYUVOverlay = NULL; + device->AllocHWSurface = RISCOS_AllocHWSurface; + device->CheckHWBlit = NULL; + device->FillHWRect = NULL; + device->SetHWColorKey = NULL; + device->SetHWAlpha = NULL; + device->LockHWSurface = RISCOS_LockHWSurface; + device->UnlockHWSurface = RISCOS_UnlockHWSurface; + device->FreeHWSurface = RISCOS_FreeHWSurface; + + device->FreeWMCursor = RISCOS_FreeWMCursor; + device->CreateWMCursor = RISCOS_CreateWMCursor; + device->CheckMouseMode = RISCOS_CheckMouseMode; + device->GrabInput = RISCOS_GrabInput; + + device->InitOSKeymap = RISCOS_InitOSKeymap; + + device->GetWMInfo = RISCOS_GetWmInfo; + + device->free = RISCOS_DeleteDevice; + +/* Can't get Toggle screen to work if program starts up in Full screen mode so + disable it here and re-enable it when a wimp screen is chosen */ + device->ToggleFullScreen = NULL; /*RISCOS_ToggleFullScreen;*/ + + /* Set other entries for fullscreen mode */ + FULLSCREEN_SetDeviceMode(device); + + /* Mouse pointer needs to use the WIMP ShowCursor version so + that it doesn't modify the pointer until the SDL Window is + entered or the application goes full screen */ + device->ShowWMCursor = WIMP_ShowWMCursor; + + return device; +} + +VideoBootStrap RISCOS_bootstrap = { + RISCOSVID_DRIVER_NAME, "RISC OS video driver", + RISCOS_Available, RISCOS_CreateDevice +}; + + +int RISCOS_VideoInit(_THIS, SDL_PixelFormat *vformat) +{ + _kernel_swi_regs regs; + int vars[4], vals[3]; + + if (RISCOS_InitTask() == 0) + { + SDL_SetError("Unable to start task"); + return 0; + } + + vars[0] = 9; /* Log base 2 bpp */ + vars[1] = 11; /* XWndLimit - num x pixels -1 */ + vars[2] = 12; /* YWndLimit - num y pixels -1 */ + vars[3] = -1; /* Terminate list */ + regs.r[0] = (int)vars; + regs.r[1] = (int)vals; + + _kernel_swi(OS_ReadVduVariables, ®s, ®s); + vformat->BitsPerPixel = (1 << vals[0]); + + /* Determine the current screen size */ + this->info.current_w = vals[1] + 1; + this->info.current_h = vals[2] + 1; + + /* Minimum bpp for SDL is 8 */ + if (vformat->BitsPerPixel < 8) vformat->BitsPerPixel = 8; + + + switch (vformat->BitsPerPixel) + { + case 15: + case 16: + vformat->Bmask = 0x00007c00; + vformat->Gmask = 0x000003e0; + vformat->Rmask = 0x0000001f; + vformat->BitsPerPixel = 16; /* SDL wants actual number of bits used */ + vformat->BytesPerPixel = 2; + break; + + case 24: + case 32: + vformat->Bmask = 0x00ff0000; + vformat->Gmask = 0x0000ff00; + vformat->Rmask = 0x000000ff; + vformat->BytesPerPixel = 4; + break; + + default: + vformat->Bmask = 0; + vformat->Gmask = 0; + vformat->Rmask = 0; + vformat->BytesPerPixel = 1; + break; + } + + /* Fill in some window manager capabilities */ + this->info.wm_available = 1; + + /* We're done! */ + return(0); +} + +/* Note: If we are terminated, this could be called in the middle of + another SDL video routine -- notably UpdateRects. +*/ +void RISCOS_VideoQuit(_THIS) +{ + RISCOS_ExitTask(); + + if (this->hidden->alloc_bank) SDL_free(this->hidden->alloc_bank); + this->hidden->alloc_bank = 0; +} + + +SDL_Rect **RISCOS_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags) +{ + if (flags & SDL_FULLSCREEN) + { + /* Build mode list when first required. */ + if (SDL_nummodes[0] == 0) FULLSCREEN_BuildModeList(this); + + return(SDL_modelist[((format->BitsPerPixel+7)/8)-1]); + } else + return (SDL_Rect **)-1; +} + + +/* Set up video mode */ +SDL_Surface *RISCOS_SetVideoMode(_THIS, SDL_Surface *current, + int width, int height, int bpp, Uint32 flags) +{ + if (flags & SDL_FULLSCREEN) + { + RISCOS_StoreWimpMode(); + /* Dump wimp window on switch to full screen */ + if (this->hidden->window_handle) WIMP_DeleteWindow(this); + + return FULLSCREEN_SetVideoMode(this, current, width, height, bpp, flags); + } else + { + RISCOS_RestoreWimpMode(); + return WIMP_SetVideoMode(this, current, width, height, bpp, flags); + } +} + + +/* We don't actually allow hardware surfaces other than the main one */ +static int RISCOS_AllocHWSurface(_THIS, SDL_Surface *surface) +{ + return(-1); +} +static void RISCOS_FreeHWSurface(_THIS, SDL_Surface *surface) +{ + return; +} + +/* We need to wait for vertical retrace on page flipped displays */ +static int RISCOS_LockHWSurface(_THIS, SDL_Surface *surface) +{ + return(0); +} + +static void RISCOS_UnlockHWSurface(_THIS, SDL_Surface *surface) +{ + return; +} + + +int RISCOS_GetWmInfo(_THIS, SDL_SysWMinfo *info) +{ + SDL_VERSION(&(info->version)); + info->wimpVersion = RISCOS_GetWimpVersion(); + info->taskHandle = RISCOS_GetTaskHandle(); + info->window = this->hidden->window_handle; + + return 1; +} +/* Toggle full screen mode. + Returns 1 if successful otherwise 0 +*/ + +int RISCOS_ToggleFullScreen(_THIS, int fullscreen) +{ + if (fullscreen) + { + return FULLSCREEN_ToggleFromWimp(this); + } else + { + return WIMP_ToggleFromFullScreen(this); + } + + return 0; +} + diff --git a/3rdparty/SDL/src/video/riscos/SDL_riscosvideo.h b/3rdparty/SDL/src/video/riscos/SDL_riscosvideo.h new file mode 100644 index 0000000..7c717ad --- /dev/null +++ b/3rdparty/SDL/src/video/riscos/SDL_riscosvideo.h @@ -0,0 +1,62 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#ifndef _SDL_riscosvideo_h +#define _SDL_riscosvideo_h + +#include "SDL_mouse.h" +#include "SDL_mutex.h" +#include "../SDL_sysvideo.h" + +/* Hidden "this" pointer for the video functions */ +#define _THIS SDL_VideoDevice *this + + +/* Private display data */ + +struct SDL_PrivateVideoData { + unsigned char *bank[2]; + int current_bank; + unsigned char *alloc_bank; + int height; + int xeig; + int yeig; + int screen_bpp; + int screen_width; + int screen_height; + char *pixtrans; + + /* Wimp variables */ + unsigned int window_handle; + char title[256]; + +#define NUM_MODELISTS 4 /* 8, 16, 24, and 32 bits-per-pixel */ + int SDL_nummodes[NUM_MODELISTS]; + SDL_Rect **SDL_modelist[NUM_MODELISTS]; +}; + +/* Old variable names */ +#define SDL_nummodes (this->hidden->SDL_nummodes) +#define SDL_modelist (this->hidden->SDL_modelist) + +#endif /* _SDL_risosvideo_h */ diff --git a/3rdparty/SDL/src/video/riscos/SDL_wimppoll.c b/3rdparty/SDL/src/video/riscos/SDL_wimppoll.c new file mode 100644 index 0000000..4999664 --- /dev/null +++ b/3rdparty/SDL/src/video/riscos/SDL_wimppoll.c @@ -0,0 +1,330 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* + File added by Alan Buckley (alan_baa@hotmail.com) for RISC OS compatability + 27 March 2003 + + Implements Pumping of events and WIMP polling +*/ + +#include "SDL.h" +#include "SDL_syswm.h" +#include "../../events/SDL_sysevents.h" +#include "../../events/SDL_events_c.h" +#include "SDL_riscosvideo.h" +#include "SDL_riscosevents_c.h" +#include "SDL_riscosmouse_c.h" +#include "../../timer/SDL_timer_c.h" + +#include "memory.h" +#include "stdlib.h" +#include "ctype.h" + +#include "kernel.h" +#include "swis.h" +#include "unixlib/os.h" + +#if !SDL_THREADS_DISABLED +#include <pthread.h> +#endif + +/* Local functions */ +void WIMP_Poll(_THIS, int waitTime); +void WIMP_SetFocus(int win); + +/* SDL_riscossprite functions */ +void WIMP_PlotSprite(_THIS, int x, int y); +void WIMP_ModeChanged(_THIS); +void WIMP_PaletteChanged(_THIS); + + +extern void WIMP_PollMouse(_THIS); +extern void RISCOS_PollKeyboard(); + +#if SDL_THREADS_DISABLED +/* Timer running function */ +extern void RISCOS_CheckTimer(); +#else +extern int riscos_using_threads; +#endif + +/* Mouse cursor handling */ +extern void WIMP_ReshowCursor(_THIS); +extern void WIMP_RestoreWimpCursor(); + +int hasFocus = 0; +int mouseInWindow = 0; + +/* Flag to ensure window is correct size after a mode change */ +static int resizeOnOpen = 0; + +void WIMP_PumpEvents(_THIS) +{ + WIMP_Poll(this, 0); + if (hasFocus) RISCOS_PollKeyboard(); + if (mouseInWindow) WIMP_PollMouse(this); +#if SDL_THREADS_DISABLED + if (SDL_timer_running) RISCOS_CheckTimer(); +#endif +} + + +void WIMP_Poll(_THIS, int waitTime) +{ + _kernel_swi_regs regs; + int message[64]; + unsigned int code; + int pollMask = 0; + int doPoll = 1; + int sysEvent; + int sdlWindow = this->hidden->window_handle; + + if (this->PumpEvents != WIMP_PumpEvents) return; + + if (waitTime > 0) + { + _kernel_swi(OS_ReadMonotonicTime, ®s, ®s); + waitTime += regs.r[0]; + } + + while (doPoll) + { +#if !SDL_THREADS_DISABLED + /* Stop thread callbacks while program is paged out */ + if (riscos_using_threads) __pthread_stop_ticker(); +#endif + + if (waitTime <= 0) + { + regs.r[0] = pollMask; /* Poll Mask */ + /* For no wait time mask out null event so we wait until something happens */ + if (waitTime < 0) regs.r[0] |= 1; + regs.r[1] = (int)message; + _kernel_swi(Wimp_Poll, ®s, ®s); + } else + { + regs.r[0] = pollMask; + regs.r[1] = (int)message; + regs.r[2] = waitTime; + _kernel_swi(Wimp_PollIdle, ®s, ®s); + } + + /* Flag to specify if we post a SDL_SysWMEvent */ + sysEvent = 0; + + code = (unsigned int)regs.r[0]; + + switch(code) + { + case 0: /* Null Event - drop out for standard processing*/ + doPoll = 0; + break; + + case 1: /* Redraw window */ + _kernel_swi(Wimp_RedrawWindow, ®s,®s); + if (message[0] == sdlWindow) + { + while (regs.r[0]) + { + WIMP_PlotSprite(this, message[1], message[2]); + _kernel_swi(Wimp_GetRectangle, ®s, ®s); + } + } else + { + /* TODO: Currently we just eat them - we may need to pass them on */ + while (regs.r[0]) + { + _kernel_swi(Wimp_GetRectangle, ®s, ®s); + } + } + break; + + case 2: /* Open window */ + if ( resizeOnOpen && message[0] == sdlWindow) + { + /* Ensure window is correct size */ + resizeOnOpen = 0; + message[3] = message[1] + (this->screen->w << this->hidden->xeig); + message[4] = message[2] + (this->screen->h << this->hidden->yeig); + } + _kernel_swi(Wimp_OpenWindow, ®s, ®s); + break; + + case 3: /* Close window */ + if (message[0] == sdlWindow) + { + /* Documentation makes it looks as if the following line is correct: + ** if (SDL_PrivateQuit() == 1) _kernel_swi(Wimp_CloseWindow, ®s, ®s); + ** However some programs don't process this message and so sit there invisibly + ** in the background so I just post the quit message and hope the application + ** does the correct thing. + */ + SDL_PrivateQuit(); + } else + sysEvent = 1; + doPoll = 0; + break; + + case 4: /* Pointer_Leaving_Window */ + if (message[0] == sdlWindow) + { + mouseInWindow = 0; + //TODO: Lose buttons / dragging + /* Reset to default pointer */ + WIMP_RestoreWimpCursor(); + SDL_PrivateAppActive(0, SDL_APPMOUSEFOCUS); + } else + sysEvent = 1; + break; + + case 5: /* Pointer_Entering_Window */ + if (message[0] == sdlWindow) + { + mouseInWindow = 1; + WIMP_ReshowCursor(this); + SDL_PrivateAppActive(1, SDL_APPMOUSEFOCUS); + } else sysEvent = 1; + break; + + case 6: /* Mouse_Click */ + if (hasFocus == 0) + { + /* First click gives focus if it's not a menu */ + /* we only count non-menu clicks on a window that has the focus */ + WIMP_SetFocus(message[3]); + } else + doPoll = 0; // So PollMouse gets a chance to pick it up + break; + + case 7: /* User_Drag_Box - Used for mouse release */ + //TODO: May need to implement this in the future + sysEvent = 1; + break; + + case 8: /* Keypressed */ + doPoll = 0; /* PollKeyboard should pick it up */ + if (message[0] != sdlWindow) sysEvent = 1; + /*TODO: May want to always pass F12 etc to the wimp + { + regs.r[0] = message[6]; + _kernel_swi(Wimp_ProcessKey, ®s, ®s); + } + */ + break; + + case 11: /* Lose Caret */ + hasFocus = 0; + if (message[0] == sdlWindow) SDL_PrivateAppActive(0, SDL_APPINPUTFOCUS); + else sysEvent = 1; + break; + + case 12: /* Gain Caret */ + hasFocus = 1; + if (message[0] == sdlWindow) SDL_PrivateAppActive(1, SDL_APPINPUTFOCUS); + else sysEvent = 1; + break; + + case 17: + case 18: + sysEvent = 1; /* All messages are passed on */ + + switch(message[4]) + { + case 0: /* Quit Event */ + /* No choice - have to quit */ + SDL_Quit(); + exit(0); + break; + + case 8: /* Pre Quit */ + SDL_PrivateQuit(); + break; + + case 0x400c1: /* Mode change */ + WIMP_ModeChanged(this); + resizeOnOpen = 1; + break; + + case 9: /* Palette changed */ + WIMP_PaletteChanged(this); + break; + } + break; + + default: + /* Pass unknown events on */ + sysEvent = 1; + break; + } + + if (sysEvent) + { + SDL_SysWMmsg wmmsg; + + SDL_VERSION(&wmmsg.version); + wmmsg.eventCode = code; + SDL_memcpy(wmmsg.pollBlock, message, 64 * sizeof(int)); + + /* Fall out of polling loop if message is successfully posted */ + if (SDL_PrivateSysWMEvent(&wmmsg)) doPoll = 0; + } +#if !SDL_THREADS_DISABLED + if (riscos_using_threads) + { + /* Restart ticker here so other thread can not interfere + with the Redraw processing */ + if (riscos_using_threads) __pthread_start_ticker(); + /* Give other threads a better chance of running */ + pthread_yield(); + } +#endif + } +} + +/* Set focus to specified window */ +void WIMP_SetFocus(int win) +{ + _kernel_swi_regs regs; + + regs.r[0] = win; + regs.r[1] = -1; /* Icon handle */ + regs.r[2] = 0; /* X-offset we just put it at position 0 */ + regs.r[3] = 0; /* Y-offset as above */ + regs.r[4] = 1 << 25; /* Caret is invisible */ + regs.r[5] = 0; /* index into string */ + + _kernel_swi(Wimp_SetCaretPosition, ®s, ®s); +} + +/** Run background task while in a sleep command */ +void RISCOS_BackgroundTasks(void) +{ + if (current_video && current_video->hidden->window_handle) + { + WIMP_Poll(current_video, 0); + } +#if SDL_THREADS_DISABLED + if (SDL_timer_running) RISCOS_CheckTimer(); +#endif +} diff --git a/3rdparty/SDL/src/video/riscos/SDL_wimpvideo.c b/3rdparty/SDL/src/video/riscos/SDL_wimpvideo.c new file mode 100644 index 0000000..0f9c545 --- /dev/null +++ b/3rdparty/SDL/src/video/riscos/SDL_wimpvideo.c @@ -0,0 +1,501 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* + File added by Alan Buckley (alan_baa@hotmail.com) for RISC OS compatability + 27 March 2003 + + Implements RISC OS Wimp display. +*/ + +#include "SDL_video.h" +#include "SDL_mouse.h" +#include "../SDL_sysvideo.h" +#include "../SDL_pixels_c.h" +#include "../../events/SDL_events_c.h" + +#include "SDL_riscostask.h" +#include "SDL_riscosvideo.h" +#include "SDL_riscosevents_c.h" +#include "SDL_riscosmouse_c.h" + +#include "kernel.h" +#include "swis.h" + +/* Initialization/Query functions */ +SDL_Rect **WIMP_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags); +SDL_Surface *WIMP_SetVideoMode(_THIS, SDL_Surface *current, int width, int height, int bpp, Uint32 flags); +int WIMP_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors); +void WIMP_SetWMCaption(_THIS, const char *title, const char *icon); + + +extern unsigned char *WIMP_CreateBuffer(int width, int height, int bpp); +extern void WIMP_PumpEvents(_THIS); +extern void WIMP_PlotSprite(_THIS, int x, int y); +extern void WIMP_SetupPlotInfo(_THIS); +extern void WIMP_SetFocus(int win); + +/* etc. */ +static void WIMP_UpdateRects(_THIS, int numrects, SDL_Rect *rects); + +/* RISC OS Wimp handling helpers */ +void WIMP_ReadModeInfo(_THIS); +unsigned int WIMP_SetupWindow(_THIS, SDL_Surface *surface); +void WIMP_SetDeviceMode(_THIS); +void WIMP_DeleteWindow(_THIS); + +/* FULLSCREEN function required for wimp/fullscreen toggling */ +extern int FULLSCREEN_SetMode(int width, int height, int bpp); + +/* Currently need to set this up here as it only works if you + start up in a Wimp mode */ +extern int RISCOS_ToggleFullScreen(_THIS, int fullscreen); + +extern int riscos_backbuffer; +extern int mouseInWindow; +extern int riscos_closeaction; + +/* Following needed to ensure window is shown immediately */ +extern int hasFocus; +extern void WIMP_Poll(_THIS, int waitTime); + +SDL_Surface *WIMP_SetVideoMode(_THIS, SDL_Surface *current, + int width, int height, int bpp, Uint32 flags) +{ + Uint32 Rmask = 0; + Uint32 Gmask = 0; + Uint32 Bmask = 0; + char *buffer = NULL; + int bytesPerPixel = 1; + + /* Don't support double buffering in Wimp mode */ + flags &= ~SDL_DOUBLEBUF; + flags &= ~SDL_HWSURFACE; + + switch(bpp) + { + case 8: + /* Emulated palette using ColourTrans */ + flags |= SDL_HWPALETTE; + break; + + case 15: + case 16: + Bmask = 0x00007c00; + Gmask = 0x000003e0; + Rmask = 0x0000001f; + bytesPerPixel = 2; + break; + + case 32: + Bmask = 0x00ff0000; + Gmask = 0x0000ff00; + Rmask = 0x000000ff; + bytesPerPixel = 4; + break; + + default: + SDL_SetError("Pixel depth not supported"); + return NULL; + break; + } + +/* printf("Setting mode %dx%d\n", width, height);*/ + + /* Allocate the new pixel format for the screen */ + if ( ! SDL_ReallocFormat(current, bpp, Rmask, Gmask, Bmask, 0) ) { + SDL_SetError("Couldn't allocate new pixel format for requested mode"); + return(NULL); + } + + /* Set up the new mode framebuffer */ + current->w = width; + this->hidden->height = current->h = height; + + if (bpp == 15) bpp = 16; + buffer = WIMP_CreateBuffer(width, height, bpp); + if (buffer == NULL) + { + SDL_SetError("Couldn't create sprite for video memory"); + return (NULL); + } + + this->hidden->bank[0] = buffer + 60; /* Start of sprite data */ + if (bpp == 8) this->hidden->bank[0] += 2048; /* 8bpp sprite have palette first */ + + this->hidden->bank[1] = buffer; /* Start of buffer */ + + /* Remember sprite buffer so it can be freed later */ + if (this->hidden->alloc_bank) SDL_free(this->hidden->alloc_bank); + this->hidden->alloc_bank = buffer; + + current->pitch = width * bytesPerPixel; + if ((current->pitch & 3)) + { + /* Sprites are 32bit word aligned */ + current->pitch += (4 - (current->pitch & 3)); + } + + current->flags = flags | SDL_PREALLOC; + + WIMP_ReadModeInfo(this); + + SDL_memset(this->hidden->bank[0], 0, height * current->pitch); + + this->hidden->current_bank = 0; + current->pixels = this->hidden->bank[0]; + + + if (WIMP_SetupWindow(this, current) == 0) + { + SDL_SetError("Unable to create window to display surface"); + return NULL; + } + + /* Reset device functions for the wimp */ + WIMP_SetDeviceMode(this); + + /* Needs to set up plot info after window has been created */ + /* Not sure why, but plots don't work if I do it earlier */ + WIMP_SetupPlotInfo(this); + + /* Poll until window is shown */ + { + /* We wait until it gets the focus, but give up after 5 seconds + in case the focus is prevented in any way. + */ + Uint32 now = SDL_GetTicks(); + while (!hasFocus && SDL_GetTicks() - now < 5000) + { + WIMP_Poll(this, 0); + } + } + + /* We're done */ + return(current); +} + + +void WIMP_ReadModeInfo(_THIS) +{ + _kernel_swi_regs regs; + int vars[6]; + int vals[5]; + + vars[0] = 4; /* XEig */ + vars[1] = 5; /* YEig */ + vars[2] = 9; /* Log base 2 bpp */ + vars[3] = 11; /* Screen Width - 1 */ + vars[4] = 12; /* Screen Depth - 1 */ + vars[5] = -1; /* Terminate list */ + + regs.r[0] = (int)vars; + regs.r[1] = (int)vals; + _kernel_swi(OS_ReadVduVariables, ®s, ®s); + this->hidden->xeig = vals[0]; + this->hidden->yeig = vals[1]; + this->hidden->screen_bpp = 1 << vals[2]; + this->hidden->screen_width = vals[3] + 1; + this->hidden->screen_height = vals[4] + 1; +} + +/* Set device function to call the correct versions for running + in a wimp window */ + +void WIMP_SetDeviceMode(_THIS) +{ + if (this->UpdateRects == WIMP_UpdateRects) return; /* Already set up */ + + this->SetColors = WIMP_SetColors; + this->UpdateRects = WIMP_UpdateRects; + + this->FlipHWSurface = NULL; + + this->SetCaption = WIMP_SetWMCaption; + this->SetIcon = NULL; + this->IconifyWindow = NULL; + + this->ShowWMCursor = WIMP_ShowWMCursor; + this->WarpWMCursor = WIMP_WarpWMCursor; + + this->ToggleFullScreen = RISCOS_ToggleFullScreen; + + this->PumpEvents = WIMP_PumpEvents; +} + +/* Setup the Window to display the surface */ +unsigned int WIMP_SetupWindow(_THIS, SDL_Surface *surface) +{ + _kernel_swi_regs regs; + int window_data[23]; + int *window_block = window_data+1; + int x = (this->hidden->screen_width - surface->w) / 2; + int y = (this->hidden->screen_height - surface->h) / 2; + int xeig = this->hidden->xeig; + int yeig = this->hidden->yeig; + + mouseInWindow = 0; + + /* Always delete the window and recreate on a change */ + if (this->hidden->window_handle) WIMP_DeleteWindow(this); + + /* Setup window co-ordinates */ + window_block[0] = x << xeig; + window_block[1] = y << yeig; + window_block[2] = window_block[0] + (surface->w << xeig); + window_block[3] = window_block[1] + (surface->h << yeig); + + + window_block[4] = 0; /* Scroll offsets */ + window_block[5] = 0; + window_block[6] = -1; /* Open on top of window stack */ + + window_block[7] = 0x85040042; /* Window flags */ + if (riscos_closeaction != 0) window_block[7] |= 0x2000000; + + /* TODO: Take into account surface->flags */ + + window_block[8] = 0xff070207; /* Window colours */ + window_block[9] = 0x000c0103; + window_block[10] = 0; /* Work area minimum */ + window_block[11] = -surface->h << yeig; + window_block[12] = surface->w << xeig; /* Work area maximum */ + window_block[13] = 0; + window_block[14] = 0x2700013d; /* Title icon flags */ + window_block[15] = 0x00003000; /* Work area flags - Mouse click down reported */ + window_block[16] = 1; /* Sprite area control block pointer */ + window_block[17] = 0x00100010; /* Minimum window size (width & height) (16x16)*/ + window_block[18] = (int)this->hidden->title; /* Title data */ + window_block[19] = -1; + window_block[20] = 256; + window_block[21] = 0; /* Number of icons */ + + regs.r[1] = (unsigned int)(window_block); + + /* Create the window */ + if (_kernel_swi(Wimp_CreateWindow, ®s, ®s) == NULL) + { + this->hidden->window_handle = window_data[0] = regs.r[0]; + + /* Show the window on the screen */ + regs.r[1] = (unsigned int)window_data; + if (_kernel_swi(Wimp_OpenWindow, ®s, ®s) == NULL) + { + WIMP_SetFocus(this->hidden->window_handle); + } else + { + WIMP_DeleteWindow(this); + } + } + + return this->hidden->window_handle; +} + +/* Destroy the Window */ + +void WIMP_DeleteWindow(_THIS) +{ + _kernel_swi_regs regs; + regs.r[1] = (unsigned int)&(this->hidden->window_handle); + _kernel_swi(Wimp_DeleteWindow, ®s, ®s); + this->hidden->window_handle = 0; +} + + +void WIMP_UpdateRects(_THIS, int numrects, SDL_Rect *rects) +{ + _kernel_swi_regs regs; + int update_block[12]; + int xeig = this->hidden->xeig; + int yeig = this->hidden->yeig; + int j; + update_block[0] = this->hidden->window_handle; + + for (j = 0; j < numrects; j++) + { + update_block[1] = rects[j].x << xeig; /* Min X */ + update_block[4] = -(rects[j].y << yeig); + update_block[3] = update_block[1] + (rects[j].w << xeig); + update_block[2] = update_block[4] - (rects[j].h << yeig); + + regs.r[1] = (int)update_block; + /* Update window can fail if called before first poll */ + if (_kernel_swi(Wimp_UpdateWindow, ®s, ®s) == 0) + { + while (regs.r[0]) + { + WIMP_PlotSprite(this, update_block[1], update_block[2]); + _kernel_swi(Wimp_GetRectangle, ®s, ®s); + } + } + } +} + + +int WIMP_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors) +{ + unsigned int *pal = (unsigned int *)(this->hidden->bank[1]+60); + int j; + SDL_Rect update; + + pal += firstcolor*2; + for (j = 0; j < ncolors; j++) + { + *pal = (((unsigned int)colors->r) << 8) + + (((unsigned int)colors->g) << 16) + + (((unsigned int)colors->b) << 24); + pal[1] = *pal; + pal += 2; + colors++; + } + + WIMP_SetupPlotInfo(this); + + /* Need to refresh the window */ + update.x = 0; + update.y = 0; + update.w = SDL_VideoSurface->w; + update.h = SDL_VideoSurface->h; + WIMP_UpdateRects(this, 1, &update); + + return 1; +} + +void WIMP_SetWMCaption(_THIS, const char *title, const char *icon) +{ + _kernel_swi_regs regs; + + SDL_strlcpy(this->hidden->title, title, SDL_arraysize(this->hidden->title)); + + if (RISCOS_GetWimpVersion() < 380) + { + int block[6]; + + regs.r[1] = (int)block; + _kernel_swi(Wimp_GetCaretPosition, ®s, ®s); + if (block[0] == (int)this->hidden->window_handle) + { + regs.r[0] = -1; + _kernel_swi(Wimp_SetCaretPosition, ®s,®s); + } else + { + regs.r[0] = this->hidden->window_handle; + regs.r[1] = -1; + regs.r[2] = -1; + regs.r[3] = -1; + _kernel_swi(Wimp_SetCaretPosition, ®s,®s); + } + regs.r[0] = block[0]; + regs.r[1] = block[1]; + regs.r[2] = block[2]; + regs.r[3] = block[3]; + regs.r[4] = block[4]; + regs.r[5] = block[5]; + _kernel_swi(Wimp_SetCaretPosition, ®s,®s); + } else + { + regs.r[0] = this->hidden->window_handle; + regs.r[1] = 0x4b534154; /* "TASK" */ + regs.r[2] = 3; /* Redraw title */ + _kernel_swi(Wimp_ForceRedraw, ®s, ®s); + } +} + +void WIMP_RefreshDesktop(_THIS) +{ + int width = this->hidden->screen_width << this->hidden->xeig; + int height = this->hidden->screen_height << this->hidden->yeig; + _kernel_swi_regs regs; + regs.r[0] = -1; /* Whole screen */ + regs.r[1] = 0; + regs.r[2] = 0; + regs.r[3] = width; + regs.r[4] = height; + _kernel_swi(Wimp_ForceRedraw, ®s, ®s); +} + +/* Toggle to window from full screen */ +int WIMP_ToggleFromFullScreen(_THIS) +{ + int width = this->screen->w; + int height = this->screen->h; + int bpp = this->screen->format->BitsPerPixel; + char *buffer = NULL; + char *old_bank[2]; + char *old_alloc_bank; + + /* Ensure flags are OK */ + this->screen->flags &= ~(SDL_DOUBLEBUF|SDL_HWSURFACE); + + if (this->hidden->bank[0] == this->hidden->alloc_bank || riscos_backbuffer == 0) + { + /* Need to create a sprite for the screen and copy the data to it */ + char *data; + buffer = WIMP_CreateBuffer(width, height, bpp); + data = buffer + 60; /* Start of sprite data */ + if (bpp == 8) data += 2048; /* 8bpp sprite have palette first */ + + if (buffer == NULL) return 0; + SDL_memcpy(data, this->hidden->bank[0], width * height * this->screen->format->BytesPerPixel); + } + /* else We've switch to full screen before so we already have a sprite */ + + old_bank[0] = this->hidden->bank[0]; + old_bank[1] = this->hidden->bank[1]; + old_alloc_bank = this->hidden->alloc_bank; + + if (buffer != NULL) this->hidden->alloc_bank = buffer; + + this->hidden->bank[1] = this->hidden->alloc_bank; + this->hidden->bank[0] = this->hidden->bank[1] + 60; /* Start of sprite data */ + if (bpp == 8) this->hidden->bank[0] += 2048; /* 8bpp sprite have palette first */ + + this->hidden->current_bank = 0; + this->screen->pixels = this->hidden->bank[0]; + + RISCOS_RestoreWimpMode(); + WIMP_ReadModeInfo(this); + if (WIMP_SetupWindow(this, this->screen)) + { + WIMP_SetDeviceMode(this); + WIMP_SetupPlotInfo(this); + + if (riscos_backbuffer == 0) riscos_backbuffer = 1; + + if (buffer && old_alloc_bank) SDL_free(old_alloc_bank); + + return 1; + } else + { + /* Drop back to full screen mode on failure */ + this->hidden->bank[0] = old_bank[0]; + this->hidden->bank[1] = old_bank[1]; + this->hidden->alloc_bank = old_alloc_bank; + if (buffer) SDL_free(buffer); + + RISCOS_StoreWimpMode(); + FULLSCREEN_SetMode(width, height, bpp); + } + + return 0; +} diff --git a/3rdparty/SDL/src/video/svga/SDL_svgaevents.c b/3rdparty/SDL/src/video/svga/SDL_svgaevents.c new file mode 100644 index 0000000..107a702 --- /dev/null +++ b/3rdparty/SDL/src/video/svga/SDL_svgaevents.c @@ -0,0 +1,412 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* Handle the event stream, converting X11 events into SDL events */ + +#include <vga.h> +#include <vgamouse.h> +#include <vgakeyboard.h> +#if defined(__LINUX__) +#include <linux/kd.h> +#include <linux/keyboard.h> +#elif defined(__FREEBSD__) +#include <sys/kbio.h> +#else +#error You must choose your operating system here +#endif + +#include "../../events/SDL_sysevents.h" +#include "../../events/SDL_events_c.h" +#include "SDL_svgavideo.h" +#include "SDL_svgaevents_c.h" + +/* The translation tables from a console scancode to a SDL keysym */ +#if defined(linux) +#define NUM_VGAKEYMAPS (1<<KG_CAPSSHIFT) +static Uint16 vga_keymap[NUM_VGAKEYMAPS][NR_KEYS]; +#elif defined(__FREEBSD__) +/* FIXME: Free the keymap when we shut down the video mode */ +static keymap_t *vga_keymap = NULL; +#else +#error You must choose your operating system here +#endif +static SDLKey keymap[128]; +static SDL_keysym *TranslateKey(int scancode, SDL_keysym *keysym); + +/* Ugh, we have to duplicate the kernel's keysym mapping code... + Oh, it's not so bad. :-) + + FIXME: Add keyboard LED handling code + */ +#if defined(linux) +int SVGA_initkeymaps(int fd) +{ + struct kbentry entry; + int map, i; + + /* Load all the keysym mappings */ + for ( map=0; map<NUM_VGAKEYMAPS; ++map ) { + SDL_memset(vga_keymap[map], 0, NR_KEYS*sizeof(Uint16)); + for ( i=0; i<NR_KEYS; ++i ) { + entry.kb_table = map; + entry.kb_index = i; + if ( ioctl(fd, KDGKBENT, &entry) == 0 ) { + /* The "Enter" key is a special case */ + if ( entry.kb_value == K_ENTER ) { + entry.kb_value = K(KT_ASCII,13); + } + /* Handle numpad specially as well */ + if ( KTYP(entry.kb_value) == KT_PAD ) { + switch ( entry.kb_value ) { + case K_P0: + case K_P1: + case K_P2: + case K_P3: + case K_P4: + case K_P5: + case K_P6: + case K_P7: + case K_P8: + case K_P9: + vga_keymap[map][i]=entry.kb_value; + vga_keymap[map][i]+= '0'; + break; + case K_PPLUS: + vga_keymap[map][i]=K(KT_ASCII,'+'); + break; + case K_PMINUS: + vga_keymap[map][i]=K(KT_ASCII,'-'); + break; + case K_PSTAR: + vga_keymap[map][i]=K(KT_ASCII,'*'); + break; + case K_PSLASH: + vga_keymap[map][i]=K(KT_ASCII,'/'); + break; + case K_PENTER: + vga_keymap[map][i]=K(KT_ASCII,'\r'); + break; + case K_PCOMMA: + vga_keymap[map][i]=K(KT_ASCII,','); + break; + case K_PDOT: + vga_keymap[map][i]=K(KT_ASCII,'.'); + break; + default: + break; + } + } + /* Do the normal key translation */ + if ( (KTYP(entry.kb_value) == KT_LATIN) || + (KTYP(entry.kb_value) == KT_ASCII) || + (KTYP(entry.kb_value) == KT_LETTER) ) { + vga_keymap[map][i] = entry.kb_value; + } + } + } + } + return(0); +} +#elif defined(__FREEBSD__) +int SVGA_initkeymaps(int fd) +{ + vga_keymap = SDL_malloc(sizeof(keymap_t)); + if ( ! vga_keymap ) { + SDL_OutOfMemory(); + return(-1); + } + if (ioctl(fd, GIO_KEYMAP, vga_keymap) == -1) { + SDL_free(vga_keymap); + vga_keymap = NULL; + SDL_SetError("Unable to get keyboard map"); + return(-1); + } + return(0); +} +#else +#error You must choose your operating system here +#endif + +int posted = 0; + +void SVGA_mousecallback(int button, int dx, int dy, + int u1,int u2,int u3, int u4) +{ + if ( dx || dy ) { + posted += SDL_PrivateMouseMotion(0, 1, dx, dy); + } + if ( button & MOUSE_LEFTBUTTON ) { + if ( !(SDL_GetMouseState(NULL, NULL) & SDL_BUTTON(1)) ) { + posted += SDL_PrivateMouseButton(SDL_PRESSED, 1, 0, 0); + } + } else { + if ( (SDL_GetMouseState(NULL, NULL) & SDL_BUTTON(1)) ) { + posted += SDL_PrivateMouseButton(SDL_RELEASED, 1, 0, 0); + } + } + if ( button & MOUSE_MIDDLEBUTTON ) { + if ( !(SDL_GetMouseState(NULL, NULL) & SDL_BUTTON(2)) ) { + posted += SDL_PrivateMouseButton(SDL_PRESSED, 2, 0, 0); + } + } else { + if ( (SDL_GetMouseState(NULL, NULL) & SDL_BUTTON(2)) ) { + posted += SDL_PrivateMouseButton(SDL_RELEASED, 2, 0, 0); + } + } + if ( button & MOUSE_RIGHTBUTTON ) { + if ( !(SDL_GetMouseState(NULL, NULL) & SDL_BUTTON(3)) ) { + posted += SDL_PrivateMouseButton(SDL_PRESSED, 3, 0, 0); + } + } else { + if ( (SDL_GetMouseState(NULL, NULL) & SDL_BUTTON(3)) ) { + posted += SDL_PrivateMouseButton(SDL_RELEASED, 3, 0, 0); + } + } +} + +void SVGA_keyboardcallback(int scancode, int pressed) +{ + SDL_keysym keysym; + + if ( pressed ) { + posted += SDL_PrivateKeyboard(SDL_PRESSED, + TranslateKey(scancode, &keysym)); + } else { + posted += SDL_PrivateKeyboard(SDL_RELEASED, + TranslateKey(scancode, &keysym)); + } +} + +void SVGA_PumpEvents(_THIS) +{ + do { + posted = 0; + mouse_update(); + keyboard_update(); + } while ( posted ); +} + +void SVGA_InitOSKeymap(_THIS) +{ + int i; + + /* Initialize the BeOS key translation table */ + for ( i=0; i<SDL_arraysize(keymap); ++i ) + keymap[i] = SDLK_UNKNOWN; + + keymap[SCANCODE_ESCAPE] = SDLK_ESCAPE; + keymap[SCANCODE_1] = SDLK_1; + keymap[SCANCODE_2] = SDLK_2; + keymap[SCANCODE_3] = SDLK_3; + keymap[SCANCODE_4] = SDLK_4; + keymap[SCANCODE_5] = SDLK_5; + keymap[SCANCODE_6] = SDLK_6; + keymap[SCANCODE_7] = SDLK_7; + keymap[SCANCODE_8] = SDLK_8; + keymap[SCANCODE_9] = SDLK_9; + keymap[SCANCODE_0] = SDLK_0; + keymap[SCANCODE_MINUS] = SDLK_MINUS; + keymap[SCANCODE_EQUAL] = SDLK_EQUALS; + keymap[SCANCODE_BACKSPACE] = SDLK_BACKSPACE; + keymap[SCANCODE_TAB] = SDLK_TAB; + keymap[SCANCODE_Q] = SDLK_q; + keymap[SCANCODE_W] = SDLK_w; + keymap[SCANCODE_E] = SDLK_e; + keymap[SCANCODE_R] = SDLK_r; + keymap[SCANCODE_T] = SDLK_t; + keymap[SCANCODE_Y] = SDLK_y; + keymap[SCANCODE_U] = SDLK_u; + keymap[SCANCODE_I] = SDLK_i; + keymap[SCANCODE_O] = SDLK_o; + keymap[SCANCODE_P] = SDLK_p; + keymap[SCANCODE_BRACKET_LEFT] = SDLK_LEFTBRACKET; + keymap[SCANCODE_BRACKET_RIGHT] = SDLK_RIGHTBRACKET; + keymap[SCANCODE_ENTER] = SDLK_RETURN; + keymap[SCANCODE_LEFTCONTROL] = SDLK_LCTRL; + keymap[SCANCODE_A] = SDLK_a; + keymap[SCANCODE_S] = SDLK_s; + keymap[SCANCODE_D] = SDLK_d; + keymap[SCANCODE_F] = SDLK_f; + keymap[SCANCODE_G] = SDLK_g; + keymap[SCANCODE_H] = SDLK_h; + keymap[SCANCODE_J] = SDLK_j; + keymap[SCANCODE_K] = SDLK_k; + keymap[SCANCODE_L] = SDLK_l; + keymap[SCANCODE_SEMICOLON] = SDLK_SEMICOLON; + keymap[SCANCODE_APOSTROPHE] = SDLK_QUOTE; + keymap[SCANCODE_GRAVE] = SDLK_BACKQUOTE; + keymap[SCANCODE_LEFTSHIFT] = SDLK_LSHIFT; + keymap[SCANCODE_BACKSLASH] = SDLK_BACKSLASH; + keymap[SCANCODE_Z] = SDLK_z; + keymap[SCANCODE_X] = SDLK_x; + keymap[SCANCODE_C] = SDLK_c; + keymap[SCANCODE_V] = SDLK_v; + keymap[SCANCODE_B] = SDLK_b; + keymap[SCANCODE_N] = SDLK_n; + keymap[SCANCODE_M] = SDLK_m; + keymap[SCANCODE_COMMA] = SDLK_COMMA; + keymap[SCANCODE_PERIOD] = SDLK_PERIOD; + keymap[SCANCODE_SLASH] = SDLK_SLASH; + keymap[SCANCODE_RIGHTSHIFT] = SDLK_RSHIFT; + keymap[SCANCODE_KEYPADMULTIPLY] = SDLK_KP_MULTIPLY; + keymap[SCANCODE_LEFTALT] = SDLK_LALT; + keymap[SCANCODE_SPACE] = SDLK_SPACE; + keymap[SCANCODE_CAPSLOCK] = SDLK_CAPSLOCK; + keymap[SCANCODE_F1] = SDLK_F1; + keymap[SCANCODE_F2] = SDLK_F2; + keymap[SCANCODE_F3] = SDLK_F3; + keymap[SCANCODE_F4] = SDLK_F4; + keymap[SCANCODE_F5] = SDLK_F5; + keymap[SCANCODE_F6] = SDLK_F6; + keymap[SCANCODE_F7] = SDLK_F7; + keymap[SCANCODE_F8] = SDLK_F8; + keymap[SCANCODE_F9] = SDLK_F9; + keymap[SCANCODE_F10] = SDLK_F10; + keymap[SCANCODE_NUMLOCK] = SDLK_NUMLOCK; + keymap[SCANCODE_SCROLLLOCK] = SDLK_SCROLLOCK; + keymap[SCANCODE_KEYPAD7] = SDLK_KP7; + keymap[SCANCODE_CURSORUPLEFT] = SDLK_KP7; + keymap[SCANCODE_KEYPAD8] = SDLK_KP8; + keymap[SCANCODE_CURSORUP] = SDLK_KP8; + keymap[SCANCODE_KEYPAD9] = SDLK_KP9; + keymap[SCANCODE_CURSORUPRIGHT] = SDLK_KP9; + keymap[SCANCODE_KEYPADMINUS] = SDLK_KP_MINUS; + keymap[SCANCODE_KEYPAD4] = SDLK_KP4; + keymap[SCANCODE_CURSORLEFT] = SDLK_KP4; + keymap[SCANCODE_KEYPAD5] = SDLK_KP5; + keymap[SCANCODE_KEYPAD6] = SDLK_KP6; + keymap[SCANCODE_CURSORRIGHT] = SDLK_KP6; + keymap[SCANCODE_KEYPADPLUS] = SDLK_KP_PLUS; + keymap[SCANCODE_KEYPAD1] = SDLK_KP1; + keymap[SCANCODE_CURSORDOWNLEFT] = SDLK_KP1; + keymap[SCANCODE_KEYPAD2] = SDLK_KP2; + keymap[SCANCODE_CURSORDOWN] = SDLK_KP2; + keymap[SCANCODE_KEYPAD3] = SDLK_KP3; + keymap[SCANCODE_CURSORDOWNRIGHT] = SDLK_KP3; + keymap[SCANCODE_KEYPAD0] = SDLK_KP0; + keymap[SCANCODE_KEYPADPERIOD] = SDLK_KP_PERIOD; + keymap[SCANCODE_LESS] = SDLK_LESS; + keymap[SCANCODE_F11] = SDLK_F11; + keymap[SCANCODE_F12] = SDLK_F12; + keymap[SCANCODE_KEYPADENTER] = SDLK_KP_ENTER; + keymap[SCANCODE_RIGHTCONTROL] = SDLK_RCTRL; + keymap[SCANCODE_CONTROL] = SDLK_RCTRL; + keymap[SCANCODE_KEYPADDIVIDE] = SDLK_KP_DIVIDE; + keymap[SCANCODE_PRINTSCREEN] = SDLK_PRINT; + keymap[SCANCODE_RIGHTALT] = SDLK_RALT; + keymap[SCANCODE_BREAK] = SDLK_BREAK; + keymap[SCANCODE_BREAK_ALTERNATIVE] = SDLK_UNKNOWN; + keymap[SCANCODE_HOME] = SDLK_HOME; + keymap[SCANCODE_CURSORBLOCKUP] = SDLK_UP; + keymap[SCANCODE_PAGEUP] = SDLK_PAGEUP; + keymap[SCANCODE_CURSORBLOCKLEFT] = SDLK_LEFT; + keymap[SCANCODE_CURSORBLOCKRIGHT] = SDLK_RIGHT; + keymap[SCANCODE_END] = SDLK_END; + keymap[SCANCODE_CURSORBLOCKDOWN] = SDLK_DOWN; + keymap[SCANCODE_PAGEDOWN] = SDLK_PAGEDOWN; + keymap[SCANCODE_INSERT] = SDLK_INSERT; + keymap[SCANCODE_REMOVE] = SDLK_DELETE; + keymap[119] = SDLK_PAUSE; + keymap[SCANCODE_RIGHTWIN] = SDLK_RSUPER; + keymap[SCANCODE_LEFTWIN] = SDLK_LSUPER; + keymap[127] = SDLK_MENU; +} + +#if defined(linux) +static SDL_keysym *TranslateKey(int scancode, SDL_keysym *keysym) +{ + /* Set the keysym information */ + keysym->scancode = scancode; + keysym->sym = keymap[scancode]; + keysym->mod = KMOD_NONE; + + /* If UNICODE is on, get the UNICODE value for the key */ + keysym->unicode = 0; + if ( SDL_TranslateUNICODE ) { + int map; + SDLMod modstate; + + modstate = SDL_GetModState(); + map = 0; + if ( modstate & KMOD_SHIFT ) { + map |= (1<<KG_SHIFT); + } + if ( modstate & KMOD_CTRL ) { + map |= (1<<KG_CTRL); + } + if ( modstate & KMOD_ALT ) { + map |= (1<<KG_ALT); + } + if ( modstate & KMOD_MODE ) { + map |= (1<<KG_ALTGR); + } + if ( KTYP(vga_keymap[map][scancode]) == KT_LETTER ) { + if ( modstate & KMOD_CAPS ) { + map ^= (1<<KG_SHIFT); + } + } + if ( KTYP(vga_keymap[map][scancode]) == KT_PAD ) { + if ( modstate & KMOD_NUM ) { + keysym->unicode=KVAL(vga_keymap[map][scancode]); + } + } else { + keysym->unicode = KVAL(vga_keymap[map][scancode]); + } + } + return(keysym); +} +#elif defined(__FREEBSD__) +static SDL_keysym *TranslateKey(int scancode, SDL_keysym *keysym) +{ + /* Set the keysym information */ + keysym->scancode = scancode; + keysym->sym = keymap[scancode]; + keysym->mod = KMOD_NONE; + + /* If UNICODE is on, get the UNICODE value for the key */ + keysym->unicode = 0; + if ( SDL_TranslateUNICODE && vga_keymap ) { + int map; + SDLMod modstate; + + modstate = SDL_GetModState(); + map = 0; + if ( modstate & KMOD_SHIFT ) { + map += 1; + } + if ( modstate & KMOD_CTRL ) { + map += 2; + } + if ( modstate & KMOD_ALT ) { + map += 4; + } + if ( !(vga_keymap->key[scancode].spcl & (0x80 >> map)) ) { + keysym->unicode = vga_keymap->key[scancode].map[map]; + } + + } + return(keysym); +} +#else +#error You must choose your operating system here +#endif diff --git a/3rdparty/SDL/src/video/svga/SDL_svgaevents_c.h b/3rdparty/SDL/src/video/svga/SDL_svgaevents_c.h new file mode 100644 index 0000000..cd9f888 --- /dev/null +++ b/3rdparty/SDL/src/video/svga/SDL_svgaevents_c.h @@ -0,0 +1,35 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#include "SDL_svgavideo.h" + +/* Variables and functions exported by SDL_sysevents.c to other parts + of the native video subsystem (SDL_sysvideo.c) +*/ +extern int SVGA_initkeymaps(int fd); +extern void SVGA_mousecallback(int button, int dx, int dy, + int u1,int u2,int u3, int u4); +extern void SVGA_keyboardcallback(int scancode, int pressed); + +extern void SVGA_InitOSKeymap(_THIS); +extern void SVGA_PumpEvents(_THIS); diff --git a/3rdparty/SDL/src/video/svga/SDL_svgamouse.c b/3rdparty/SDL/src/video/svga/SDL_svgamouse.c new file mode 100644 index 0000000..a82dbfd --- /dev/null +++ b/3rdparty/SDL/src/video/svga/SDL_svgamouse.c @@ -0,0 +1,33 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#include "SDL_mouse.h" +#include "../../events/SDL_events_c.h" +#include "SDL_svgavideo.h" +#include "SDL_svgamouse_c.h" + + +/* The implementation dependent data for the window manager cursor */ +struct WMcursor { + int unused; +}; diff --git a/3rdparty/SDL/src/video/svga/SDL_svgamouse_c.h b/3rdparty/SDL/src/video/svga/SDL_svgamouse_c.h new file mode 100644 index 0000000..78fe8ab --- /dev/null +++ b/3rdparty/SDL/src/video/svga/SDL_svgamouse_c.h @@ -0,0 +1,26 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#include "SDL_svgavideo.h" + +/* Functions to be exported */ diff --git a/3rdparty/SDL/src/video/svga/SDL_svgavideo.c b/3rdparty/SDL/src/video/svga/SDL_svgavideo.c new file mode 100644 index 0000000..58ea800 --- /dev/null +++ b/3rdparty/SDL/src/video/svga/SDL_svgavideo.c @@ -0,0 +1,584 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* SVGAlib based SDL video driver implementation. +*/ + +#include <unistd.h> +#include <sys/stat.h> +#include <sys/types.h> +#include <sys/ioctl.h> +#include <fcntl.h> + +#if defined(__LINUX__) +#include <linux/vt.h> +#elif defined(__FREEBSD__) +#include <sys/consio.h> +#else +#error You must choose your operating system here +#endif +#include <vga.h> +#include <vgamouse.h> +#include <vgakeyboard.h> + +#include "SDL_video.h" +#include "SDL_mouse.h" +#include "../SDL_sysvideo.h" +#include "../SDL_pixels_c.h" +#include "../../events/SDL_events_c.h" +#include "SDL_svgavideo.h" +#include "SDL_svgaevents_c.h" +#include "SDL_svgamouse_c.h" + +/* Initialization/Query functions */ +static int SVGA_VideoInit(_THIS, SDL_PixelFormat *vformat); +static SDL_Rect **SVGA_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags); +static SDL_Surface *SVGA_SetVideoMode(_THIS, SDL_Surface *current, int width, int height, int bpp, Uint32 flags); +static int SVGA_SetColors(_THIS, int firstcolor, int ncolors, + SDL_Color *colors); +static void SVGA_VideoQuit(_THIS); + +/* Hardware surface functions */ +static int SVGA_AllocHWSurface(_THIS, SDL_Surface *surface); +static int SVGA_LockHWSurface(_THIS, SDL_Surface *surface); +static int SVGA_FlipHWSurface(_THIS, SDL_Surface *surface); +static void SVGA_UnlockHWSurface(_THIS, SDL_Surface *surface); +static void SVGA_FreeHWSurface(_THIS, SDL_Surface *surface); + +/* SVGAlib driver bootstrap functions */ + +static int SVGA_Available(void) +{ + /* Check to see if we are root and stdin is a virtual console */ + int console; + + /* SVGALib 1.9.x+ doesn't require root (via /dev/svga) */ + int svgalib2 = -1; + + /* See if we are connected to a virtual terminal */ + console = STDIN_FILENO; +#if 0 /* This is no longer needed, SVGAlib can switch consoles for us */ + if ( console >= 0 ) { + struct stat sb; + struct vt_mode dummy; + + if ( (fstat(console, &sb) < 0) || + (ioctl(console, VT_GETMODE, &dummy) < 0) ) { + console = -1; + } + } +#endif /* 0 */ + + /* See if SVGAlib 2.0 is available */ + svgalib2 = open("/dev/svga", O_RDONLY); + if (svgalib2 != -1) { + close(svgalib2); + } + + return(((svgalib2 != -1) || (geteuid() == 0)) && (console >= 0)); +} + +static void SVGA_DeleteDevice(SDL_VideoDevice *device) +{ + SDL_free(device->hidden); + SDL_free(device); +} + +static SDL_VideoDevice *SVGA_CreateDevice(int devindex) +{ + SDL_VideoDevice *device; + + /* Initialize all variables that we clean on shutdown */ + device = (SDL_VideoDevice *)SDL_malloc(sizeof(SDL_VideoDevice)); + if ( device ) { + SDL_memset(device, 0, (sizeof *device)); + device->hidden = (struct SDL_PrivateVideoData *) + SDL_malloc((sizeof *device->hidden)); + } + if ( (device == NULL) || (device->hidden == NULL) ) { + SDL_OutOfMemory(); + if ( device ) { + SDL_free(device); + } + return(0); + } + SDL_memset(device->hidden, 0, (sizeof *device->hidden)); + + /* Set the function pointers */ + device->VideoInit = SVGA_VideoInit; + device->ListModes = SVGA_ListModes; + device->SetVideoMode = SVGA_SetVideoMode; + device->SetColors = SVGA_SetColors; + device->UpdateRects = NULL; + device->VideoQuit = SVGA_VideoQuit; + device->AllocHWSurface = SVGA_AllocHWSurface; + device->CheckHWBlit = NULL; + device->FillHWRect = NULL; + device->SetHWColorKey = NULL; + device->SetHWAlpha = NULL; + device->LockHWSurface = SVGA_LockHWSurface; + device->UnlockHWSurface = SVGA_UnlockHWSurface; + device->FlipHWSurface = SVGA_FlipHWSurface; + device->FreeHWSurface = SVGA_FreeHWSurface; + device->SetCaption = NULL; + device->SetIcon = NULL; + device->IconifyWindow = NULL; + device->GrabInput = NULL; + device->GetWMInfo = NULL; + device->InitOSKeymap = SVGA_InitOSKeymap; + device->PumpEvents = SVGA_PumpEvents; + + device->free = SVGA_DeleteDevice; + + return device; +} + +VideoBootStrap SVGALIB_bootstrap = { + "svgalib", "SVGAlib", + SVGA_Available, SVGA_CreateDevice +}; + +static int SVGA_AddMode(_THIS, int mode, int actually_add) +{ + int i, j; + vga_modeinfo *modeinfo; + + modeinfo = vga_getmodeinfo(mode); + + i = modeinfo->bytesperpixel-1; + if ( i < 0 ) { + return 0; + } + if ( actually_add ) { + SDL_Rect saved_rect[2]; + int saved_mode[2]; + int b; + + /* Add the mode, sorted largest to smallest */ + b = 0; + j = 0; + while ( (SDL_modelist[i][j]->w > modeinfo->width) || + (SDL_modelist[i][j]->h > modeinfo->height) ) { + ++j; + } + /* Skip modes that are already in our list */ + if ( (SDL_modelist[i][j]->w == modeinfo->width) && + (SDL_modelist[i][j]->h == modeinfo->height) ) { + return(0); + } + /* Insert the new mode */ + saved_rect[b] = *SDL_modelist[i][j]; + saved_mode[b] = SDL_vgamode[i][j]; + SDL_modelist[i][j]->w = modeinfo->width; + SDL_modelist[i][j]->h = modeinfo->height; + SDL_vgamode[i][j] = mode; + /* Everybody scoot down! */ + if ( saved_rect[b].w && saved_rect[b].h ) { + for ( ++j; SDL_modelist[i][j]->w; ++j ) { + saved_rect[!b] = *SDL_modelist[i][j]; + saved_mode[!b] = SDL_vgamode[i][j]; + *SDL_modelist[i][j] = saved_rect[b]; + SDL_vgamode[i][j] = saved_mode[b]; + b = !b; + } + *SDL_modelist[i][j] = saved_rect[b]; + SDL_vgamode[i][j] = saved_mode[b]; + } + } else { + ++SDL_nummodes[i]; + } + return(1); +} + +static void SVGA_UpdateVideoInfo(_THIS) +{ + vga_modeinfo *modeinfo; + + this->info.wm_available = 0; + this->info.hw_available = (banked ? 0 : 1); + modeinfo = vga_getmodeinfo(vga_getcurrentmode()); + this->info.video_mem = modeinfo->memory; + /* FIXME: Add hardware accelerated blit information */ +#ifdef SVGALIB_DEBUG + printf("Hardware accelerated blit: %savailable\n", modeinfo->haveblit ? "" : "not "); +#endif +} + +int SVGA_VideoInit(_THIS, SDL_PixelFormat *vformat) +{ + int keyboard; + int i, j; + int mode, total_modes; + + /* Initialize all variables that we clean on shutdown */ + for ( i=0; i<NUM_MODELISTS; ++i ) { + SDL_nummodes[i] = 0; + SDL_modelist[i] = NULL; + SDL_vgamode[i] = NULL; + } + + /* Initialize the library */ + vga_disabledriverreport(); + if ( vga_init() < 0 ) { + SDL_SetError("Unable to initialize SVGAlib"); + return(-1); + } + vga_setmode(TEXT); + + /* Enable mouse and keyboard support */ + vga_setmousesupport(1); + keyboard = keyboard_init_return_fd(); + if ( keyboard < 0 ) { + SDL_SetError("Unable to initialize keyboard"); + return(-1); + } + if ( SVGA_initkeymaps(keyboard) < 0 ) { + return(-1); + } + keyboard_seteventhandler(SVGA_keyboardcallback); + + /* Determine the current screen size */ + this->info.current_w = 0; + this->info.current_h = 0; + + /* Determine the screen depth (use default 8-bit depth) */ + vformat->BitsPerPixel = 8; + + /* Enumerate the available fullscreen modes */ + total_modes = 0; + for ( mode=vga_lastmodenumber(); mode; --mode ) { + if ( vga_hasmode(mode) ) { + if ( SVGA_AddMode(this, mode, 0) ) { + ++total_modes; + } + } + } + if ( SVGA_AddMode(this, G320x200x256, 0) ) ++total_modes; + if ( total_modes == 0 ) { + SDL_SetError("No linear video modes available"); + return(-1); + } + for ( i=0; i<NUM_MODELISTS; ++i ) { + SDL_vgamode[i] = (int *)SDL_malloc(SDL_nummodes[i]*sizeof(int)); + if ( SDL_vgamode[i] == NULL ) { + SDL_OutOfMemory(); + return(-1); + } + SDL_modelist[i] = (SDL_Rect **) + SDL_malloc((SDL_nummodes[i]+1)*sizeof(SDL_Rect *)); + if ( SDL_modelist[i] == NULL ) { + SDL_OutOfMemory(); + return(-1); + } + for ( j=0; j<SDL_nummodes[i]; ++j ) { + SDL_modelist[i][j]=(SDL_Rect *)SDL_malloc(sizeof(SDL_Rect)); + if ( SDL_modelist[i][j] == NULL ) { + SDL_OutOfMemory(); + return(-1); + } + SDL_memset(SDL_modelist[i][j], 0, sizeof(SDL_Rect)); + } + SDL_modelist[i][j] = NULL; + } + for ( mode=vga_lastmodenumber(); mode; --mode ) { + if ( vga_hasmode(mode) ) { + SVGA_AddMode(this, mode, 1); + } + } + SVGA_AddMode(this, G320x200x256, 1); + + /* Free extra (duplicated) modes */ + for ( i=0; i<NUM_MODELISTS; ++i ) { + j = 0; + while ( SDL_modelist[i][j] && SDL_modelist[i][j]->w ) { + j++; + } + while ( SDL_modelist[i][j] ) { + SDL_free(SDL_modelist[i][j]); + SDL_modelist[i][j] = NULL; + j++; + } + } + + /* Fill in our hardware acceleration capabilities */ + SVGA_UpdateVideoInfo(this); + + /* We're done! */ + return(0); +} + +SDL_Rect **SVGA_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags) +{ + return(SDL_modelist[((format->BitsPerPixel+7)/8)-1]); +} + +/* Various screen update functions available */ +static void SVGA_DirectUpdate(_THIS, int numrects, SDL_Rect *rects); +static void SVGA_BankedUpdate(_THIS, int numrects, SDL_Rect *rects); + +SDL_Surface *SVGA_SetVideoMode(_THIS, SDL_Surface *current, + int width, int height, int bpp, Uint32 flags) +{ + int mode; + int vgamode; + vga_modeinfo *modeinfo; + int screenpage_len; + + /* Free old pixels if we were in banked mode */ + if ( banked && current->pixels ) { + free(current->pixels); + current->pixels = NULL; + } + + /* Try to set the requested linear video mode */ + bpp = (bpp+7)/8-1; + for ( mode=0; SDL_modelist[bpp][mode]; ++mode ) { + if ( (SDL_modelist[bpp][mode]->w == width) && + (SDL_modelist[bpp][mode]->h == height) ) { + break; + } + } + if ( SDL_modelist[bpp][mode] == NULL ) { + SDL_SetError("Couldn't find requested mode in list"); + return(NULL); + } + vgamode = SDL_vgamode[bpp][mode]; + vga_setmode(vgamode); + vga_setpage(0); + + if ( (vga_setlinearaddressing() < 0) && (vgamode != G320x200x256) ) { + banked = 1; + } else { + banked = 0; + } + + modeinfo = vga_getmodeinfo(SDL_vgamode[bpp][mode]); + + /* Update hardware acceleration info */ + SVGA_UpdateVideoInfo(this); + + /* Allocate the new pixel format for the screen */ + bpp = (bpp+1)*8; + if ( (bpp == 16) && (modeinfo->colors == 32768) ) { + bpp = 15; + } + if ( ! SDL_ReallocFormat(current, bpp, 0, 0, 0, 0) ) { + return(NULL); + } + + /* Set up the new mode framebuffer */ + current->flags = SDL_FULLSCREEN; + if ( !banked ) { + current->flags |= SDL_HWSURFACE; + } + if ( bpp == 8 ) { + /* FIXME: What about DirectColor? */ + current->flags |= SDL_HWPALETTE; + } + current->w = width; + current->h = height; + current->pitch = modeinfo->linewidth; + if ( banked ) { + current->pixels = SDL_malloc(current->h * current->pitch); + if ( !current->pixels ) { + SDL_OutOfMemory(); + return(NULL); + } + } else { + current->pixels = vga_getgraphmem(); + } + + /* set double-buffering */ + if ( (flags & SDL_DOUBLEBUF) && !banked ) + { + /* length of one screen page in bytes */ + screenpage_len=current->h*modeinfo->linewidth; + + /* if start address should be aligned */ + if ( modeinfo->linewidth_unit ) + { + if ( screenpage_len % modeinfo->linewidth_unit ) + { + screenpage_len += modeinfo->linewidth_unit - ( screenpage_len % modeinfo->linewidth_unit ); + } + } + + /* if we heve enough videomemory = ak je dost videopamete */ + if ( modeinfo->memory > ( screenpage_len * 2 / 1024 ) ) + { + current->flags |= SDL_DOUBLEBUF; + flip_page = 0; + flip_offset[0] = 0; + flip_offset[1] = screenpage_len; + flip_address[0] = vga_getgraphmem(); + flip_address[1] = flip_address[0]+screenpage_len; + SVGA_FlipHWSurface(this,current); + } + } + + /* Set the blit function */ + if ( banked ) { + this->UpdateRects = SVGA_BankedUpdate; + } else { + this->UpdateRects = SVGA_DirectUpdate; + } + + /* Set up the mouse handler again (buggy SVGAlib 1.40) */ + mouse_seteventhandler(SVGA_mousecallback); + + /* We're done */ + return(current); +} + +/* We don't actually allow hardware surfaces other than the main one */ +static int SVGA_AllocHWSurface(_THIS, SDL_Surface *surface) +{ + return(-1); +} +static void SVGA_FreeHWSurface(_THIS, SDL_Surface *surface) +{ + return; +} + +/* We need to wait for vertical retrace on page flipped displays */ +static int SVGA_LockHWSurface(_THIS, SDL_Surface *surface) +{ + /* The waiting is done in SVGA_FlipHWSurface() */ + return(0); +} +static void SVGA_UnlockHWSurface(_THIS, SDL_Surface *surface) +{ + return; +} + +static int SVGA_FlipHWSurface(_THIS, SDL_Surface *surface) +{ + if ( !banked ) { + vga_setdisplaystart(flip_offset[flip_page]); + flip_page=!flip_page; + surface->pixels=flip_address[flip_page]; + vga_waitretrace(); + } + return(0); +} + +static void SVGA_DirectUpdate(_THIS, int numrects, SDL_Rect *rects) +{ + return; +} + +static void SVGA_BankedUpdate(_THIS, int numrects, SDL_Rect *rects) +{ + int i, j; + SDL_Rect *rect; + int page, vp; + int x, y, w, h; + unsigned char *src; + unsigned char *dst; + int bpp = this->screen->format->BytesPerPixel; + int pitch = this->screen->pitch; + + dst = vga_getgraphmem(); + for ( i=0; i < numrects; ++i ) { + rect = &rects[i]; + x = rect->x; + y = rect->y; + w = rect->w * bpp; + h = rect->h; + + vp = y * pitch + x * bpp; + src = (unsigned char *)this->screen->pixels + vp; + page = vp >> 16; + vp &= 0xffff; + vga_setpage(page); + for (j = 0; j < h; j++) { + if (vp + w > 0x10000) { + if (vp >= 0x10000) { + page++; + vga_setpage(page); + vp &= 0xffff; + } else { + SDL_memcpy(dst + vp, src, 0x10000 - vp); + page++; + vga_setpage(page); + SDL_memcpy(dst, src + 0x10000 - vp, + (vp + w) & 0xffff); + vp = (vp + pitch) & 0xffff; + src += pitch; + continue; + } + } + SDL_memcpy(dst + vp, src, w); + src += pitch; + vp += pitch; + } + } +} + +int SVGA_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors) +{ + int i; + + for(i = 0; i < ncolors; i++) { + vga_setpalette(firstcolor + i, + colors[i].r>>2, + colors[i].g>>2, + colors[i].b>>2); + } + return(1); +} + +/* Note: If we are terminated, this could be called in the middle of + another SDL video routine -- notably UpdateRects. +*/ +void SVGA_VideoQuit(_THIS) +{ + int i, j; + + /* Reset the console video mode */ + if ( this->screen && (this->screen->w && this->screen->h) ) { + vga_setmode(TEXT); + } + keyboard_close(); + + /* Free video mode lists */ + for ( i=0; i<NUM_MODELISTS; ++i ) { + if ( SDL_modelist[i] != NULL ) { + for ( j=0; SDL_modelist[i][j]; ++j ) + SDL_free(SDL_modelist[i][j]); + SDL_free(SDL_modelist[i]); + SDL_modelist[i] = NULL; + } + if ( SDL_vgamode[i] != NULL ) { + SDL_free(SDL_vgamode[i]); + SDL_vgamode[i] = NULL; + } + } + if ( this->screen ) { + if ( banked && this->screen->pixels ) { + SDL_free(this->screen->pixels); + } + this->screen->pixels = NULL; + } +} + diff --git a/3rdparty/SDL/src/video/svga/SDL_svgavideo.h b/3rdparty/SDL/src/video/svga/SDL_svgavideo.h new file mode 100644 index 0000000..7fb86cb --- /dev/null +++ b/3rdparty/SDL/src/video/svga/SDL_svgavideo.h @@ -0,0 +1,58 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#ifndef _SDL_svgavideo_h +#define _SDL_svgavideo_h + +#include "SDL_mouse.h" +#include "../SDL_sysvideo.h" + +/* Hidden "this" pointer for the video functions */ +#define _THIS SDL_VideoDevice *this + +/* Private display data */ +struct SDL_PrivateVideoData { +#define NUM_MODELISTS 4 /* 8, 16, 24, and 32 bits-per-pixel */ + int SDL_nummodes[NUM_MODELISTS]; + SDL_Rect **SDL_modelist[NUM_MODELISTS]; + int *SDL_vgamode[NUM_MODELISTS]; + + /* information for double-buffering */ + int flip_page; + int flip_offset[2]; + Uint8 *flip_address[2]; + + /* Set to 1 if we're in banked video mode */ + int banked; +}; +/* Old variable names */ +#define SDL_nummodes (this->hidden->SDL_nummodes) +#define SDL_modelist (this->hidden->SDL_modelist) +#define SDL_vgamode (this->hidden->SDL_vgamode) +#define flip_page (this->hidden->flip_page) +#define flip_offset (this->hidden->flip_offset) +#define flip_address (this->hidden->flip_address) +#define banked (this->hidden->banked) + +#endif /* _SDL_svgavideo_h */ + diff --git a/3rdparty/SDL/src/video/symbian/EKA1/SDL_epocevents.cpp b/3rdparty/SDL/src/video/symbian/EKA1/SDL_epocevents.cpp new file mode 100644 index 0000000..5ceed5f --- /dev/null +++ b/3rdparty/SDL/src/video/symbian/EKA1/SDL_epocevents.cpp @@ -0,0 +1,626 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Sam Lantinga + slouken@devolution.com +*/ + +/* + SDL_epocevents.cpp + Handle the event stream, converting Epoc events into SDL events + + Epoc version by Hannu Viitala (hannu.j.viitala@mbnet.fi) +*/ + + +#include <stdio.h> +#undef NULL +extern "C" { +//#define DEBUG_TRACE_ENABLED +#include "SDL_error.h" +#include "SDL_video.h" +#include "SDL_keysym.h" +#include "SDL_keyboard.h" +#include "SDL_events_c.h" +#include "SDL_timer.h" +}; /* extern "C" */ + +#include "SDL_epocvideo.h" +#include "SDL_epocevents_c.h" + +#include<linereader.h> +#include<bautils.h> + + +#include <hal.h> + +extern "C" { +/* The translation tables from a console scancode to a SDL keysym */ +static SDLKey keymap[MAX_SCANCODE]; +static SDL_keysym *TranslateKey(_THIS, int scancode, SDL_keysym *keysym); +void DisableKeyBlocking(_THIS); +}; /* extern "C" */ + +TBool isCursorVisible = EFalse; + +int EPOC_HandleWsEvent(_THIS, const TWsEvent& aWsEvent) +{ + int posted = 0; + SDL_keysym keysym; + +// SDL_TRACE1("hws %d", aWsEvent.Type()); + + switch (aWsEvent.Type()) + { + case EEventPointer: /* Mouse pointer events */ + { + + const TPointerCursorMode mode = Private->EPOC_WsSession.PointerCursorMode(); + + if(mode == EPointerCursorNone) + { + return 0; //TODO: Find out why events are get despite of cursor should be off + } + + const TPointerEvent* pointerEvent = aWsEvent.Pointer(); + TPoint mousePos = pointerEvent->iPosition; + + /*!! TODO Pointer do not yet work properly + //SDL_TRACE1("SDL: EPOC_HandleWsEvent, pointerEvent->iType=%d", pointerEvent->iType); //!! + + if (Private->EPOC_ShrinkedHeight) { + mousePos.iY <<= 1; // Scale y coordinate to shrinked screen height + } + if (Private->EPOC_ShrinkedWidth) { + mousePos.iX <<= 1; // Scale x coordinate to shrinked screen width + } + */ + + posted += SDL_PrivateMouseMotion(0, 0, mousePos.iX, mousePos.iY); /* Absolute position on screen */ + + switch (pointerEvent->iType) + { + case TPointerEvent::EButton1Down: + posted += SDL_PrivateMouseButton(SDL_PRESSED, SDL_BUTTON_LEFT, 0, 0); + break; + case TPointerEvent::EButton1Up: + posted += SDL_PrivateMouseButton(SDL_RELEASED, SDL_BUTTON_LEFT, 0, 0); + break; + case TPointerEvent::EButton2Down: + posted += SDL_PrivateMouseButton(SDL_PRESSED, SDL_BUTTON_RIGHT, 0, 0); + break; + case TPointerEvent::EButton2Up: + posted += SDL_PrivateMouseButton(SDL_RELEASED, SDL_BUTTON_RIGHT, 0, 0); + break; + case TPointerEvent::EButton3Down: + posted += SDL_PrivateMouseButton(SDL_PRESSED, SDL_BUTTON_MIDDLE, 0, 0); + break; + case TPointerEvent::EButton3Up: + posted += SDL_PrivateMouseButton(SDL_RELEASED, SDL_BUTTON_MIDDLE, 0, 0); + break; + } // switch + break; + } + + case EEventKeyDown: /* Key events */ + { +#ifdef SYMBIAN_CRYSTAL + // special case: 9300/9500 rocker down, simulate left mouse button + if (aWsEvent.Key()->iScanCode == EStdKeyDeviceA) + { + const TPointerCursorMode mode = Private->EPOC_WsSession.PointerCursorMode(); + if(mode != EPointerCursorNone) + posted += SDL_PrivateMouseButton(SDL_PRESSED, SDL_BUTTON_LEFT, 0, 0); + } +#endif + (void*)TranslateKey(_this, aWsEvent.Key()->iScanCode, &keysym); + +#ifndef DISABLE_JOYSTICK + /* Special handling */ + switch((int)keysym.sym) { + case SDLK_CAPSLOCK: + if (!isCursorVisible) { + /* Enable virtual cursor */ + HAL::Set(HAL::EMouseState, HAL::EMouseState_Visible); + } + else { + /* Disable virtual cursor */ + HAL::Set(HAL::EMouseState, HAL::EMouseState_Invisible); + } + isCursorVisible = !isCursorVisible; + break; + } +#endif + posted += SDL_PrivateKeyboard(SDL_PRESSED, &keysym); + break; + } + + case EEventKeyUp: /* Key events */ + { +#ifdef SYMBIAN_CRYSTAL + // special case: 9300/9500 rocker up, simulate left mouse button + if (aWsEvent.Key()->iScanCode == EStdKeyDeviceA) + { + posted += SDL_PrivateMouseButton(SDL_RELEASED, SDL_BUTTON_LEFT, 0, 0); + } +#endif + posted += SDL_PrivateKeyboard(SDL_RELEASED, TranslateKey(_this, aWsEvent.Key()->iScanCode, &keysym)); + break; + } + + case EEventFocusGained: /* SDL window got focus */ + { + Private->EPOC_IsWindowFocused = ETrue; + posted += SDL_PrivateAppActive(1, SDL_APPINPUTFOCUS|SDL_APPMOUSEFOCUS); + /* Draw window background and screen buffer */ + DisableKeyBlocking(_this); //Markus: guess why:-) + + RedrawWindowL(_this); + break; + } + + case EEventFocusLost: /* SDL window lost focus */ + { +/* + CFbsBitmap* bmp = new (ELeave) CFbsBitmap(); + bmp->Create(Private->EPOC_ScreenSize, Private->EPOC_DisplayMode); + Private->EPOC_WsScreen->CopyScreenToBitmap(bmp); + Private->EPOC_WindowGc->Activate(Private->EPOC_WsWindow); + Private->EPOC_WsWindow.BeginRedraw(TRect(Private->EPOC_WsWindow.Size())); + Private->EPOC_WindowGc->BitBlt(TPoint(0, 0), bmp); + Private->EPOC_WsWindow.EndRedraw(); + Private->EPOC_WindowGc->Deactivate(); + bmp->Save(_L("C:\\scr.mbm")); + delete bmp; +*/ + + Private->EPOC_IsWindowFocused = EFalse; + + posted += SDL_PrivateAppActive(0, SDL_APPINPUTFOCUS|SDL_APPMOUSEFOCUS); + + RWsSession s; + s.Connect(); + RWindowGroup g(s); + g.Construct(TUint32(&g), EFalse); + g.EnableReceiptOfFocus(EFalse); + RWindow w(s); + w.Construct(g, TUint32(&w)); + w.SetExtent(TPoint(0, 0), Private->EPOC_WsWindow.Size()); + w.SetOrdinalPosition(0); + w.Activate(); + w.Close(); + g.Close(); + s.Close(); + +/* + Private->EPOC_WsSession.SetWindowGroupOrdinalPosition(Private->EPOC_WsWindowGroupID, -1); + + + SDL_Delay(500); + TInt focus = -1; + while(focus < 0) + { + const TInt curr = Private->EPOC_WsSession.GetFocusWindowGroup(); + if(curr != Private->EPOC_WsWindowGroupID) + focus = curr; + else + SDL_Delay(500); + } + + if(1 < Private->EPOC_WsSession.GetWindowGroupOrdinalPriority(Private->EPOC_WsWindowGroupID)) + { + Private->EPOC_WsSession.SetWindowGroupOrdinalPosition(focus, -1); + SDL_Delay(500); + Private->EPOC_WsSession.SetWindowGroupOrdinalPosition(focus, 0); + } +*/ + /*//and the request redraw + TRawEvent redrawEvent; + redrawEvent.Set(TRawEvent::ERedraw); + Private->EPOC_WsSession.SimulateRawEvent(redrawEvent); + Private->EPOC_WsSession.Flush();*/ +#if 0 + //!! Not used + // Wait and eat events until focus is gained again + while (ETrue) { + Private->EPOC_WsSession.EventReady(&Private->EPOC_WsEventStatus); + User::WaitForRequest(Private->EPOC_WsEventStatus); + Private->EPOC_WsSession.GetEvent(Private->EPOC_WsEvent); + TInt eventType = Private->EPOC_WsEvent.Type(); + Private->EPOC_WsEventStatus = KRequestPending; + //Private->EPOC_WsSession.EventReady(&Private->EPOC_WsEventStatus); + if (eventType == EEventFocusGained) { + RedrawWindowL(_this); + break; + } + } +#endif + break; + } + + case EEventModifiersChanged: + { + TModifiersChangedEvent* modEvent = aWsEvent.ModifiersChanged(); + TUint modstate = KMOD_NONE; + if (modEvent->iModifiers == EModifierLeftShift) + modstate |= KMOD_LSHIFT; + if (modEvent->iModifiers == EModifierRightShift) + modstate |= KMOD_RSHIFT; + if (modEvent->iModifiers == EModifierLeftCtrl) + modstate |= KMOD_LCTRL; + if (modEvent->iModifiers == EModifierRightCtrl) + modstate |= KMOD_RCTRL; + if (modEvent->iModifiers == EModifierLeftAlt) + modstate |= KMOD_LALT; + if (modEvent->iModifiers == EModifierRightAlt) + modstate |= KMOD_RALT; + if (modEvent->iModifiers == EModifierLeftFunc) + modstate |= KMOD_LMETA; + if (modEvent->iModifiers == EModifierRightFunc) + modstate |= KMOD_RMETA; + if (modEvent->iModifiers == EModifierCapsLock) + modstate |= KMOD_CAPS; + SDL_SetModState(STATIC_CAST(SDLMod,(modstate | KMOD_LSHIFT))); + break; + } + default: + break; + } + + return posted; +} + +extern "C" { + +void EPOC_PumpEvents(_THIS) +{ + int posted = 0; // !! Do we need this? + //Private->EPOC_WsSession.EventReady(&Private->EPOC_WsEventStatus); + while (Private->EPOC_WsEventStatus != KRequestPending) { + + Private->EPOC_WsSession.GetEvent(Private->EPOC_WsEvent); + posted = EPOC_HandleWsEvent(_this, Private->EPOC_WsEvent); + Private->EPOC_WsEventStatus = KRequestPending; + Private->EPOC_WsSession.EventReady(&Private->EPOC_WsEventStatus); + } +} + + +_LIT(KMapFileName, "C:\\sdl_info\\sdlkeymap.cfg"); +LOCAL_C void ReadL(RFs& aFs, RArray<TInt>& aArray) + { + TInt drive = -1; + TFileName name(KMapFileName); + for(TInt i = 'z'; drive < 0 && i >= 'a'; i--) + { + name[0] = (TUint16)i; + if(BaflUtils::FileExists(aFs, name)) + drive = i; + } + if(drive < 0) + return; + CLineReader* reader = CLineReader::NewLC(aFs, name); + while(reader->NextL()) + { + TPtrC ln = reader->Current(); + TLex line(ln); + TInt n = 0; + for(;;) + { + const TPtrC token = line.NextToken(); + if(token.Length() == 0) + break; + if((n & 1) != 0) + { + TInt value; + TLex lex(token); + User::LeaveIfError(lex.Val(value)); + User::LeaveIfError(aArray.Append(value)); + } + n++; + } + } + CleanupStack::PopAndDestroy(); + } + + +void EPOC_InitOSKeymap(_THIS) +{ + int i; + + /* Initialize the key translation table */ + for ( i=0; i<SDL_TABLESIZE(keymap); ++i ) + keymap[i] = SDLK_UNKNOWN; + + + /* Numbers */ + for ( i = 0; i<32; ++i ){ + keymap[' ' + i] = (SDLKey)(SDLK_SPACE+i); + } + /* e.g. Alphabet keys */ + for ( i = 0; i<32; ++i ){ + keymap['A' + i] = (SDLKey)(SDLK_a+i); + } + + keymap[EStdKeyBackspace] = SDLK_BACKSPACE; + keymap[EStdKeyTab] = SDLK_TAB; + keymap[EStdKeyEnter] = SDLK_RETURN; + keymap[EStdKeyEscape] = SDLK_ESCAPE; + keymap[EStdKeySpace] = SDLK_SPACE; + keymap[EStdKeyPause] = SDLK_PAUSE; + keymap[EStdKeyHome] = SDLK_HOME; + keymap[EStdKeyEnd] = SDLK_END; + keymap[EStdKeyPageUp] = SDLK_PAGEUP; + keymap[EStdKeyPageDown] = SDLK_PAGEDOWN; + keymap[EStdKeyDelete] = SDLK_DELETE; + keymap[EStdKeyUpArrow] = SDLK_UP; + keymap[EStdKeyDownArrow] = SDLK_DOWN; + keymap[EStdKeyLeftArrow] = SDLK_LEFT; + keymap[EStdKeyRightArrow] = SDLK_RIGHT; + keymap[EStdKeyCapsLock] = SDLK_CAPSLOCK; + keymap[EStdKeyLeftShift] = SDLK_LSHIFT; + keymap[EStdKeyRightShift] = SDLK_RSHIFT; + keymap[EStdKeyLeftAlt] = SDLK_LALT; + keymap[EStdKeyRightAlt] = SDLK_RALT; + keymap[EStdKeyLeftCtrl] = SDLK_LCTRL; + keymap[EStdKeyRightCtrl] = SDLK_RCTRL; + keymap[EStdKeyLeftFunc] = SDLK_LMETA; + keymap[EStdKeyRightFunc] = SDLK_RMETA; + keymap[EStdKeyInsert] = SDLK_INSERT; + keymap[EStdKeyComma] = SDLK_COMMA; + keymap[EStdKeyFullStop] = SDLK_PERIOD; + keymap[EStdKeyForwardSlash] = SDLK_SLASH; + keymap[EStdKeyBackSlash] = SDLK_BACKSLASH; + keymap[EStdKeySemiColon] = SDLK_SEMICOLON; + keymap[EStdKeySingleQuote] = SDLK_QUOTE; + keymap[EStdKeyHash] = SDLK_HASH; + keymap[EStdKeySquareBracketLeft] = SDLK_LEFTBRACKET; + keymap[EStdKeySquareBracketRight] = SDLK_RIGHTBRACKET; + keymap[EStdKeyMinus] = SDLK_MINUS; + keymap[EStdKeyEquals] = SDLK_EQUALS; + + keymap[EStdKeyF1] = SDLK_F1; /* chr + q */ + keymap[EStdKeyF2] = SDLK_F2; /* chr + w */ + keymap[EStdKeyF3] = SDLK_F3; /* chr + e */ + keymap[EStdKeyF4] = SDLK_F4; /* chr + r */ + keymap[EStdKeyF5] = SDLK_F5; /* chr + t */ + keymap[EStdKeyF6] = SDLK_F6; /* chr + y */ + keymap[EStdKeyF7] = SDLK_F7; /* chr + i */ + keymap[EStdKeyF8] = SDLK_F8; /* chr + o */ + + keymap[EStdKeyF9] = SDLK_F9; /* chr + a */ + keymap[EStdKeyF10] = SDLK_F10; /* chr + s */ + keymap[EStdKeyF11] = SDLK_F11; /* chr + d */ + keymap[EStdKeyF12] = SDLK_F12; /* chr + f */ + + #ifndef SYMBIAN_CRYSTAL + //!!7650 additions + #ifdef __WINS__ + keymap[EStdKeyXXX] = SDLK_RETURN; /* "fire" key */ + #else + keymap[EStdKeyDevice3] = SDLK_RETURN; /* "fire" key */ + #endif + keymap[EStdKeyNkpAsterisk] = SDLK_ASTERISK; + keymap[EStdKeyYes] = SDLK_HOME; /* "call" key */ + keymap[EStdKeyNo] = SDLK_END; /* "end call" key */ + keymap[EStdKeyDevice0] = SDLK_SPACE; /* right menu key */ + keymap[EStdKeyDevice1] = SDLK_ESCAPE; /* left menu key */ + keymap[EStdKeyDevice2] = SDLK_POWER; /* power key */ + #endif + + #ifdef SYMBIAN_CRYSTAL + keymap[EStdKeyMenu] = SDLK_ESCAPE; // menu key + keymap[EStdKeyDevice6] = SDLK_LEFT; // Rocker (joystick) left + keymap[EStdKeyDevice7] = SDLK_RIGHT; // Rocker (joystick) right + keymap[EStdKeyDevice8] = SDLK_UP; // Rocker (joystick) up + keymap[EStdKeyDevice9] = SDLK_DOWN; // Rocker (joystick) down + keymap[EStdKeyLeftFunc] = SDLK_LALT; //chr? + keymap[EStdKeyRightFunc] = SDLK_RALT; + keymap[EStdKeyDeviceA] = SDLK_RETURN; /* "fire" key */ +#endif + + /////////////////////////////////////////////////////////// + + RFs fs; + if(KErrNone == fs.Connect()) + { + RArray<TInt> array; + TRAPD(err, ReadL(fs, array)); + if(err == KErrNone && array.Count() > 0) + { + + SDLKey temp[MAX_SCANCODE]; + Mem::Copy(temp, keymap, MAX_SCANCODE * sizeof(SDLKey)); + + for(TInt k = 0; k < array.Count(); k+= 2) + { + const TInt oldval = array[k]; + const TInt newval = array[k + 1]; + if(oldval >= 0 && oldval < MAX_SCANCODE && newval >= 0 && newval < MAX_SCANCODE) + { + keymap[oldval] = temp[newval]; + } + } + } + array.Close(); + } + + fs.Close(); + /////////////////////////////////////////////////////////// + + /* !!TODO + EStdKeyNumLock=0x1b, + EStdKeyScrollLock=0x1c, + + EStdKeyNkpForwardSlash=0x84, + EStdKeyNkpAsterisk=0x85, + EStdKeyNkpMinus=0x86, + EStdKeyNkpPlus=0x87, + EStdKeyNkpEnter=0x88, + EStdKeyNkp1=0x89, + EStdKeyNkp2=0x8a, + EStdKeyNkp3=0x8b, + EStdKeyNkp4=0x8c, + EStdKeyNkp5=0x8d, + EStdKeyNkp6=0x8e, + EStdKeyNkp7=0x8f, + EStdKeyNkp8=0x90, + EStdKeyNkp9=0x91, + EStdKeyNkp0=0x92, + EStdKeyNkpFullStop=0x93, + EStdKeyMenu=0x94, + EStdKeyBacklightOn=0x95, + EStdKeyBacklightOff=0x96, + EStdKeyBacklightToggle=0x97, + EStdKeyIncContrast=0x98, + EStdKeyDecContrast=0x99, + EStdKeySliderDown=0x9a, + EStdKeySliderUp=0x9b, + EStdKeyDictaphonePlay=0x9c, + EStdKeyDictaphoneStop=0x9d, + EStdKeyDictaphoneRecord=0x9e, + EStdKeyHelp=0x9f, + EStdKeyOff=0xa0, + EStdKeyDial=0xa1, + EStdKeyIncVolume=0xa2, + EStdKeyDecVolume=0xa3, + EStdKeyDevice0=0xa4, + EStdKeyDevice1=0xa5, + EStdKeyDevice2=0xa6, + EStdKeyDevice3=0xa7, + EStdKeyDevice4=0xa8, + EStdKeyDevice5=0xa9, + EStdKeyDevice6=0xaa, + EStdKeyDevice7=0xab, + EStdKeyDevice8=0xac, + EStdKeyDevice9=0xad, + EStdKeyDeviceA=0xae, + EStdKeyDeviceB=0xaf, + EStdKeyDeviceC=0xb0, + EStdKeyDeviceD=0xb1, + EStdKeyDeviceE=0xb2, + EStdKeyDeviceF=0xb3, + EStdKeyApplication0=0xb4, + EStdKeyApplication1=0xb5, + EStdKeyApplication2=0xb6, + EStdKeyApplication3=0xb7, + EStdKeyApplication4=0xb8, + EStdKeyApplication5=0xb9, + EStdKeyApplication6=0xba, + EStdKeyApplication7=0xbb, + EStdKeyApplication8=0xbc, + EStdKeyApplication9=0xbd, + EStdKeyApplicationA=0xbe, + EStdKeyApplicationB=0xbf, + EStdKeyApplicationC=0xc0, + EStdKeyApplicationD=0xc1, + EStdKeyApplicationE=0xc2, + EStdKeyApplicationF=0xc3, + EStdKeyYes=0xc4, + EStdKeyNo=0xc5, + EStdKeyIncBrightness=0xc6, + EStdKeyDecBrightness=0xc7, + EStdKeyCaseOpen=0xc8, + EStdKeyCaseClose=0xc9 + */ + +} + + + +static SDL_keysym *TranslateKey(_THIS, int scancode, SDL_keysym *keysym) +{ +// char debug[256]; + //SDL_TRACE1("SDL: TranslateKey, scancode=%d", scancode); //!! + + /* Set the keysym information */ + + keysym->scancode = scancode; + + if ((scancode >= MAX_SCANCODE) && + ((scancode - ENonCharacterKeyBase + 0x0081) >= MAX_SCANCODE)) { + SDL_SetError("Too big scancode"); + keysym->scancode = SDLK_UNKNOWN; + keysym->mod = KMOD_NONE; + return keysym; + } + + keysym->mod = SDL_GetModState(); + + /* Handle function keys: F1, F2, F3 ... */ + if (keysym->mod & KMOD_META) { + if (scancode >= 'A' && scancode < ('A' + 24)) { /* first 32 alphabet keys */ + switch(scancode) { + case 'Q': scancode = EStdKeyF1; break; + case 'W': scancode = EStdKeyF2; break; + case 'E': scancode = EStdKeyF3; break; + case 'R': scancode = EStdKeyF4; break; + case 'T': scancode = EStdKeyF5; break; + case 'Y': scancode = EStdKeyF6; break; + case 'U': scancode = EStdKeyF7; break; + case 'I': scancode = EStdKeyF8; break; + case 'A': scancode = EStdKeyF9; break; + case 'S': scancode = EStdKeyF10; break; + case 'D': scancode = EStdKeyF11; break; + case 'F': scancode = EStdKeyF12; break; + } + keysym->sym = keymap[scancode]; + } + } + + if (scancode >= ENonCharacterKeyBase) { + // Non character keys + keysym->sym = keymap[scancode - + ENonCharacterKeyBase + 0x0081]; // !!hard coded + } else { + keysym->sym = keymap[scancode]; + } + + /* Remap the arrow keys if the device is rotated */ + if (Private->EPOC_ScreenOrientation == CFbsBitGc::EGraphicsOrientationRotated270) { + switch(keysym->sym) { + case SDLK_UP: keysym->sym = SDLK_LEFT; break; + case SDLK_DOWN: keysym->sym = SDLK_RIGHT; break; + case SDLK_LEFT: keysym->sym = SDLK_DOWN; break; + case SDLK_RIGHT:keysym->sym = SDLK_UP; break; + } + } + + /* If UNICODE is on, get the UNICODE value for the key */ + keysym->unicode = 0; + +#if 0 // !!TODO:unicode + + if ( SDL_TranslateUNICODE ) + { + /* Populate the unicode field with the ASCII value */ + keysym->unicode = scancode; + } +#endif + + //!! + //sprintf(debug, "SDL: TranslateKey: keysym->scancode=%d, keysym->sym=%d, keysym->mod=%d", + // keysym->scancode, keysym->sym, keysym->mod); + //SDL_TRACE(debug); //!! + + return(keysym); +} + +}; /* extern "C" */ + + diff --git a/3rdparty/SDL/src/video/symbian/EKA1/SDL_epocvideo.cpp b/3rdparty/SDL/src/video/symbian/EKA1/SDL_epocvideo.cpp new file mode 100644 index 0000000..06874d5 --- /dev/null +++ b/3rdparty/SDL/src/video/symbian/EKA1/SDL_epocvideo.cpp @@ -0,0 +1,1356 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Sam Lantinga + slouken@devolution.com +*/ + +/* + SDL_epocvideo.cpp + Epoc based SDL video driver implementation + + Thanks to Peter van Sebille, the author of EMame. It is a great example of + low level graphics coding in Epoc. + + Epoc version by Hannu Viitala (hannu.j.viitala@mbnet.fi) + Assembler routines by Kimmo Kinnunen +*/ + + + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> + +extern "C" { +#include "SDL_error.h" +#include "SDL_timer.h" +#include "SDL_video.h" +#undef NULL +#include "SDL_pixels_c.h" +#include "SDL.h" +}; + +#include "SDL_epocvideo.h" +#include "SDL_epocevents_c.h" + +#include "sdl_epocruntime.h" + +#include <hal.h> +#include <coedef.h> +#include <flogger.h> + +#ifdef SYMBIAN_QUARTZ +SDL_VideoDevice* _thisDevice; +#endif + +_LIT(KLibName, "SDL"); + +/* For debugging */ + +//if old SOS, from 7.x this is public! +class CLockable : public CFbsBitmap + { + public: + static CLockable* Lockable(CFbsBitmap* aBmp) {return static_cast<CLockable*>(aBmp);} + void Lock() {LockHeap();} + void Unlock() {UnlockHeap();} + }; +#define LockHeap(x) CLockable::Lockable(x)->Lock() +#define UnlockHeap(x) CLockable::Lockable(x)->Unlock() + +void RDebug_Print_b(char* error_str, void* param) + { + TBuf8<128> error8((TUint8*)error_str); + TBuf<128> error; + error.Copy(error8); + +#ifndef TRACE_TO_FILE + if (param) //!! Do not work if the parameter is really 0!! + RDebug::Print(error, param); + else + RDebug::Print(error); +#else + if (param) //!! Do not work if the parameter is really 0!! + RFileLogger::WriteFormat(KLibName, _L("SDL.txt"), EFileLoggingModeAppend, error, param); + else + RFileLogger::Write(KLibName, _L("SDL.txt"), EFileLoggingModeAppend, error); +#endif + + } + +extern "C" void RDebug_Print(char* error_str, void* param) + { + RDebug_Print_b(error_str, param); + } + + +int Debug_AvailMem2() + { + //User::CompressAllHeaps(); + TMemoryInfoV1Buf membuf; + User::LeaveIfError(UserHal::MemoryInfo(membuf)); + TMemoryInfoV1 minfo = membuf(); + return(minfo.iFreeRamInBytes); + } + +extern "C" int Debug_AvailMem() + { + return(Debug_AvailMem2()); + } + + +extern "C" { + +/* Initialization/Query functions */ + +static int EPOC_VideoInit(_THIS, SDL_PixelFormat *vformat); +static SDL_Rect **EPOC_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags); +static SDL_Surface *EPOC_SetVideoMode(_THIS, SDL_Surface *current, int width, int height, int bpp, Uint32 flags); +static int EPOC_SetColors(_THIS, int firstcolor, int ncolors, + SDL_Color *colors); +static void EPOC_VideoQuit(_THIS); + +/* Hardware surface functions */ + +static int EPOC_AllocHWSurface(_THIS, SDL_Surface *surface); +static int EPOC_LockHWSurface(_THIS, SDL_Surface *surface); +static int EPOC_FlipHWSurface(_THIS, SDL_Surface *surface); +static void EPOC_UnlockHWSurface(_THIS, SDL_Surface *surface); +static void EPOC_FreeHWSurface(_THIS, SDL_Surface *surface); +static void EPOC_DirectUpdate(_THIS, int numrects, SDL_Rect *rects); + +static int EPOC_Available(void); +static SDL_VideoDevice *EPOC_CreateDevice(int devindex); + +void DrawBackground(_THIS); +void DirectDraw(_THIS, int numrects, SDL_Rect *rects, TUint16* screenBuffer); +void DirectDrawRotated(_THIS, int numrects, SDL_Rect *rects, TUint16* screenBuffer); + +/* Mouse functions */ + +static WMcursor *EPOC_CreateWMCursor(_THIS, Uint8 *data, Uint8 *mask, int w, int h, int hot_x, int hot_y); +static void EPOC_FreeWMCursor(_THIS, WMcursor *cursor); +static int EPOC_ShowWMCursor(_THIS, WMcursor *cursor); + + + +/* !!For 12 bit screen HW. Table for fast conversion from 8 bit to 12 bit */ +// TUint16 is enough, but using TUint32 so we can use better instruction selection on ARMI +static TUint32 EPOC_HWPalette_256_to_Screen[256]; + +VideoBootStrap EPOC_bootstrap = { + "epoc", "EPOC system", + EPOC_Available, EPOC_CreateDevice +}; + +const TUint32 WindowClientHandle = 9210; //!! const + +/* Epoc video driver bootstrap functions */ + +static int EPOC_Available(void) +{ + return 1; /* Always available */ +} + +static void EPOC_DeleteDevice(SDL_VideoDevice *device) +{ + free(device->hidden); + free(device); +} + +static SDL_VideoDevice *EPOC_CreateDevice(int /*devindex*/) +{ + SDL_VideoDevice *device; + + SDL_TRACE("SDL:EPOC_CreateDevice"); + + /* Allocate all variables that we free on delete */ + device = (SDL_VideoDevice *)malloc(sizeof(SDL_VideoDevice)); + if ( device ) { + memset(device, 0, (sizeof *device)); + device->hidden = (struct SDL_PrivateVideoData *) + malloc((sizeof *device->hidden)); + } + if ( (device == NULL) || (device->hidden == NULL) ) { + SDL_OutOfMemory(); + if ( device ) { + free(device); + } + return(0); + } + memset(device->hidden, 0, (sizeof *device->hidden)); + + /* Set the function pointers */ + device->VideoInit = EPOC_VideoInit; + device->ListModes = EPOC_ListModes; + device->SetVideoMode = EPOC_SetVideoMode; + device->SetColors = EPOC_SetColors; + device->UpdateRects = NULL; + device->VideoQuit = EPOC_VideoQuit; + device->AllocHWSurface = EPOC_AllocHWSurface; + device->CheckHWBlit = NULL; + device->FillHWRect = NULL; + device->SetHWColorKey = NULL; + device->SetHWAlpha = NULL; + device->LockHWSurface = EPOC_LockHWSurface; + device->UnlockHWSurface = EPOC_UnlockHWSurface; + device->FlipHWSurface = EPOC_FlipHWSurface; + device->FreeHWSurface = EPOC_FreeHWSurface; + device->SetIcon = NULL; + device->SetCaption = NULL; + device->GetWMInfo = NULL; + device->FreeWMCursor = EPOC_FreeWMCursor; + device->CreateWMCursor = EPOC_CreateWMCursor; + device->ShowWMCursor = EPOC_ShowWMCursor; + device->WarpWMCursor = NULL; + device->InitOSKeymap = EPOC_InitOSKeymap; + device->PumpEvents = EPOC_PumpEvents; + device->free = EPOC_DeleteDevice; + + return device; +} + + +int GetBpp(TDisplayMode displaymode) +{ + /*TInt numColors = TDisplayModeUtils::NumDisplayModeColors(displaymode); + TInt bitsPerPixel = 1; + for (TInt32 i = 2; i < numColors; i <<= 1, bitsPerPixel++); + return bitsPerPixel;*/ + return TDisplayModeUtils::NumDisplayModeBitsPerPixel(displaymode); +} + + +void DisableKeyBlocking(_THIS) + { + // Disable key blocking + TRawEvent event; + event.Set((TRawEvent::TType)/*EDisableKeyBlock*/51); // !!EDisableKeyBlock not found in epoc32\include! + Private->EPOC_WsSession.SimulateRawEvent(event); + } + +void ConstructWindowL(_THIS) +{ + TInt error; + + SDL_TRACE("SDL:ConstructWindowL"); + error = Private->EPOC_WsSession.Connect(); + User::LeaveIfError(error); + Private->EPOC_WsScreen=new(ELeave) CWsScreenDevice(Private->EPOC_WsSession); + User::LeaveIfError(Private->EPOC_WsScreen->Construct()); + User::LeaveIfError(Private->EPOC_WsScreen->CreateContext(Private->EPOC_WindowGc)); + + Private->EPOC_WsWindowGroup=RWindowGroup(Private->EPOC_WsSession); + User::LeaveIfError(Private->EPOC_WsWindowGroup.Construct(WindowClientHandle)); + Private->EPOC_WsWindowGroup.SetOrdinalPosition(0); + + // Set window group name (the same as process name)) !!Gives always "EPOC" in WINS + RProcess thisProcess; + TParse exeName; + exeName.Set(thisProcess.FileName(), NULL, NULL); + TBuf<32> winGroupName; + winGroupName.Append(0); + winGroupName.Append(0); + winGroupName.Append(0);// uid + winGroupName.Append(0); + winGroupName.Append(exeName.Name()); // caption + winGroupName.Append(0); + winGroupName.Append(0); //doc name + Private->EPOC_WsWindowGroup.SetName(winGroupName); + + Private->EPOC_WsWindow=RWindow(Private->EPOC_WsSession); + // Markus, it was: + // User::LeaveIfError(Private->EPOC_WsWindow.Construct(Private->EPOC_WsWindowGroup,WindowClientHandle )); + // but SOS 7.0s debug does not accept same window handle twice + User::LeaveIfError(Private->EPOC_WsWindow.Construct(Private->EPOC_WsWindowGroup,WindowClientHandle - 1)); + Private->EPOC_WsWindow.SetBackgroundColor(KRgbWhite); + Private->EPOC_WsWindow.Activate(); + Private->EPOC_WsWindow.SetSize(Private->EPOC_WsScreen->SizeInPixels()); + Private->EPOC_WsWindow.SetVisible(ETrue); + + Private->EPOC_WsWindowGroupID = Private->EPOC_WsWindowGroup.Identifier(); + Private->EPOC_IsWindowFocused = EFalse; + + DisableKeyBlocking(_this); //disable key blocking +} + +int EPOC_VideoInit(_THIS, SDL_PixelFormat *vformat) +{ + // !!TODO:handle leave functions! + + int i; + + SDL_TRACE("SDL:EPOC_VideoInit"); + + /* Initialize all variables that we clean on shutdown */ + + for ( i=0; i<SDL_NUMMODES; ++i ) { + Private->SDL_modelist[i] = (SDL_Rect *)malloc(sizeof(SDL_Rect)); + Private->SDL_modelist[i]->x = Private->SDL_modelist[i]->y = 0; + } + + /* Modes sorted largest to smallest */ + Private->SDL_modelist[0]->w = 800; Private->SDL_modelist[0]->h = 250; + Private->SDL_modelist[1]->w = 640; Private->SDL_modelist[1]->h = 480; + Private->SDL_modelist[2]->w = 480; Private->SDL_modelist[2]->h = 600; + Private->SDL_modelist[3]->w = 640; Private->SDL_modelist[3]->h = 400; + Private->SDL_modelist[4]->w = 352; Private->SDL_modelist[4]->h = 416; + Private->SDL_modelist[5]->w = 416; Private->SDL_modelist[5]->h = 352; + Private->SDL_modelist[6]->w = 416; Private->SDL_modelist[6]->h = 312; + Private->SDL_modelist[7]->w = 352; Private->SDL_modelist[7]->h = 264; + Private->SDL_modelist[8]->w = 800; Private->SDL_modelist[8]->h = 240; //for doom all these.. + Private->SDL_modelist[9]->w = 640; Private->SDL_modelist[9]->h = 240; + Private->SDL_modelist[10]->w = 480; Private->SDL_modelist[10]->h = 240; + Private->SDL_modelist[11]->w = 640; Private->SDL_modelist[11]->h = 240; + Private->SDL_modelist[12]->w = 352; Private->SDL_modelist[12]->h = 240; + Private->SDL_modelist[13]->w = 416; Private->SDL_modelist[13]->h = 240; + Private->SDL_modelist[14]->w = 416; Private->SDL_modelist[14]->h = 240; + Private->SDL_modelist[15]->w = 352; Private->SDL_modelist[15]->h = 240; + Private->SDL_modelist[16]->w = 640; Private->SDL_modelist[16]->h = 200; + Private->SDL_modelist[17]->w = 320; Private->SDL_modelist[17]->h = 240; //...for doom, currently engine renders no-higher windows :-(, propably should get fixed + Private->SDL_modelist[18]->w = 320; Private->SDL_modelist[18]->h = 200; + Private->SDL_modelist[19]->w = 256; Private->SDL_modelist[19]->h = 192; + Private->SDL_modelist[20]->w = 176; Private->SDL_modelist[20]->h = 208; + Private->SDL_modelist[21]->w = 208; Private->SDL_modelist[21]->h = 176; // Rotated + Private->SDL_modelist[22]->w = 160; Private->SDL_modelist[22]->h = 144; + + Private->SDL_modelist[23]->w = 640; Private->SDL_modelist[2]->h = 200; //s80 some new modes + Private->SDL_modelist[24]->w = 640; Private->SDL_modelist[2]->h = 320; //s90 modes are added + Private->SDL_modelist[25]->w = 640; Private->SDL_modelist[2]->h = 240; //here + Private->SDL_modelist[26]->w = 640; Private->SDL_modelist[4]->h = 200; //now + + Private->SDL_modelist[27] = NULL; + + /* Construct Epoc window */ + + ConstructWindowL(_this); + + /* Initialise Epoc frame buffer */ + + TDisplayMode displayMode = Private->EPOC_WsScreen->DisplayMode(); + +#if !defined(__WINS__) && !defined(TEST_BM_DRAW) + + TScreenInfoV01 screenInfo; + TPckg<TScreenInfoV01> sInfo(screenInfo); + UserSvr::ScreenInfo(sInfo); + + Private->EPOC_ScreenSize = screenInfo.iScreenSize; + Private->EPOC_DisplayMode = displayMode; + Private->EPOC_HasFrameBuffer = screenInfo.iScreenAddressValid; + Private->EPOC_FrameBuffer = Private->EPOC_HasFrameBuffer ? (TUint8*) screenInfo.iScreenAddress : NULL; + Private->EPOC_BytesPerPixel = ((GetBpp(displayMode)-1) / 8) + 1; + + Private->EPOC_BytesPerScanLine = screenInfo.iScreenSize.iWidth * Private->EPOC_BytesPerPixel; + Private->EPOC_BytesPerScreen = Private->EPOC_BytesPerScanLine * Private->EPOC_ScreenSize.iHeight; + + SDL_TRACE1("Screen width %d", screenInfo.iScreenSize.iWidth); + SDL_TRACE1("Screen height %d", screenInfo.iScreenSize.iHeight); + SDL_TRACE1("Screen dmode %d", displayMode); + SDL_TRACE1("Screen valid %d", screenInfo.iScreenAddressValid); + + SDL_TRACE1("bpp %d", Private->EPOC_BytesPerPixel); + SDL_TRACE1("bpsl %d", Private->EPOC_BytesPerScanLine); + SDL_TRACE1("bps %d", Private->EPOC_BytesPerScreen); + + + /* It seems that in SA1100 machines for 8bpp displays there is a 512 palette table at the + * beginning of the frame buffer. E.g. Series 7 and Netbook. + * In 12 bpp machines the table has 16 entries. + */ + if (Private->EPOC_HasFrameBuffer && GetBpp(displayMode) == 8) + { + Private->EPOC_FrameBuffer += 512; + } + else + { + Private->EPOC_FrameBuffer += 32; + } + /*if (Private->EPOC_HasFrameBuffer && GetBpp(displayMode) == 12) + Private->EPOC_FrameBuffer += 16 * 2; + if (Private->EPOC_HasFrameBuffer && GetBpp(displayMode) == 16) + Private->EPOC_FrameBuffer += 16 * 2; + */ +#else /* defined __WINS__ */ + + /* Create bitmap, device and context for screen drawing */ + Private->EPOC_ScreenSize = Private->EPOC_WsScreen->SizeInPixels(); + + Private->EPOC_Bitmap = new (ELeave) CWsBitmap(Private->EPOC_WsSession); + Private->EPOC_Bitmap->Create(Private->EPOC_ScreenSize, displayMode); + + Private->EPOC_DisplayMode = displayMode; + Private->EPOC_HasFrameBuffer = ETrue; + Private->EPOC_FrameBuffer = NULL; /* Private->EPOC_Bitmap->DataAddress() can change any time */ + Private->EPOC_BytesPerPixel = ((GetBpp(displayMode)-1) / 8) + 1; + Private->EPOC_BytesPerScanLine = Private->EPOC_WsScreen->SizeInPixels().iWidth * Private->EPOC_BytesPerPixel; + +#endif /* __WINS__ */ + +#ifndef SYMBIAN_CRYSTAL + // Get draw device for updating the screen + TScreenInfoV01 screenInfo2; + + Epoc_Runtime::GetScreenInfo(screenInfo2); + + TRAPD(status, Private->EPOC_DrawDevice = CFbsDrawDevice::NewScreenDeviceL(screenInfo2, displayMode)); + User::LeaveIfError(status); +#endif + + /* The "best" video format should be returned to caller. */ + + vformat->BitsPerPixel = /*!!GetBpp(displayMode) */ 8; + vformat->BytesPerPixel = /*!!Private->EPOC_BytesPerPixel*/ 1; + + /* Activate events for me */ + + Private->EPOC_WsEventStatus = KRequestPending; + Private->EPOC_WsSession.EventReady(&Private->EPOC_WsEventStatus); + + SDL_TRACE("SDL:WsEventStatus"); + User::WaitForRequest(Private->EPOC_WsEventStatus); //Markus: I added this and ... + + Private->EPOC_RedrawEventStatus = KRequestPending; + Private->EPOC_WsSession.RedrawReady(&Private->EPOC_RedrawEventStatus); + + SDL_TRACE("SDL:RedrawEventStatus"); + User::WaitForRequest(Private->EPOC_RedrawEventStatus); //...this, if not catches a stray event is risen + //if there are active objects used, or confucing + //actions with User::WaitForAnyRequest + Private->EPOC_WsWindow.PointerFilter(EPointerFilterDrag, 0); + + Private->EPOC_ScreenOffset = TPoint(0, 0); + +#if defined(__WINS__) || defined(TEST_BM_DRAW) + LockHeap(Private->EPOC_Bitmap); // Lock bitmap heap +#endif + + SDL_TRACE("SDL:DrawBackground"); + DrawBackground(_this); // Clear screen + +#if defined(__WINS__) || defined(TEST_BM_DRAW) + UnlockHeap(Private->EPOC_Bitmap); // Unlock bitmap heap +#endif + //!! TODO: error handling + //if (ret != KErrNone) + // return(-1); + //else + return(0); +} + + +SDL_Rect **EPOC_ListModes(_THIS, SDL_PixelFormat *format, Uint32 /*flags*/) +{ + if (format->BitsPerPixel == 12 || format->BitsPerPixel == 8) + return Private->SDL_modelist; + return NULL; +} + +int EPOC_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors) +{ + if ((firstcolor+ncolors) > 256) + return -1; +// SDL_TRACE1("colors %d", (TDisplayModeUtils::NumDisplayModeColors(Private->EPOC_DisplayMode))); + if(TDisplayModeUtils::NumDisplayModeColors(Private->EPOC_DisplayMode) == 4096) + { + // Set 12 bit palette + for(int i = firstcolor; i < ncolors; i++) + { + // 4k value: 0000 rrrr gggg bbbb + TUint32 color4K = (colors[i].r & 0x0000f0) << 4; + color4K |= (colors[i].g & 0x0000f0); + color4K |= (colors[i].b & 0x0000f0) >> 4; + EPOC_HWPalette_256_to_Screen[i] = color4K; + } + } + else if(TDisplayModeUtils::NumDisplayModeColors(Private->EPOC_DisplayMode) == 65536) + { + for(int i = firstcolor; i < ncolors; i++) + { + // 64k-colour displays effectively support RGB values + // with 5 bits allocated to red, 6 to green and 5 to blue + // 64k value: rrrr rggg gggb bbbb + TUint32 color64K = (colors[i].r & 0x0000f8) << 8; + color64K |= (colors[i].g & 0x0000fc) << 3; + color64K |= (colors[i].b & 0x0000f8) >> 3; + EPOC_HWPalette_256_to_Screen[i] = color64K; + } + } + else if(TDisplayModeUtils::NumDisplayModeColors(Private->EPOC_DisplayMode) == 16777216) + { + for(int i = firstcolor; i < ncolors; i++) + { + // 16M-colour + //0000 0000 rrrr rrrr gggg gggg bbbb bbbb + TUint32 color16M = colors[i].r << 16; + color16M |= colors[i].g << 8; + color16M |= colors[i].b; + EPOC_HWPalette_256_to_Screen[i] = color16M; + } + } + else + { + return -2; + } + return(0); +} + + +SDL_Surface *EPOC_SetVideoMode(_THIS, SDL_Surface *current, + int width, int height, int bpp, Uint32 /*flags*/) +{ + SDL_TRACE("SDL:EPOC_SetVideoMode"); + /* Check parameters */ +#ifdef SYMBIAN_CRYSTAL + if (! (bpp == 8 || bpp == 12 || bpp == 16) && + ( + (width == 640 && height == 200) || + (width == 640 && height == 400) || + (width == 640 && height == 480) || + (width == 320 && height == 200) || + (width == 320 && height == 240) + )) { + SDL_SetError("Requested video mode is not supported"); + return NULL; + } +#else // SYMBIAN_SERIES60 + if (! (bpp == 8 || bpp == 12 || bpp == 16) && + ( + (width == 320 && height == 200) || + (width == 320 && height == 240) || + (width == 256 && height == 192) || + (width == 176 && height == 208) || + (width == 208 && height == 176) || // Rotated + (width == 160 && height == 144) + )) { + SDL_SetError("Requested video mode is not supported"); + return NULL; + } +#endif + + if (current && current->pixels) { + free(current->pixels); + current->pixels = NULL; + } + if ( ! SDL_ReallocFormat(current, bpp, 0, 0, 0, 0) ) { + return(NULL); + } + + /* Set up the new mode framebuffer */ + if (bpp == 8) + current->flags = (SDL_FULLSCREEN|SDL_SWSURFACE|SDL_PREALLOC|SDL_HWPALETTE); + else // 12 bpp, 16 bpp + current->flags = (SDL_FULLSCREEN|SDL_SWSURFACE|SDL_PREALLOC); + current->w = width; + current->h = height; + int numBytesPerPixel = ((bpp-1)>>3) + 1; + current->pitch = numBytesPerPixel * width; // Number of bytes in scanline + current->pixels = malloc(width * height * numBytesPerPixel); + memset(current->pixels, 0, width * height * numBytesPerPixel); + + /* Set the blit function */ + _this->UpdateRects = EPOC_DirectUpdate; + + /* + * Logic for getting suitable screen dimensions, offset, scaling and orientation + */ + + int w = current->w; + int h = current->h; + + // Rotate, if the screen does not fit horizontally and it is landscape screen +/* + if ((width>Private->EPOC_ScreenSize.iWidth) && (width>height)) { + Private->EPOC_ScreenOrientation = CFbsBitGc::EGraphicsOrientationRotated270; + w = current->h; + h = current->w; + } +*/ + // Get nearest stepwise scale values for width and height. The smallest supported scaled screen is 1/2. + TInt scaleValue = 0; + Private->EPOC_ScreenXScaleValue = 1; + Private->EPOC_ScreenYScaleValue = 1; + if (w > Private->EPOC_ScreenSize.iWidth) { + // Find the biggest scale value that result the width that fits in the screen HW + for (scaleValue = 2; scaleValue++;) { + TInt scaledWidth = (w * (scaleValue-1))/scaleValue; + if (scaledWidth > Private->EPOC_ScreenSize.iWidth) + break; + } + Private->EPOC_ScreenXScaleValue = Max(2, scaleValue - 1); + w = (w * (Private->EPOC_ScreenXScaleValue-1))/Private->EPOC_ScreenXScaleValue; + } + if (h > Private->EPOC_ScreenSize.iHeight) { + // Find the biggest scale value that result the height that fits in the screen HW + for (scaleValue = 2; scaleValue++;) { + TInt scaledHeight = (h * (scaleValue-1))/scaleValue; + if (scaledHeight > Private->EPOC_ScreenSize.iHeight) + break; + } + Private->EPOC_ScreenYScaleValue = Max(2, scaleValue - 1); + h = (h * (Private->EPOC_ScreenYScaleValue-1))/Private->EPOC_ScreenYScaleValue; + } + + /* Centralize game window on device screen */ + Private->EPOC_ScreenOffset.iX = (Private->EPOC_ScreenSize.iWidth - w) / 2; + if (Private->EPOC_ScreenOffset.iX < 0) + Private->EPOC_ScreenOffset.iX = 0; + Private->EPOC_ScreenOffset.iY = (Private->EPOC_ScreenSize.iHeight - h) / 2; + if (Private->EPOC_ScreenOffset.iY < 0) + Private->EPOC_ScreenOffset.iY = 0; + + + SDL_TRACE1("View width %d", w); + SDL_TRACE1("View height %d", h); + SDL_TRACE1("View bmode %d", bpp); + SDL_TRACE1("View s %d", scaleValue); + SDL_TRACE1("View x %d", Private->EPOC_ScreenOffset.iX); + SDL_TRACE1("View y %d", Private->EPOC_ScreenOffset.iY); + + /* We're done */ + return(current); +} + + +void RedrawWindowL(_THIS) +{ + +#if defined(__WINS__) || defined(TEST_BM_DRAW) + LockHeap(Private->EPOC_Bitmap); // Lock bitmap heap + Private->EPOC_WindowGc->Activate(Private->EPOC_WsWindow); +#endif + + int w = _this->screen->w; + int h = _this->screen->h; + if (Private->EPOC_ScreenOrientation == CFbsBitGc::EGraphicsOrientationRotated270) { + w = _this->screen->h; + h = _this->screen->w; + } + if ((w < Private->EPOC_ScreenSize.iWidth) + || (h < Private->EPOC_ScreenSize.iHeight)) { + DrawBackground(_this); + } + + /* Tell the system that something has been drawn */ + TRect rect = TRect(Private->EPOC_WsWindow.Size()); + Private->EPOC_WsWindow.Invalidate(rect); + +#if defined(__WINS__) || defined(TEST_BM_DRAW) + Private->EPOC_WsWindow.BeginRedraw(rect); + Private->EPOC_WindowGc->BitBlt(TPoint(), Private->EPOC_Bitmap); + Private->EPOC_WsWindow.EndRedraw(); + Private->EPOC_WindowGc->Deactivate(); + UnlockHeap(Private->EPOC_Bitmap);; // Unlock bitmap heap + Private->EPOC_WsSession.Flush(); +#endif + + /* Draw current buffer */ + SDL_Rect fullScreen; + fullScreen.x = 0; + fullScreen.y = 0; + fullScreen.w = _this->screen->w; + fullScreen.h = _this->screen->h; + EPOC_DirectUpdate(_this, 1, &fullScreen); +} + + +void DrawBackground(_THIS) +{ + /* Draw background */ +#if defined(__WINS__) || defined(TEST_BM_DRAW) + //warning heap is not locked! - a function calling must ensure that it's ok + TUint16* screenBuffer = (TUint16*)Private->EPOC_Bitmap->DataAddress(); +#else + TUint16* screenBuffer = (TUint16*)Private->EPOC_FrameBuffer; +#endif + // Draw black background + Mem::FillZ(screenBuffer, Private->EPOC_BytesPerScreen); + +#if 0 + for (int y = 0; y < Private->EPOC_ScreenSize.iHeight; y++) { + for (int x = 0; x < Private->EPOC_ScreenSize.iWidth; x++) { +#ifdef SYMBIAN_CRYSTAL + const TUint16 color = 0; // ((x+y)>>1) & 0xf; /* Draw blue stripes pattern, because in e.g. 320x200 mode there is a big background area*/ +#else // SYMBIAN_SERIES60 + const TUint16 color = 0; /* Draw black background */ +#endif + *screenBuffer++ = color; + } + } +#endif +} + + +/* We don't actually allow hardware surfaces other than the main one */ +static int EPOC_AllocHWSurface(_THIS, SDL_Surface* /*surface*/) +{ + return(-1); +} +static void EPOC_FreeHWSurface(_THIS, SDL_Surface* /*surface*/) +{ + return; +} + +static int EPOC_LockHWSurface(_THIS, SDL_Surface* /*surface*/) +{ + return(0); +} +static void EPOC_UnlockHWSurface(_THIS, SDL_Surface* /*surface*/) +{ + return; +} + +static int EPOC_FlipHWSurface(_THIS, SDL_Surface* /*surface*/) +{ + return(0); +} + +static void EPOC_DirectUpdate(_THIS, int numrects, SDL_Rect *rects) +{ + //TInt focusWindowGroupId = Private->EPOC_WsSession.GetFocusWindowGroup();//these are async services + // if (focusWindowGroupId != Private->EPOC_WsWindowGroupID) { //for that cannot be called from + //SDL threads ??? + if (!Private->EPOC_IsWindowFocused) + { + /* Force focus window to redraw again for cleaning away SDL screen graphics */ +/* + TInt pos = Private->EPOC_WsWindowGroup.OrdinalPosition(); + Private->EPOC_WsWindowGroup.SetOrdinalPosition(0, KMaxTInt); + TRect rect = TRect(Private->EPOC_WsWindow.Size()); + Private->EPOC_WsWindow.Invalidate(rect); + Private->EPOC_WsWindowGroup.SetOrdinalPosition(pos, ECoeWinPriorityNormal); + */ /* If this is not the topmost window, wait here! Sleep for 1 second to give cpu time to + multitasking and poll for being the topmost window. + */ + // if (Private->EPOC_WsSession.GetFocusWindowGroup() != Private->EPOC_WsWindowGroupID) { + + /* !!TODO: Could call GetRedraw() etc. for WsSession and redraw the screen if needed. That might be + needed if a small dialog comes in front of Game screen. + */ + // while (Private->EPOC_WsSession.GetFocusWindowGroup() != Private->EPOC_WsWindowGroupID) + + SDL_PauseAudio(1); + SDL_Delay(1000); + return; + // } + + // RedrawWindowL(_this); + } + + SDL_PauseAudio(0); + + // if we are not focused, do not draw +// if (!Private->EPOC_IsWindowFocused) +// return; +#if defined(__WINS__) || defined(TEST_BM_DRAW) + TBitmapUtil lock(Private->EPOC_Bitmap); + lock.Begin(TPoint(0,0)); // Lock bitmap heap + Private->EPOC_WindowGc->Activate(Private->EPOC_WsWindow); + TUint16* screenBuffer = (TUint16*)Private->EPOC_Bitmap->DataAddress(); +#else + TUint16* screenBuffer = (TUint16*)Private->EPOC_FrameBuffer; +#endif + + if (Private->EPOC_ScreenOrientation == CFbsBitGc::EGraphicsOrientationRotated270) + DirectDrawRotated(_this, numrects, rects, screenBuffer); + else + DirectDraw(_this, numrects, rects, screenBuffer); + + +#if defined(__WINS__) || defined(TEST_BM_DRAW) + + TRect rect = TRect(Private->EPOC_WsWindow.Size()); + Private->EPOC_WsWindow.Invalidate(rect); + Private->EPOC_WsWindow.BeginRedraw(rect); + Private->EPOC_WindowGc->BitBlt(TPoint(), Private->EPOC_Bitmap); + Private->EPOC_WsWindow.EndRedraw(); + Private->EPOC_WindowGc->Deactivate(); + lock.End(); // Unlock bitmap heap + Private->EPOC_WsSession.Flush(); +#else +#ifndef SYMBIAN_CRYSTAL + // This is not needed in Crystal. What is the performance penalty in SERIES60? + TRect rect2 = TRect(Private->EPOC_WsWindow.Size()); + + Private->EPOC_DrawDevice->UpdateRegion(rect2); // Should we update rects parameter area only?? + Private->EPOC_DrawDevice->Update(); +#endif +#endif + + /* Update virtual cursor. !!Do not yet work properly + Private->EPOC_WsSession.SetPointerCursorPosition(Private->EPOC_WsSession.PointerCursorPosition()); + */ + + /*static int foo = 1; + + for ( int i=0; i < numrects; ++i ) { + const SDL_Rect& currentRect = rects[i]; + SDL_Rect rect2; + rect2.x = currentRect.x; + rect2.y = currentRect.y; + rect2.w = currentRect.w; + rect2.h = currentRect.h; + + if (rect2.w <= 0 || rect2.h <= 0) + continue; + + + foo++; + if((foo % 200) == 0) + { + SDL_TRACE1("foo %d", foo); + CFbsBitmap* b = new (ELeave) CFbsBitmap; + SDL_TRACE1("bee %d", (int)b); + int e = b->Create(TSize(currentRect.w, currentRect.h), Private->EPOC_DisplayMode); + + SDL_TRACE1("err %d", e); + if(e != KErrNone) + User::Panic(_L("damn"), e); + + TBitmapUtil u(b); + u.Begin(TPoint(0, 0)); + TUint32* d = b->DataAddress(); + + SDL_TRACE1("addr %d", (int)d); + + for(TInt o = 0; o < currentRect.h; o++) + for(TInt p = 0; p < currentRect.w; p++) + { + u.SetPos(TPoint(p, o)); + u.SetPixel(0xFFFF); + } + + SDL_TRACE1("w %d", (int)currentRect.w); + SDL_TRACE1("h %d", (int)currentRect.h); + + SDL_TRACE1("addr %d", (int)Private->EPOC_DisplayMode); + + + const TUint f = (TUint)Private->EPOC_FrameBuffer; + const TUint y = (TUint)Private->EPOC_BytesPerScreen; + + + SDL_TRACE1("frame %u", f); + SDL_TRACE1("bytes %u", y); + + Mem::Copy(d, Private->EPOC_FrameBuffer, Private->EPOC_BytesPerScreen); + + SDL_TRACE("kopied"); + + u.End(); + TBuf<32> name; + name.Format(_L("C:\\nokia\\images\\doom%d.mbm"), (foo / 200)); + e= b->Save(name); + if(e != KErrNone) + User::Panic(_L("damned"), e); + delete b; + }}*/ +} + + +void DirectDraw(_THIS, int numrects, SDL_Rect *rects, TUint16* screenBuffer) +{ + TInt i; + + const TInt sourceNumBytesPerPixel = ((_this->screen->format->BitsPerPixel-1)>>3) + 1; + const TPoint fixedOffset = Private->EPOC_ScreenOffset; + const TInt screenW = _this->screen->w; + const TInt screenH = _this->screen->h; + const TInt sourceScanlineLength = screenW; + const TInt targetScanlineLength = Private->EPOC_ScreenSize.iWidth; + + /* Render the rectangles in the list */ + + for ( i=0; i < numrects; ++i ) { + const SDL_Rect& currentRect = rects[i]; + SDL_Rect rect2; + rect2.x = currentRect.x; + rect2.y = currentRect.y; + rect2.w = currentRect.w; + rect2.h = currentRect.h; + + if (rect2.w <= 0 || rect2.h <= 0) /* sanity check */ + continue; + + /* All variables are measured in pixels */ + + /* Check rects validity, i.e. upper and lower bounds */ + TInt maxX = Min(screenW - 1, rect2.x + rect2.w - 1); + TInt maxY = Min(screenH - 1, rect2.y + rect2.h - 1); + if (maxX < 0 || maxY < 0) /* sanity check */ + continue; + /* Clip from bottom */ + maxY = Min(maxY, Private->EPOC_ScreenSize.iHeight-1); + /* TODO: Clip from the right side */ + + const TInt sourceRectWidth = maxX - rect2.x + 1; + const TInt sourceRectWidthInBytes = sourceRectWidth * sourceNumBytesPerPixel; + const TInt sourceRectHeight = maxY - rect2.y + 1; + const TInt sourceStartOffset = rect2.x + rect2.y * sourceScanlineLength; + const TUint skipValue = 1; // no skip + + TInt targetStartOffset = fixedOffset.iX + rect2.x + (fixedOffset.iY +rect2.y) * targetScanlineLength; + + // Nokia7650 native mode: 12 bpp --> 12 bpp + // + + switch (_this->screen->format->BitsPerPixel) + { + case 12: + { + TUint16* bitmapLine = (TUint16*)_this->screen->pixels + sourceStartOffset; + TUint16* screenMemory = screenBuffer + targetStartOffset; + if (skipValue == 1) + { + for(TInt y = 0 ; y < sourceRectHeight ; y++) + { + Mem::Copy(screenMemory, bitmapLine, sourceRectWidthInBytes); + } + bitmapLine += sourceScanlineLength; + screenMemory += targetScanlineLength; + } + else + { + for(TInt y = 0 ; y < sourceRectHeight ; y++) + { + //TODO: optimize: separate loops for 1, 2 and n skip. Mem::Copy() can be used in unscaled case. + TUint16* bitmapPos = bitmapLine; /* 2 bytes per pixel */ + TUint16* screenMemoryLinePos = screenMemory; /* 2 bytes per pixel */ + for(TInt x = 0 ; x < sourceRectWidth ; x++) + { + __ASSERT_DEBUG(screenMemory < (screenBuffer + Private->EPOC_ScreenSize.iWidth * Private->EPOC_ScreenSize.iHeight), User::Panic(_L("SDL"), KErrCorrupt)); + __ASSERT_DEBUG(screenMemory >= screenBuffer, User::Panic(_L("SDL"), KErrCorrupt)); + __ASSERT_DEBUG(bitmapLine < ((TUint16*)_this->screen->pixels + (_this->screen->w * _this->screen->h)), User::Panic(_L("SDL"), KErrCorrupt)); + __ASSERT_DEBUG(bitmapLine >= (TUint16*)_this->screen->pixels, User::Panic(_L("SDL"), KErrCorrupt)); + + *screenMemoryLinePos++ = *bitmapPos; + bitmapPos+=skipValue; + } + bitmapLine += sourceScanlineLength; + screenMemory += targetScanlineLength; + } + } + } + break; + // 256 color paletted mode: 8 bpp --> 12 bpp + // + default: + { + if(Private->EPOC_BytesPerPixel <= 2) + { + TUint8* bitmapLine = (TUint8*)_this->screen->pixels + sourceStartOffset; + TUint16* screenMemory = screenBuffer + targetStartOffset; + for(TInt y = 0 ; y < sourceRectHeight ; y++) + { + TUint8* bitmapPos = bitmapLine; /* 1 byte per pixel */ + TUint16* screenMemoryLinePos = screenMemory; /* 2 bytes per pixel */ + /* Convert each pixel from 256 palette to 4k color values */ + for(TInt x = 0 ; x < sourceRectWidth ; x++) + { + __ASSERT_DEBUG(screenMemoryLinePos < (screenBuffer + (Private->EPOC_ScreenSize.iWidth * Private->EPOC_ScreenSize.iHeight)), User::Panic(_L("SDL"), KErrCorrupt)); + __ASSERT_DEBUG(screenMemoryLinePos >= screenBuffer, User::Panic(_L("SDL"), KErrCorrupt)); + __ASSERT_DEBUG(bitmapPos < ((TUint8*)_this->screen->pixels + (_this->screen->w * _this->screen->h)), User::Panic(_L("SDL"), KErrCorrupt)); + __ASSERT_DEBUG(bitmapPos >= (TUint8*)_this->screen->pixels, User::Panic(_L("SDL"), KErrCorrupt)); + *screenMemoryLinePos++ = EPOC_HWPalette_256_to_Screen[*bitmapPos++]; + // bitmapPos+=skipValue; //TODO: optimize: separate loops for 1, 2 and n skip + } + bitmapLine += sourceScanlineLength; + screenMemory += targetScanlineLength; + } + } + else + { + TUint8* bitmapLine = (TUint8*)_this->screen->pixels + sourceStartOffset; + TUint32* screenMemory = reinterpret_cast<TUint32*>(screenBuffer + targetStartOffset); + for(TInt y = 0 ; y < sourceRectHeight ; y++) + { + TUint8* bitmapPos = bitmapLine; /* 1 byte per pixel */ + TUint32* screenMemoryLinePos = screenMemory; /* 2 bytes per pixel */ + /* Convert each pixel from 256 palette to 4k color values */ + for(TInt x = 0 ; x < sourceRectWidth ; x++) + { + __ASSERT_DEBUG(screenMemoryLinePos < (reinterpret_cast<TUint32*>(screenBuffer) + (Private->EPOC_ScreenSize.iWidth * Private->EPOC_ScreenSize.iHeight)), User::Panic(_L("SDL"), KErrCorrupt)); + __ASSERT_DEBUG(screenMemoryLinePos >= reinterpret_cast<TUint32*>(screenBuffer), User::Panic(_L("SDL"), KErrCorrupt)); + __ASSERT_DEBUG(bitmapPos < ((TUint8*)_this->screen->pixels + (_this->screen->w * _this->screen->h)), User::Panic(_L("SDL"), KErrCorrupt)); + __ASSERT_DEBUG(bitmapPos >= (TUint8*)_this->screen->pixels, User::Panic(_L("SDL"), KErrCorrupt)); + *screenMemoryLinePos++ = EPOC_HWPalette_256_to_Screen[*bitmapPos++]; + // bitmapPos+=skipValue; //TODO: optimize: separate loops for 1, 2 and n skip + } + bitmapLine += sourceScanlineLength; + screenMemory += targetScanlineLength; + } + } + } + } // switch + } // for +} + +/* +void DirectDraw(_THIS, int numrects, SDL_Rect *rects, TUint16* screenBuffer) +{ + TInt i; + const TInt sourceNumBytesPerPixel = ((_this->screen->format->BitsPerPixel-1)>>3) + 1; + const TPoint fixedOffset = Private->EPOC_ScreenOffset; + const TInt screenW = _this->screen->w; + const TInt screenH = _this->screen->h; + const TInt sourceScanlineLength = screenW; + const TInt targetScanlineLength = Private->EPOC_ScreenSize.iWidth; + + /* Render the rectangles in the list */ + +/* for ( i=0; i < numrects; ++i ) { + const SDL_Rect& currentRect = rects[i]; + SDL_Rect rect2; + rect2.x = currentRect.x; + rect2.y = currentRect.y; + rect2.w = currentRect.w; + rect2.h = currentRect.h; + + if (rect2.w <= 0 || rect2.h <= 0) /* sanity check */ +/* continue; + + /* All variables are measured in pixels */ + + /* Check rects validity, i.e. upper and lower bounds */ +/* TInt maxX = Min(screenW - 1, rect2.x + rect2.w - 1); + TInt maxY = Min(screenH - 1, rect2.y + rect2.h - 1); + if (maxX < 0 || maxY < 0) /* sanity check */ +/* continue; + /* Clip from bottom */ +/* maxY = Min(maxY, Private->EPOC_ScreenSize.iHeight-1); + /* TODO: Clip from the right side */ + +/* TInt sourceRectWidth = maxX - rect2.x + 1; + const TInt sourceRectWidthInBytes = sourceRectWidth * sourceNumBytesPerPixel; + const TInt sourceRectHeight = maxY - rect2.y + 1; + const TInt sourceStartOffset = rect2.x + rect2.y * sourceScanlineLength; + const TUint skipValue = Private->EPOC_ScreenXScaleValue; //1; // no skip + + const TInt targetStartOffset = // = (fixedOffset.iX + (rect2.x / skipValue) + (fixedOffset.iY + rect2.y) * targetScanlineLength ) ; + (skipValue > 1 ? + (fixedOffset.iX + (rect2.x / skipValue) + (fixedOffset.iY + rect2.y) * targetScanlineLength ) : + (fixedOffset.iX + rect2.x + (fixedOffset.iY + rect2.y) * targetScanlineLength )); + + __ASSERT_DEBUG(skipValue >= 1, User::Panic(KLibName, KErrArgument)); + + // Nokia7650 native mode: 12 bpp --> 12 bpp + // + switch (_this->screen->format->BitsPerPixel) + { + case 12: + { + TUint16* bitmapLine = (TUint16*)_this->screen->pixels + sourceStartOffset; + TUint16* screenMemory = screenBuffer + targetStartOffset; + if (skipValue == 1) + { + for(TInt y = 0 ; y < sourceRectHeight ; y++) + { + Mem::Copy(screenMemory, bitmapLine, sourceRectWidthInBytes); + } + bitmapLine += sourceScanlineLength; + screenMemory += targetScanlineLength; + } + else + { + for(TInt y = 0 ; y < sourceRectHeight ; y++) + { + //TODO: optimize: separate loops for 1, 2 and n skip. Mem::Copy() can be used in unscaled case. + TUint16* bitmapPos = bitmapLine; /* 2 bytes per pixel */ +/* TUint16* screenMemoryLinePos = screenMemory; /* 2 bytes per pixel */ +/* for(TInt x = 0 ; x < sourceRectWidth ; x++) + { + __ASSERT_DEBUG(screenMemory < (screenBuffer + Private->EPOC_ScreenSize.iWidth * Private->EPOC_ScreenSize.iHeight), User::Panic(KLibName, KErrCorrupt)); + __ASSERT_DEBUG(screenMemory >= screenBuffer, User::Panic(KLibName, KErrCorrupt)); + __ASSERT_DEBUG(bitmapLine < ((TUint16*)_this->screen->pixels + (_this->screen->w * _this->screen->h)), User::Panic(KLibName, KErrCorrupt)); + __ASSERT_DEBUG(bitmapLine >= (TUint16*)_this->screen->pixels, User::Panic(KLibName, KErrCorrupt)); + + *screenMemoryLinePos++ = *bitmapPos; + bitmapPos+=skipValue; + } + bitmapLine += sourceScanlineLength; + screenMemory += targetScanlineLength; + } + } + } + break; + // 256 color paletted mode: 8 bpp --> 12 bpp + // + default: + { + TUint8* bitmapLine = (TUint8*)_this->screen->pixels + sourceStartOffset; + TUint16* screenMemory = screenBuffer + targetStartOffset; + if (skipValue > 1) + sourceRectWidth /= skipValue; +#if defined __MARM_ARMI__ + __asm volatile(" + mov %4, %4, lsl #1 @ targetScanLineLength is in pixels, we need it in bytes + 1: + mov r6, %0 @ bitmapLine + mov r7, %2 @ screenMemory + mov r8, %6 @ sourceRectWidth + 2: + ldrb r4, [%0], %7 @ r4 = *bitmapPos; bitmapPos += skipValue + ldr r5, [%1, r4, lsl #2] @ only 16 lower bits actually used + subs r8, r8, #1 @ x-- + strh r5, [%2], #2 @ *screenMemoryLinePos++ = r4 + bne 2b + + add %0, r6, %3 @ bitmapLine += sourceScanlineLength + add %2, r7, %4 @ screenMemory += targetScanlineLength + subs %5, %5, #1 @ sourceRectHeight-- + bne 1b + " + : // no output + // %0 %1 %2 %3 %4 %5 %6 %7 + : "r" (bitmapLine), "r" (&EPOC_HWPalette_256_to_Screen[0]), "r" (screenMemory), "r" (sourceScanlineLength), "r" (targetScanlineLength), "r" (sourceRectHeight), "r" (sourceRectWidth), "r" (skipValue) + : "r4", "r5", "r6", "r7", "r8" + ); +#else + for(TInt y = 0 ; y < sourceRectHeight ; y++) + { + TUint8* bitmapPos = bitmapLine; /* 1 byte per pixel */ +/* TUint16* screenMemoryLinePos = screenMemory; /* 2 bytes per pixel */ + /* Convert each pixel from 256 palette to 4k color values */ +/* for (TInt x = 0 ; x < sourceRectWidth ; x++) + { + //__ASSERT_DEBUG(screenMemoryLinePos < (screenBuffer + (Private->EPOC_ScreenSize.iWidth * Private->EPOC_ScreenSize.iHeight)), User::Panic(KLibName, KErrCorrupt)); + //__ASSERT_DEBUG(screenMemoryLinePos >= screenBuffer, User::Panic(KLibName, KErrCorrupt)); + //__ASSERT_DEBUG(bitmapPos < ((TUint8*)_this->screen->pixels + (_this->screen->w * _this->screen->h)), User::Panic(KLibName, KErrCorrupt)); + //__ASSERT_DEBUG(bitmapPos >= (TUint8*)_this->screen->pixels, User::Panic(KLibName, KErrCorrupt)); + + *screenMemoryLinePos++ = EPOC_HWPalette_256_to_Screen[*bitmapPos]; + bitmapPos += skipValue; + } + bitmapLine += sourceScanlineLength; + screenMemory += targetScanlineLength; + } +//#endif + } + } // switch + } // for +} +*/ + +void DirectDrawRotated(_THIS, int numrects, SDL_Rect *rects, TUint16* screenBuffer) +{ + TInt i; +// TInt sourceNumBytesPerPixel = ((_this->screen->format->BitsPerPixel-1)>>3) + 1; + TPoint fixedScreenOffset = Private->EPOC_ScreenOffset; + TInt bufferW = _this->screen->w; + TInt bufferH = _this->screen->h; + TInt ScreenW = Private->EPOC_ScreenSize.iWidth; +// TInt ScreenH = Private->EPOC_ScreenSize.iWidth; + TInt sourceW = bufferW; + TInt sourceH = bufferH; + TInt targetW = ScreenW - fixedScreenOffset.iX * 2; +// TInt targetH = ScreenH - fixedScreenOffset.iY * 2; + TInt sourceScanlineLength = bufferW; + TInt targetScanlineLength = Private->EPOC_ScreenSize.iWidth; + + /* Render the rectangles in the list */ + + for ( i=0; i < numrects; ++i ) { + SDL_Rect rect2; + const SDL_Rect& currentRect = rects[i]; + rect2.x = currentRect.x; + rect2.y = currentRect.y; + rect2.w = currentRect.w; + rect2.h = currentRect.h; + + if (rect2.w <= 0 || rect2.h <= 0) /* sanity check */ + continue; + + /* All variables are measured in pixels */ + + /* Check rects validity, i.e. upper and lower bounds */ + TInt maxX = Min(sourceW - 1, rect2.x + rect2.w - 1); + TInt maxY = Min(sourceH - 1, rect2.y + rect2.h - 1); + if (maxX < 0 || maxY < 0) /* sanity check */ + continue; + /* Clip from bottom */ + //maxX = Min(maxX, Private->EPOC_ScreenSize.iHeight-1); + /* TODO: Clip from the right side */ + + TInt sourceRectWidth = maxX - rect2.x + 1; +// TInt sourceRectWidthInBytes = sourceRectWidth * sourceNumBytesPerPixel; + TInt sourceRectHeight = maxY - rect2.y + 1; + TInt sourceStartOffset = rect2.x + rect2.y * sourceScanlineLength; + TInt targetStartOffset = fixedScreenOffset.iX + (targetW-1 - rect2.y) + (fixedScreenOffset.iY +rect2.x) * targetScanlineLength; + + // Nokia7650 native mode: 12 bpp --> 12 bpp + if (_this->screen->format->BitsPerPixel == 12) { + + /* !!TODO: not yet implemented + + TUint16* bitmapLine = (TUint16*)_this->screen->pixels + sourceStartOffset; + TUint16* screenMemory = screenBuffer + targetStartOffset; + for(TInt y = 0 ; y < sourceRectHeight ; y++) { + //TODO: optimize: separate loops for 1, 2 and n skip + //Mem::Copy(screenMemory, bitmapLine, sourceRectWidthInBytes); + TUint16* bitmapPos = bitmapLine; // 2 bytes per pixel + TUint16* screenMemoryLinePos = screenMemory; // 2 bytes per pixel + for(TInt x = 0 ; x < sourceRectWidth ; x++) { + + __ASSERT_DEBUG(screenMemory < (screenBuffer + Private->EPOC_ScreenSize.iWidth * Private->EPOC_ScreenSize.iHeight), User::Panic(KLibName, KErrCorrupt)); + __ASSERT_DEBUG(screenMemory >= screenBuffer, User::Panic(KLibName, KErrCorrupt)); + __ASSERT_DEBUG(bitmapLine < ((TUint16*)_this->screen->pixels + (_this->screen->w * _this->screen->h)), User::Panic(KLibName, KErrCorrupt)); + __ASSERT_DEBUG(bitmapLine >= (TUint16*)_this->screen->pixels, User::Panic(KLibName, KErrCorrupt)); + + *screenMemoryLinePos = *bitmapPos; + bitmapPos++; + screenMemoryLinePos += targetScanlineLength; + } + bitmapLine += sourceScanlineLength; + screenMemory--; + } + + */ + } + // 256 color paletted mode: 8 bpp --> 12 bpp + else { + TUint8* bitmapLine = (TUint8*)_this->screen->pixels + sourceStartOffset; + TUint16* screenMemory = screenBuffer + targetStartOffset; + TInt screenXScaleValue = Private->EPOC_ScreenXScaleValue; + TInt debug_ycount=0; + for(TInt y = 0 ; y < sourceRectHeight ; y++) { + if(--screenXScaleValue) { + TUint8* bitmapPos = bitmapLine; /* 1 byte per pixel */ + TUint16* screenMemoryLinePos = screenMemory; /* 2 bytes per pixel */ + TInt screenYScaleValue = Private->EPOC_ScreenYScaleValue; + TInt debug_xcount=0; + /* Convert each pixel from 256 palette to 4k color values */ + for(TInt x = 0 ; x < sourceRectWidth ; x++) { + if(--screenYScaleValue) { + + __ASSERT_DEBUG(screenMemoryLinePos < (screenBuffer + (Private->EPOC_ScreenSize.iWidth * Private->EPOC_ScreenSize.iHeight)), User::Panic(KLibName, KErrCorrupt)); + __ASSERT_DEBUG(screenMemoryLinePos >= screenBuffer, User::Panic(KLibName, KErrCorrupt)); + __ASSERT_DEBUG(bitmapPos < ((TUint8*)_this->screen->pixels + (_this->screen->w * _this->screen->h)), User::Panic(KLibName, KErrCorrupt)); + __ASSERT_DEBUG(bitmapPos >= (TUint8*)_this->screen->pixels, User::Panic(KLibName, KErrCorrupt)); + + *screenMemoryLinePos = TUint16(EPOC_HWPalette_256_to_Screen[*bitmapPos]); + screenMemoryLinePos += targetScanlineLength; debug_xcount++; + } + else + screenYScaleValue = Private->EPOC_ScreenYScaleValue; + bitmapPos++; + } + screenMemory--; debug_ycount++; + } // endif + else + screenXScaleValue = Private->EPOC_ScreenXScaleValue; + bitmapLine += sourceScanlineLength; + } + } + } +} + + +/* Note: If we are terminated, this could be called in the middle of + another SDL video routine -- notably UpdateRects. +*/ +void EPOC_VideoQuit(_THIS) +{ + int i; + + /* Free video mode lists */ + for ( i=0; i<SDL_NUMMODES; ++i ) { + if ( Private->SDL_modelist[i] != NULL ) { + free(Private->SDL_modelist[i]); + Private->SDL_modelist[i] = NULL; + } + } + + if ( _this->screen && (_this->screen->flags & SDL_HWSURFACE) ) { + /* Direct screen access, no memory buffer */ + _this->screen->pixels = NULL; + } + + if (_this->screen && _this->screen->pixels) { + free(_this->screen->pixels); + _this->screen->pixels = NULL; + } + + /* Free Epoc resources */ + + /* Disable events for me */ + if (Private->EPOC_WsEventStatus != KRequestPending) + Private->EPOC_WsSession.EventReadyCancel(); + if (Private->EPOC_RedrawEventStatus != KRequestPending) + Private->EPOC_WsSession.RedrawReadyCancel(); + + #if defined(__WINS__) || defined(TEST_BM_DRAW) + delete Private->EPOC_Bitmap; + Private->EPOC_Bitmap = NULL; + #else + #endif + +#ifndef SYMBIAN_CRYSTAL + free(Private->EPOC_DrawDevice); +#endif + + if (Private->EPOC_WsWindow.WsHandle()) + Private->EPOC_WsWindow.Close(); + + if (Private->EPOC_WsWindowGroup.WsHandle()) + Private->EPOC_WsWindowGroup.Close(); + + delete Private->EPOC_WindowGc; + Private->EPOC_WindowGc = NULL; + + delete Private->EPOC_WsScreen; + Private->EPOC_WsScreen = NULL; + + if (Private->EPOC_WsSession.WsHandle()) + Private->EPOC_WsSession.Close(); +} + + +WMcursor *EPOC_CreateWMCursor(_THIS, Uint8* /*data*/, Uint8* /*mask*/, int /*w*/, int /*h*/, int /*hot_x*/, int /*hot_y*/) +{ + return (WMcursor *) 9210; // it's ok to return something unuseful but true +} + +void EPOC_FreeWMCursor(_THIS, WMcursor* /*cursor*/) +{ + /* Disable virtual cursor */ + HAL::Set(HAL::EMouseState, HAL::EMouseState_Invisible); + Private->EPOC_WsSession.SetPointerCursorMode(EPointerCursorNone); +} + +int EPOC_ShowWMCursor(_THIS, WMcursor *cursor) +{ + + if (cursor == (WMcursor *)9210) { + /* Enable virtual cursor */ + Private->EPOC_WsSession.SetPointerCursorMode(EPointerCursorNormal); + if (isCursorVisible) + HAL::Set(HAL::EMouseState, HAL::EMouseState_Visible); + else + Private->EPOC_WsSession.SetPointerCursorMode(EPointerCursorNone); + } + else { + /* Disable virtual cursor */ + HAL::Set(HAL::EMouseState, HAL::EMouseState_Invisible); + Private->EPOC_WsSession.SetPointerCursorMode(EPointerCursorNone); + } + + return(1); +} + +}; // extern "C" diff --git a/3rdparty/SDL/src/video/symbian/EKA1/SDL_epocvideo.h b/3rdparty/SDL/src/video/symbian/EKA1/SDL_epocvideo.h new file mode 100644 index 0000000..bd0b0e2 --- /dev/null +++ b/3rdparty/SDL/src/video/symbian/EKA1/SDL_epocvideo.h @@ -0,0 +1,34 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Sam Lantinga + slouken@devolution.com +*/ + +#ifndef _SDL_epocvideo_h +#define _SDL_epocvideo_h + +#ifndef EKA2 +#include"SDL_epocvideo_org.h" +#else +#include"SDL_epocvideo2.h" +#endif + + +#endif + diff --git a/3rdparty/SDL/src/video/symbian/EKA2/SDL_epocevents.cpp b/3rdparty/SDL/src/video/symbian/EKA2/SDL_epocevents.cpp new file mode 100644 index 0000000..2452dae --- /dev/null +++ b/3rdparty/SDL/src/video/symbian/EKA2/SDL_epocevents.cpp @@ -0,0 +1,521 @@ +#include "epoc_sdl.h" + +#include <stdio.h> +#undef NULL +extern "C" { +//#define DEBUG_TRACE_ENABLED +#include "SDL_error.h" +#include "SDL_video.h" +#include "SDL_keysym.h" +#include "SDL_keyboard.h" +#include "SDL_events_c.h" +#include "SDL_timer.h" +} /* extern "C" */ + +#include "SDL_epocvideo.h" +#include "SDL_epocevents_c.h" + +#include "sdlepocapi.h" + +#include <eikenv.h> + +#include<bautils.h> + + +extern "C" + { + static SDL_keysym *TranslateKey(_THIS, int scancode, SDL_keysym *keysym); + } + +//extern "C" { +/* The translation tables from a console scancode to a SDL keysym */ +static SDLKey keymap[MAX_SCANCODE]; +static SDL_keysym *TranslateKey(_THIS, int scancode, SDL_keysym *keysym); +void DisableKeyBlocking(_THIS); +//} /* extern "C" */ + +SDLKey* KeyMap() + { + return keymap; + } + +TBool isCursorVisible = EFalse; + +void ResetKeyMap() + { + int i; + + /* Initialize the key translation table */ + for ( i=0; i<SDL_TABLESIZE(keymap); ++i ) + keymap[i] = SDLK_UNKNOWN; + + + /* Numbers */ + for ( i = 0; i<32; ++i ){ + keymap[' ' + i] = (SDLKey)(SDLK_SPACE+i); + } + /* e.g. Alphabet keys */ + for ( i = 0; i<32; ++i ){ + keymap['A' + i] = (SDLKey)(SDLK_a+i); + } + + keymap[EStdKeyBackspace] = SDLK_BACKSPACE; + keymap[EStdKeyTab] = SDLK_TAB; + keymap[EStdKeyEnter] = SDLK_RETURN; + keymap[EStdKeyEscape] = SDLK_ESCAPE; + keymap[EStdKeySpace] = SDLK_SPACE; + keymap[EStdKeyPause] = SDLK_PAUSE; + keymap[EStdKeyHome] = SDLK_HOME; + keymap[EStdKeyEnd] = SDLK_END; + keymap[EStdKeyPageUp] = SDLK_PAGEUP; + keymap[EStdKeyPageDown] = SDLK_PAGEDOWN; + keymap[EStdKeyDelete] = SDLK_DELETE; + keymap[EStdKeyUpArrow] = SDLK_UP; + keymap[EStdKeyDownArrow] = SDLK_DOWN; + keymap[EStdKeyLeftArrow] = SDLK_LEFT; + keymap[EStdKeyRightArrow] = SDLK_RIGHT; + keymap[EStdKeyCapsLock] = SDLK_CAPSLOCK; + keymap[EStdKeyLeftShift] = SDLK_LSHIFT; + keymap[EStdKeyRightShift] = SDLK_RSHIFT; + keymap[EStdKeyLeftAlt] = SDLK_LALT; + keymap[EStdKeyRightAlt] = SDLK_RALT; + keymap[EStdKeyLeftCtrl] = SDLK_LCTRL; + keymap[EStdKeyRightCtrl] = SDLK_RCTRL; + keymap[EStdKeyLeftFunc] = SDLK_LMETA; + keymap[EStdKeyRightFunc] = SDLK_RMETA; + keymap[EStdKeyInsert] = SDLK_INSERT; + keymap[EStdKeyComma] = SDLK_COMMA; + keymap[EStdKeyFullStop] = SDLK_PERIOD; + keymap[EStdKeyForwardSlash] = SDLK_SLASH; + keymap[EStdKeyBackSlash] = SDLK_BACKSLASH; + keymap[EStdKeySemiColon] = SDLK_SEMICOLON; + keymap[EStdKeySingleQuote] = SDLK_QUOTE; + keymap[EStdKeyHash] = SDLK_HASH; + keymap[EStdKeySquareBracketLeft] = SDLK_LEFTBRACKET; + keymap[EStdKeySquareBracketRight] = SDLK_RIGHTBRACKET; + keymap[EStdKeyMinus] = SDLK_MINUS; + keymap[EStdKeyEquals] = SDLK_EQUALS; + + keymap[EStdKeyF1] = SDLK_F1; + keymap[EStdKeyF2] = SDLK_F2; + keymap[EStdKeyF3] = SDLK_F3; + keymap[EStdKeyF4] = SDLK_F4; + keymap[EStdKeyF5] = SDLK_F5; + keymap[EStdKeyF6] = SDLK_F6; + keymap[EStdKeyF7] = SDLK_F7; + keymap[EStdKeyF8] = SDLK_F8; + + keymap[EStdKeyF9] = SDLK_F9; + keymap[EStdKeyF10] = SDLK_F10; + keymap[EStdKeyF11] = SDLK_F11; + keymap[EStdKeyF12] = SDLK_F12; + + + keymap[EStdKeyXXX] = SDLK_RETURN; /* "fire" key */ + + keymap[EStdKeyDevice3] = SDLK_RETURN; /* "fire" key */ + keymap[EStdKeyNkpAsterisk] = SDLK_ASTERISK; + keymap[EStdKeyYes] = SDLK_HOME; /* "call" key */ + keymap[EStdKeyNo] = SDLK_END; /* "end call" key */ + keymap[EStdKeyDevice0] = SDLK_SPACE; /* right menu key */ + keymap[EStdKeyDevice1] = SDLK_ESCAPE; /* left menu key */ + keymap[EStdKeyDevice2] = SDLK_POWER; /* power key */ + + keymap[EStdKeyMenu] = SDLK_MENU; // menu key + keymap[EStdKeyDevice6] = SDLK_LEFT; // Rocker (joystick) left + keymap[EStdKeyDevice7] = SDLK_RIGHT; // Rocker (joystick) right + keymap[EStdKeyDevice8] = SDLK_UP; // Rocker (joystick) up + keymap[EStdKeyDevice9] = SDLK_DOWN; // Rocker (joystick) down + keymap[EStdKeyLeftFunc] = SDLK_LALT; //chr? + keymap[EStdKeyRightFunc] = SDLK_RALT; + keymap[EStdKeyDeviceA] = SDLK_RETURN; /* "fire" key */ + + + + + + /////////////////////////////////////////////////////////// + /* + RFs fs; + if(KErrNone == fs.Connect()) + { + RArray<TInt> array; + TRAPD(err, ReadL(fs, array)); + if(err == KErrNone && array.Count() > 0) + { + + SDLKey temp[MAX_SCANCODE]; + Mem::Copy(temp, keymap, MAX_SCANCODE * sizeof(SDLKey)); + + for(TInt k = 0; k < array.Count(); k+= 2) + { + const TInt oldval = array[k]; + const TInt newval = array[k + 1]; + if(oldval >= 0 && oldval < MAX_SCANCODE && newval >= 0 && newval < MAX_SCANCODE) + { + keymap[oldval] = temp[newval]; + } + } + } + array.Close(); + } + + fs.Close();*/ + /////////////////////////////////////////////////////////// + + + keymap[EStdKeyNumLock] = SDLK_NUMLOCK; + keymap[EStdKeyScrollLock] = SDLK_SCROLLOCK; + + keymap[EStdKeyNkpForwardSlash] = SDLK_KP_DIVIDE; + keymap[EStdKeyNkpAsterisk] = SDLK_KP_MULTIPLY; + keymap[EStdKeyNkpMinus] = SDLK_KP_MINUS; + keymap[EStdKeyNkpPlus] = SDLK_KP_PLUS; + keymap[EStdKeyNkpEnter] = SDLK_KP_ENTER; + keymap[EStdKeyNkp1] = SDLK_KP1; + keymap[EStdKeyNkp2] = SDLK_KP2; + keymap[EStdKeyNkp3] = SDLK_KP3; + keymap[EStdKeyNkp4] = SDLK_KP4; + keymap[EStdKeyNkp5] = SDLK_KP5; + keymap[EStdKeyNkp6] = SDLK_KP6; + keymap[EStdKeyNkp7] = SDLK_KP7; + keymap[EStdKeyNkp8] = SDLK_KP8; + keymap[EStdKeyNkp9] = SDLK_KP9; + keymap[EStdKeyNkp0] = SDLK_KP0; + keymap[EStdKeyNkpFullStop] = SDLK_KP_PERIOD; + /* + keymap[EStdKeyMenu] = SDLK_MENU; should be, but not yet + keymap[EStdKeyBacklightOn] = + keymap[EStdKeyBacklightOff] = + keymap[EStdKeyBacklightToggle] = + keymap[EStdKeyIncContrast] = + keymap[EStdKeyDecContrast] = + keymap[EStdKeySliderDown] = + keymap[EStdKeySliderUp] = + keymap[EStdKeyDictaphonePlay] = + keymap[EStdKeyDictaphoneStop] = + keymap[EStdKeyDictaphoneRecord] = + keymap[EStdKeyHelp] = + keymap[EStdKeyOff] = + keymap[EStdKeyDial] = + keymap[EStdKeyIncVolume] = + keymap[EStdKeyDecVolume] = + keymap[EStdKeyDevice0] = + keymap[EStdKeyDevice1] = + keymap[EStdKeyDevice2] = + keymap[EStdKeyDevice3] = + keymap[EStdKeyDevice4] = + keymap[EStdKeyDevice5] = + keymap[EStdKeyDevice6] = + keymap[EStdKeyDevice7] = + keymap[EStdKeyDevice8] = + keymap[EStdKeyDevice9] = + keymap[EStdKeyDeviceA] = + keymap[EStdKeyDeviceB] = + keymap[EStdKeyDeviceC] = + keymap[EStdKeyDeviceD] = + keymap[EStdKeyDeviceE] = + keymap[EStdKeyDeviceF] = + keymap[EStdKeyApplication0] = + keymap[EStdKeyApplication1] = + keymap[EStdKeyApplication2] = + keymap[EStdKeyApplication3] = + keymap[EStdKeyApplication4] = + keymap[EStdKeyApplication5] = + keymap[EStdKeyApplication6] = + keymap[EStdKeyApplication7] = + keymap[EStdKeyApplication8] = + keymap[EStdKeyApplication9] = + keymap[EStdKeyApplicationA] = + keymap[EStdKeyApplicationB] = + keymap[EStdKeyApplicationC] = + keymap[EStdKeyApplicationD] = + keymap[EStdKeyApplicationE] = + keymap[EStdKeyApplicationF] = + keymap[EStdKeyYes] = + keymap[EStdKeyNo] = + keymap[EStdKeyIncBrightness] = + keymap[EStdKeyDecBrightness] = + keymap[EStdKeyCaseOpen] = + keymap[EStdKeyCaseClose] = */ + + + +} + + +int EPOC_HandleWsEvent(_THIS, const TWsEvent& aWsEvent) +{ + int posted = 0; + SDL_keysym keysym; + +// SDL_TRACE1("hws %d", aWsEvent.Type()); + + switch (aWsEvent.Type()) + { + case EEventPointer: /* Mouse pointer events */ + { +/* const TPointerCursorMode mode = EpocSdlEnv::PointerMode(); + + + if(mode == EPointerCursorNone) + { + return 0; //TODO: Find out why events are get despite of cursor should be off + } +*/ + const TPointerEvent* pointerEvent = aWsEvent.Pointer(); + const TPoint mousePos = EpocSdlEnv::WindowCoordinates(pointerEvent->iPosition); + + /*!! TODO Pointer do not yet work properly + //SDL_TRACE1("SDL: EPOC_HandleWsEvent, pointerEvent->iType=%d", pointerEvent->iType); //!! + + if (Private->EPOC_ShrinkedHeight) { + mousePos.iY <<= 1; // Scale y coordinate to shrinked screen height + } + if (Private->EPOC_ShrinkedWidth) { + mousePos.iX <<= 1; // Scale x coordinate to shrinked screen width + } + */ + + posted += SDL_PrivateMouseMotion(0, 0, mousePos.iX, mousePos.iY); /* Absolute position on screen */ + + switch (pointerEvent->iType) + { + case TPointerEvent::EButton1Down: + posted += SDL_PrivateMouseButton(SDL_PRESSED, SDL_BUTTON_LEFT, 0, 0); + break; + case TPointerEvent::EButton1Up: + posted += SDL_PrivateMouseButton(SDL_RELEASED, SDL_BUTTON_LEFT, 0, 0); + break; + case TPointerEvent::EButton2Down: + posted += SDL_PrivateMouseButton(SDL_PRESSED, SDL_BUTTON_RIGHT, 0, 0); + break; + case TPointerEvent::EButton2Up: + posted += SDL_PrivateMouseButton(SDL_RELEASED, SDL_BUTTON_RIGHT, 0, 0); + break; + case TPointerEvent::EButton3Down: + posted += SDL_PrivateMouseButton(SDL_PRESSED, SDL_BUTTON_MIDDLE, 0, 0); + break; + case TPointerEvent::EButton3Up: + posted += SDL_PrivateMouseButton(SDL_RELEASED, SDL_BUTTON_MIDDLE, 0, 0); + break; + } // switch + break; + } + + case EEventKeyDown: /* Key events */ + { +#ifdef SYMBIAN_CRYSTAL + // special case: 9300/9500 rocker down, simulate left mouse button + if (aWsEvent.Key()->iScanCode == EStdKeyDeviceA) + { + const TPointerCursorMode mode = Private->EPOC_WsSession.PointerCursorMode(); + if(mode != EPointerCursorNone) + posted += SDL_PrivateMouseButton(SDL_PRESSED, SDL_BUTTON_LEFT, 0, 0); + } +#endif + (void*)TranslateKey(_this, aWsEvent.Key()->iScanCode, &keysym); + +#ifndef DISABLE_JOYSTICK + /* Special handling */ + switch((int)keysym.sym) { + case SDLK_CAPSLOCK: + if (!isCursorVisible) { + /* Enable virtual cursor */ + HAL::Set(HAL::EMouseState, HAL::EMouseState_Visible); + } + else { + /* Disable virtual cursor */ + HAL::Set(HAL::EMouseState, HAL::EMouseState_Invisible); + } + isCursorVisible = !isCursorVisible; + break; + } +#endif + posted += SDL_PrivateKeyboard(SDL_PRESSED, &keysym); + break; + } + + case EEventKeyUp: /* Key events */ + { +#ifdef SYMBIAN_CRYSTAL + // special case: 9300/9500 rocker up, simulate left mouse button + if (aWsEvent.Key()->iScanCode == EStdKeyDeviceA) + { + posted += SDL_PrivateMouseButton(SDL_RELEASED, SDL_BUTTON_LEFT, 0, 0); + } +#endif + posted += SDL_PrivateKeyboard(SDL_RELEASED, TranslateKey(_this, aWsEvent.Key()->iScanCode, &keysym)); + break; + } + + case EEventFocusGained: /* SDL window got focus */ + { + Private->iIsWindowFocused = ETrue; + posted += SDL_PrivateAppActive(1, SDL_APPINPUTFOCUS|SDL_APPMOUSEFOCUS); + /* Draw window background and screen buffer */ + DisableKeyBlocking(_this); //Markus: guess why:-) + + //RedrawWindowL(_this); + break; + } + + case EEventFocusLost: /* SDL window lost focus */ + { + + Private->iIsWindowFocused = EFalse; + + posted += SDL_PrivateAppActive(0, SDL_APPINPUTFOCUS|SDL_APPMOUSEFOCUS); + + + break; + } + + case EEventModifiersChanged: + { + TModifiersChangedEvent* modEvent = aWsEvent.ModifiersChanged(); + TUint modstate = KMOD_NONE; + if (modEvent->iModifiers == EModifierLeftShift) + modstate |= KMOD_LSHIFT; + if (modEvent->iModifiers == EModifierRightShift) + modstate |= KMOD_RSHIFT; + if (modEvent->iModifiers == EModifierLeftCtrl) + modstate |= KMOD_LCTRL; + if (modEvent->iModifiers == EModifierRightCtrl) + modstate |= KMOD_RCTRL; + if (modEvent->iModifiers == EModifierLeftAlt) + modstate |= KMOD_LALT; + if (modEvent->iModifiers == EModifierRightAlt) + modstate |= KMOD_RALT; + if (modEvent->iModifiers == EModifierLeftFunc) + modstate |= KMOD_LMETA; + if (modEvent->iModifiers == EModifierRightFunc) + modstate |= KMOD_RMETA; + if (modEvent->iModifiers == EModifierCapsLock) + modstate |= KMOD_CAPS; + SDL_SetModState(STATIC_CAST(SDLMod,(modstate | KMOD_LSHIFT))); + break; + } + case EEventScreenDeviceChanged: + { + EpocSdlEnv::WaitDeviceChange(); + } + break; + default: + break; + } + + return posted; +} + +extern "C" { + +void EPOC_PumpEvents(_THIS) + { + MEventQueue& events = EpocSdlEnv::EventQueue(); + while(events.HasData()) + { + events.Lock(); + + //there have to be a copy, so we can release + //lock immediately. HandleWsEvent may cause + //deadlock otherwise. + + const TWsEvent event = events.Shift(); + events.Unlock(); +// const TWsEvent& event = events.Top(); + EPOC_HandleWsEvent(_this, event); +// events.Shift(); + } + } + + + +void EPOC_InitOSKeymap(_THIS) + { + ResetKeyMap(); + EpocSdlEnv::ObserverEvent(MSDLObserver::EEventKeyMapInit ,0); + } + +static SDL_keysym *TranslateKey(_THIS, int scancode, SDL_keysym *keysym) +{ +// char debug[256]; + //SDL_TRACE1("SDL: TranslateKey, scancode=%d", scancode); //!! + + /* Set the keysym information */ + + keysym->scancode = scancode; + + if ((scancode >= MAX_SCANCODE) && + ((scancode - ENonCharacterKeyBase + 0x0081) >= MAX_SCANCODE)) { + SDL_SetError("Too big scancode"); + keysym->scancode = SDLK_UNKNOWN; + keysym->mod = KMOD_NONE; + return keysym; + } + + keysym->mod = SDL_GetModState(); + + /* Handle function keys: F1, F2, F3 ... */ + if (keysym->mod & KMOD_META) { + if (scancode >= 'A' && scancode < ('A' + 24)) { /* first 32 alphabet keys */ + switch(scancode) { + case 'Q': scancode = EStdKeyF1; break; + case 'W': scancode = EStdKeyF2; break; + case 'E': scancode = EStdKeyF3; break; + case 'R': scancode = EStdKeyF4; break; + case 'T': scancode = EStdKeyF5; break; + case 'Y': scancode = EStdKeyF6; break; + case 'U': scancode = EStdKeyF7; break; + case 'I': scancode = EStdKeyF8; break; + case 'A': scancode = EStdKeyF9; break; + case 'S': scancode = EStdKeyF10; break; + case 'D': scancode = EStdKeyF11; break; + case 'F': scancode = EStdKeyF12; break; + } + keysym->sym = keymap[scancode]; + } + } + + if (scancode >= ENonCharacterKeyBase) { + // Non character keys + keysym->sym = keymap[scancode - + ENonCharacterKeyBase + 0x0081]; // !!hard coded + } else { + keysym->sym = keymap[scancode]; + } + + /* Remap the arrow keys if the device is rotated */ +/* + if (Private->EPOC_ScreenOrientation == CFbsBitGc::EGraphicsOrientationRotated270) { + switch(keysym->sym) { + case SDLK_UP: keysym->sym = SDLK_LEFT; break; + case SDLK_DOWN: keysym->sym = SDLK_RIGHT; break; + case SDLK_LEFT: keysym->sym = SDLK_DOWN; break; + case SDLK_RIGHT:keysym->sym = SDLK_UP; break; + } + } +*/ + /* If UNICODE is on, get the UNICODE value for the key */ + keysym->unicode = 0; + +#if 0 // !!TODO:unicode + + if ( SDL_TranslateUNICODE ) + { + /* Populate the unicode field with the ASCII value */ + keysym->unicode = scancode; + } +#endif + + //!! + //sprintf(debug, "SDL: TranslateKey: keysym->scancode=%d, keysym->sym=%d, keysym->mod=%d", + // keysym->scancode, keysym->sym, keysym->mod); + //SDL_TRACE(debug); //!! + + return(keysym); +} + +} /* extern "C" */ + + diff --git a/3rdparty/SDL/src/video/symbian/EKA2/SDL_epocvideo.cpp b/3rdparty/SDL/src/video/symbian/EKA2/SDL_epocvideo.cpp new file mode 100644 index 0000000..c15506d --- /dev/null +++ b/3rdparty/SDL/src/video/symbian/EKA2/SDL_epocvideo.cpp @@ -0,0 +1,594 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Sam Lantinga + slouken@devolution.com +*/ + +/* + SDL_epocvideo.cpp + Epoc based SDL video driver implementation + + Markus Mertama +*/ + + + +#include "epoc_sdl.h" + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> + +extern "C" { +#include "SDL_error.h" +#include "SDL_timer.h" +#include "SDL_video.h" +#undef NULL +#include "SDL_pixels_c.h" +#include "SDL.h" +#include "SDL_mouse.h" +} + +#include "SDL_epocvideo.h" +#include "SDL_epocevents_c.h" + + + +#include <coedef.h> +#include <flogger.h> + +#include <eikenv.h> +#include <eikappui.h> +#include <eikapp.h> +#include "sdlepocapi.h" + + +//////////////////////////////////////////////////////////////// + + + + +_LIT(KLibName, "SDL"); + +void RDebug_Print_b(char* error_str, void* param) + { + TBuf8<128> error8((TUint8*)error_str); + TBuf<128> error; + error.Copy(error8); + +#ifndef TRACE_TO_FILE + if (param) //!! Do not work if the parameter is really 0!! + RDebug::Print(error, param); + else + RDebug::Print(error); +#else + if (param) //!! Do not work if the parameter is really 0!! + RFileLogger::WriteFormat(KLibName, _L("SDL.txt"), EFileLoggingModeAppend, error, param); + else + RFileLogger::Write(KLibName, _L("SDL.txt"), EFileLoggingModeAppend, error); +#endif + + } + +extern "C" void RDebug_Print(char* error_str, void* param) + { + RDebug_Print_b(error_str, param); + } + +/* +int Debug_AvailMem2() + { + //User::CompressAllHeaps(); + TMemoryInfoV1Buf membuf; + User::LeaveIfError(UserHal::MemoryInfo(membuf)); + TMemoryInfoV1 minfo = membuf(); + return(minfo.iFreeRamInBytes); + } + +extern "C" int Debug_AvailMem() + { + return(Debug_AvailMem2()); + } + +*/ + +extern "C" { + +/* Initialization/Query functions */ + +static int EPOC_VideoInit(_THIS, SDL_PixelFormat *vformat); +static SDL_Rect **EPOC_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags); +static SDL_Surface *EPOC_SetVideoMode(_THIS, SDL_Surface *current, int width, int height, int bpp, Uint32 flags); +static int EPOC_SetColors(_THIS, int firstcolor, int ncolors, + SDL_Color *colors); +static void EPOC_VideoQuit(_THIS); + +/* Hardware surface functions */ + +static int EPOC_AllocHWSurface(_THIS, SDL_Surface *surface); +static int EPOC_LockHWSurface(_THIS, SDL_Surface *surface); +static int EPOC_FlipHWSurface(_THIS, SDL_Surface *surface); +static void EPOC_UnlockHWSurface(_THIS, SDL_Surface *surface); +static void EPOC_FreeHWSurface(_THIS, SDL_Surface *surface); +static void EPOC_DirectUpdate(_THIS, int numrects, SDL_Rect *rects); + +static int EPOC_Available(void); +static SDL_VideoDevice *EPOC_CreateDevice(int devindex); + +void DrawBackground(_THIS); +void DirectDraw(_THIS, int numrects, SDL_Rect *rects, TUint16* screenBuffer); +void DirectDrawRotated(_THIS, int numrects, SDL_Rect *rects, TUint16* screenBuffer); + +/* Mouse functions */ + +static WMcursor *EPOC_CreateWMCursor(_THIS, Uint8 *data, Uint8 *mask, int w, int h, int hot_x, int hot_y); +static void EPOC_FreeWMCursor(_THIS, WMcursor *cursor); +static int EPOC_ShowWMCursor(_THIS, WMcursor *cursor); +} + + +extern "C" + { + struct WMcursor + { + }; + } + +/* Epoc video driver bootstrap functions */ + + +static int EPOC_Available(void) + { + return 1; /* Always available */ + } + +static void EPOC_DeleteDevice(SDL_VideoDevice *device) + { + User::Free(device->hidden); + User::Free(device); + } + +static SDL_VideoDevice *EPOC_CreateDevice(int /*devindex*/) + { + SDL_VideoDevice *device; + + SDL_TRACE("SDL:EPOC_CreateDevice"); + + /* Allocate all variables that we free on delete */ + device = static_cast<SDL_VideoDevice*>(User::Alloc(sizeof(SDL_VideoDevice))); + if ( device ) + { + Mem::FillZ(device, (sizeof *device)); + device->hidden = static_cast<struct SDL_PrivateVideoData*> + (User::Alloc((sizeof *device->hidden))); + } + if ( (device == NULL) || (device->hidden == NULL) ) + { + SDL_OutOfMemory(); + if ( device ) { + User::Free(device); + } + return(0); + } + Mem::FillZ(device->hidden, (sizeof *device->hidden)); + + /* Set the function pointers */ + device->VideoInit = EPOC_VideoInit; + device->ListModes = EPOC_ListModes; + device->SetVideoMode = EPOC_SetVideoMode; + device->SetColors = EPOC_SetColors; + device->UpdateRects = NULL; + device->VideoQuit = EPOC_VideoQuit; + device->AllocHWSurface = EPOC_AllocHWSurface; + device->CheckHWBlit = NULL; + device->FillHWRect = NULL; + device->SetHWColorKey = NULL; + device->SetHWAlpha = NULL; + device->LockHWSurface = EPOC_LockHWSurface; + device->UnlockHWSurface = EPOC_UnlockHWSurface; + device->FlipHWSurface = EPOC_FlipHWSurface; + device->FreeHWSurface = EPOC_FreeHWSurface; + device->SetIcon = NULL; + device->SetCaption = NULL; + device->GetWMInfo = NULL; + device->FreeWMCursor = EPOC_FreeWMCursor; + device->CreateWMCursor = EPOC_CreateWMCursor; + device->ShowWMCursor = EPOC_ShowWMCursor; + device->WarpWMCursor = NULL; + device->InitOSKeymap = EPOC_InitOSKeymap; + device->PumpEvents = EPOC_PumpEvents; + device->free = EPOC_DeleteDevice; + + return device; +} + + +VideoBootStrap EPOC_bootstrap = { + "epoc\0\0\0", "EPOC system", + EPOC_Available, EPOC_CreateDevice +}; + + + +void DisableKeyBlocking(_THIS) + { + EpocSdlEnv::Request(EpocSdlEnv::EDisableKeyBlocking); + } + +void ConstructWindowL(_THIS) + { + SDL_TRACE("SDL:ConstructWindowL"); + DisableKeyBlocking(_this); //disable key blocking + } + + +int EPOC_VideoInit(_THIS, SDL_PixelFormat *vformat) + { + /* Construct Epoc window */ + + ConstructWindowL(_this); + + /* Initialise Epoc frame buffer */ + + + const TDisplayMode displayMode = EpocSdlEnv::DisplayMode(); + + /* The "best" video format should be returned to caller. */ + + vformat->BitsPerPixel = TDisplayModeUtils::NumDisplayModeBitsPerPixel(displayMode); + vformat->BytesPerPixel = TDisplayModeUtils::NumDisplayModeBitsPerPixel(displayMode) / 8; + + + //?? Private->iWindow->PointerFilter(EPointerFilterDrag, 0); + + Private->iScreenPos = TPoint(0, 0); + + Private->iRect.x = Private->iScreenPos.iX; + Private->iRect.y = Private->iScreenPos.iY; + + const TSize sz = EpocSdlEnv::WindowSize(); + + Private->iRect.w = sz.iWidth; + Private->iRect.h = sz.iHeight; + Private->iRectPtr = &Private->iRect; + + return(0); + } + + +SDL_Rect **EPOC_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags) + { + if(flags & SDL_HWSURFACE) + { + if(format->BytesPerPixel != 4) //in HW only full color is supported + return NULL; + } + if(flags & SDL_FULLSCREEN) + { + return &Private->iRectPtr; + } + return (SDL_Rect **)(-1); //everythingisok, unless too small shoes + } + + +int EPOC_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors) + { + if ((firstcolor+ncolors) > 256) + return -1; + TUint32 palette[256]; + const TDisplayMode mode = EpocSdlEnv::DisplayMode(); + if(TDisplayModeUtils::NumDisplayModeColors(mode) == 4096) + { + // Set 12 bit palette + for(int i = firstcolor; i < ncolors; i++) + { + // 4k value: 0000 rrrr gggg bbbb + TUint32 color4K = (colors[i].r & 0x0000f0) << 4; + color4K |= (colors[i].g & 0x0000f0); + color4K |= (colors[i].b & 0x0000f0) >> 4; + palette[i] = color4K; + } + } + else if(TDisplayModeUtils::NumDisplayModeColors(mode) == 65536) + { + for(int i = firstcolor; i < ncolors; i++) + { + // 64k-colour displays effectively support RGB values + // with 5 bits allocated to red, 6 to green and 5 to blue + // 64k value: rrrr rggg gggb bbbb + TUint32 color64K = (colors[i].r & 0x0000f8) << 8; + color64K |= (colors[i].g & 0x0000fc) << 3; + color64K |= (colors[i].b & 0x0000f8) >> 3; + palette[i] = color64K; + } + } + else if(TDisplayModeUtils::NumDisplayModeColors(mode) == 16777216) + { + for(int i = firstcolor; i < ncolors; i++) + { + // 16M-colour + //0000 0000 rrrr rrrr gggg gggg bbbb bbbb + TUint32 color16M = colors[i].r << 16; + color16M |= colors[i].g << 8; + color16M |= colors[i].b; + palette[i] = color16M; + } + } + else + { + return -2; + } + if(EpocSdlEnv::SetPalette(firstcolor, ncolors, palette) == KErrNone) + return 0; + return -1; + } + + +/* +void AllocHWSurfaceL(CFbsBitmap*& aBitmap, const TDisplayMode& aMode, const TSize& aSize) + { + aBitmap = new (ELeave) CFbsBitmap(); + if(KErrNone != aBitmap->CreateHardwareBitmap(aSize, aMode, + EpocSdlEnv::EikonEnv().EikAppUi()->Application()->AppDllUid())) + //...if it fails - should we use wsbitmaps??? + {//the good reason to use hw bitmaps is that they wont need lock heap + PANIC_IF_ERROR(aBitmap->Create(aSize, aMode)); + } + } + +int CreateSurfaceL(_THIS, SDL_Surface* surface) + { + __ASSERT_ALWAYS(Private->iFrame == NULL, PANIC(KErrAlreadyExists)); +; + TInt dmode = EColorLast; + + TDisplayMode displayMode; + EpocSdlEnv::GetDiplayMode(displayMode); + + if( + TDisplayModeUtils::NumDisplayModeBitsPerPixel(displayMode) + == surface->format->BitsPerPixel) + { + dmode = displayMode; + } + else + { + --dmode; + while(TDisplayModeUtils::IsDisplayModeColor(TDisplayMode(dmode)) && + TDisplayModeUtils::NumDisplayModeBitsPerPixel(TDisplayMode(dmode)) != + surface->format->BitsPerPixel) + --dmode; + } + + __ASSERT_ALWAYS(TDisplayModeUtils::IsDisplayModeColor(TDisplayMode(dmode)), PANIC(KErrNotSupported)); + TRAPD(err, AllocHWSurfaceL(Private->iFrame, TDisplayMode(dmode), TSize(surface->w, surface->h))); + return err == KErrNone ? 0 : -1; + } +*/ + +TDisplayMode GetDisplayMode(TInt aBitsPerPixel) + { + const TDisplayMode displayMode = EpocSdlEnv::DisplayMode(); + TInt dmode = EColorLast; + if( + TDisplayModeUtils::NumDisplayModeBitsPerPixel(displayMode) + == aBitsPerPixel) + { + dmode = displayMode; + } + else + { + --dmode; + while(TDisplayModeUtils::IsDisplayModeColor(TDisplayMode(dmode)) && + TDisplayModeUtils::NumDisplayModeBitsPerPixel(TDisplayMode(dmode)) != + aBitsPerPixel) + --dmode; + } + return TDisplayMode(dmode); + } + +SDL_Surface *EPOC_SetVideoMode(_THIS, SDL_Surface *current, + int width, int height, int bpp, Uint32 flags) + { + const TSize screenSize = EpocSdlEnv::WindowSize(TSize(width, height)); + if(width > screenSize.iWidth || height > screenSize.iHeight) + { + if(flags & SDL_FULLSCREEN) + { + width = screenSize.iWidth; + height = screenSize.iHeight; + } + else + return NULL; + } + + if(current && current->pixels) + { + // free(current->pixels); + current->pixels = NULL; + } + + if(!SDL_ReallocFormat(current, bpp, 0, 0, 0, 0)) + { + return(NULL); + } + + current->flags = 0; + if(width == screenSize.iWidth && height == screenSize.iHeight) + current->flags |= SDL_FULLSCREEN; + + const int numBytesPerPixel = ((bpp-1)>>3) + 1; + current->pitch = numBytesPerPixel * width; // Number of bytes in scanline + + /* Set up the new mode framebuffer */ + current->flags |= SDL_PREALLOC; + + if(bpp <= 8) + current->flags |= SDL_HWPALETTE; + + User::Free(Private->iSwSurface); + current->pixels = NULL; + Private->iSwSurface = NULL; + + if(flags & SDL_HWSURFACE) + { + current->flags |= SDL_HWSURFACE; + // current->pixels = NULL; + // Private->iSwSurface = NULL; + } + else + { + current->flags |= SDL_SWSURFACE; + const TInt surfacesize = width * height * numBytesPerPixel; + Private->iSwSurfaceSize = TSize(width, height); + delete Private->iSwSurface; + Private->iSwSurface = NULL; + current->pixels = (TUint8*) User::AllocL(surfacesize); + Private->iSwSurface = (TUint8*) current->pixels; + const TInt err = EpocSdlEnv::AllocSwSurface + (TSize(width, height), GetDisplayMode(current->format->BitsPerPixel)); + if(err != KErrNone) + return NULL; + } + + current->w = width; + current->h = height; + + + + /* Set the blit function */ + _this->UpdateRects = EPOC_DirectUpdate; + + /* + * Logic for getting suitable screen dimensions, offset, scaling and orientation + */ + + + /* Centralize game window on device screen */ + + + Private->iScreenPos.iX = Max(0, (screenSize.iWidth - width) / 2); + Private->iScreenPos.iY = Max(0, (screenSize.iHeight - height) / 2); + + // delete (Private->iFrame); +// Private->iFrame = NULL; + + // TRAPD(err, CreateSurfaceL(_this, current)); + // PANIC_IF_ERROR(err); + + SDL_TRACE1("View width %d", width); + SDL_TRACE1("View height %d", height); + SDL_TRACE1("View bmode %d", bpp); + SDL_TRACE1("View x %d", Private->iScreenPos.iX); + SDL_TRACE1("View y %d", Private->iScreenPos.iY); + + EpocSdlEnv::LockPalette(EFalse); + /* We're done */ + return(current); +} + + + +static int EPOC_AllocHWSurface(_THIS, SDL_Surface* surface) + { + return KErrNone == EpocSdlEnv::AllocHwSurface(TSize(surface->w, surface->h), GetDisplayMode(surface->format->BitsPerPixel)); + } + +static void EPOC_FreeHWSurface(_THIS, SDL_Surface* /*surface*/) + { + } + +static int EPOC_LockHWSurface(_THIS, SDL_Surface* surface) + { + if(EpocSdlEnv::IsDsaAvailable()) + { + TUint8* address = EpocSdlEnv::LockHwSurface(); + if(address != NULL) + { + surface->pixels = address; + return 1; + } + } + return 0; + } +static void EPOC_UnlockHWSurface(_THIS, SDL_Surface* /*surface*/) + { + EpocSdlEnv::UnlockHwSurface(); + } + +static int EPOC_FlipHWSurface(_THIS, SDL_Surface* /*surface*/) + { + return(0); + } + +static void EPOC_DirectUpdate(_THIS, int numrects, SDL_Rect *rects) + { + if(EpocSdlEnv::IsDsaAvailable()) + { + if(Private->iSwSurface) + { + const TRect target(Private->iScreenPos, Private->iSwSurfaceSize); + for(TInt i = 0; i < numrects ;i++) + { + const TRect rect(TPoint(rects[i].x, rects[i].y), + TSize(rects[i].w, rects[i].h)); + if(!EpocSdlEnv::AddUpdateRect(Private->iSwSurface, rect, target)) + return; //not succesful + } + EpocSdlEnv::UpdateSwSurface(); + } + SDL_PauseAudio(0); + } + else + { + SDL_PauseAudio(1); + EpocSdlEnv::WaitDsaAvailable(); + } + } + + +/* Note: If we are terminated, this could be called in the middle of + another SDL video routine -- notably UpdateRects. +*/ +void EPOC_VideoQuit(_THIS) + { +// delete Private->iFrame; +// Private->iFrame = NULL; + User::Free(Private->iSwSurface); + Private->iSwSurface = NULL; + EpocSdlEnv::FreeSurface(); + } + + + + +WMcursor *EPOC_CreateWMCursor(_THIS, Uint8* /*data*/, Uint8* /*mask*/, int /*w*/, int /*h*/, int /*hot_x*/, int /*hot_y*/) + { + return (WMcursor*) 1; //hii! prevents SDL to view a std cursor + } + +void EPOC_FreeWMCursor(_THIS, WMcursor* /*cursor*/) + { + } + +int EPOC_ShowWMCursor(_THIS, WMcursor *cursor) + { + return true; + } + diff --git a/3rdparty/SDL/src/video/symbian/EKA2/SDL_epocvideo.h b/3rdparty/SDL/src/video/symbian/EKA2/SDL_epocvideo.h new file mode 100644 index 0000000..5aa3a20 --- /dev/null +++ b/3rdparty/SDL/src/video/symbian/EKA2/SDL_epocvideo.h @@ -0,0 +1,51 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Sam Lantinga + slouken@devolution.com +*/ + +#ifndef EPOCVIDEO_H +#define EPOCVIDEO_H + +#include<w32std.h> + +/* Hidden "this" pointer for the video functions */ +#define _THIS SDL_VideoDevice *_this +#define Private _this->hidden + +class CFbsBitmap; + +struct SDL_VideoDevice; +void DisableKeyBlocking(SDL_VideoDevice*); + +struct SDL_PrivateVideoData + { + TPoint iScreenPos; + TBool iIsWindowFocused; + TSize iSwSurfaceSize; + TUint8* iSwSurface; + SDL_Rect iRect; //same info in SDL format + SDL_Rect* iRectPtr; + }; + +#endif + + + + diff --git a/3rdparty/SDL/src/video/symbian/EKA2/dsa.cpp b/3rdparty/SDL/src/video/symbian/EKA2/dsa.cpp new file mode 100644 index 0000000..07b1ab4 --- /dev/null +++ b/3rdparty/SDL/src/video/symbian/EKA2/dsa.cpp @@ -0,0 +1,1505 @@ +#include "dsa.h" +#include "sdlepocapi.h" +#include <cdsb.h> + + +LOCAL_C TInt BytesPerPixel(TDisplayMode aMode) + { + return ((TDisplayModeUtils::NumDisplayModeBitsPerPixel(aMode) - 1) >> 3) + 1; + } + + + + +template<class T> +NONSHARABLE_CLASS(CBitmapSurface) : public T + { +public: + CBitmapSurface(RWsSession& aSession); +private: + void ConstructL(RWindow& aWindow, CWsScreenDevice& aDevice); + ~CBitmapSurface(); + TUint8* LockSurface(); + void UnlockHwSurface(); + void CreateSurfaceL(); + void Wipe(TInt aLength); + void Free(); + void Update(CFbsBitmap& aBmp); + TInt ExternalUpdate(); +private: + CFbsBitmap* iBmp; + CFbsBitmap* iCopyBmp; + }; + + +template<class T> +void CBitmapSurface<T>::ConstructL(RWindow& aWindow, CWsScreenDevice& aDevice) + { + delete iCopyBmp; + iCopyBmp = NULL; + iCopyBmp = new (ELeave) CFbsBitmap(); + T::ConstructL(aWindow, aDevice); + } + +template<class T> +CBitmapSurface<T>::CBitmapSurface(RWsSession& aSession) : T(aSession) + { + } + +template<class T> +void CBitmapSurface<T>::Free() + { + delete iBmp; + iBmp = NULL; + T::Free(); + } + +template<class T> +CBitmapSurface<T>::~CBitmapSurface() + { + __ASSERT_DEBUG(iBmp == NULL, PANIC(KErrNotReady)); + delete iCopyBmp; + } + +template<class T> +TUint8* CBitmapSurface<T>::LockSurface() + { + iBmp->LockHeap(); + return reinterpret_cast<TUint8*>(iBmp->DataAddress()); + } + + +template<class T> +void CBitmapSurface<T>::UnlockHwSurface() + { + iBmp->UnlockHeap(); + T::SetUpdating(EFalse); + Update(*iBmp); + } + + +template<class T> +void CBitmapSurface<T>::Update(CFbsBitmap& aBmp) + { + if(!T::Blitter(aBmp)) + { + if(T::SwSize() == T::HwRect().Size()) + T::Gc().BitBlt(T::HwRect().iTl, &aBmp); + else + T::Gc().DrawBitmap(T::HwRect(), &aBmp); + } + T::DrawOverlays(); + T::CompleteUpdate(); + } + +template<class T> +void CBitmapSurface<T>::CreateSurfaceL() + { + Free(); + iBmp = new (ELeave) CFbsBitmap(); + User::LeaveIfError(iBmp->Create(T::SwSize(), T::DisplayMode())); + T::CreateSurfaceL(*iBmp); + } + +template<class T> +void CBitmapSurface<T>::Wipe(TInt aLength) //dont call in drawing + { + iBmp->LockHeap(); + Mem::FillZ(iBmp->DataAddress(), aLength); + iBmp->UnlockHeap(); + } + +template<class T> +TInt CBitmapSurface<T>::ExternalUpdate() + { + if(iCopyBmp->Handle() == 0) + { + const TInt err = iCopyBmp->Duplicate(iBmp->Handle()); + if(err != KErrNone) + return err; + } + Update(*iCopyBmp); + return KErrNone; + } + + +////////////////////////////////////////////////////////////////////// + + + +NONSHARABLE_CLASS(CDsaBitgdi) : public CDsa + { +public: + CDsaBitgdi(RWsSession& aSession); +protected: + void ConstructL(RWindow& aWindow, CWsScreenDevice& aDevice); + CBitmapContext& Gc(); + void CompleteUpdate(); + ~CDsaBitgdi(); + void CreateSurfaceL(CFbsBitmap& aBmp); + void Free(); + void UnlockHWSurfaceRequestComplete(); +private: + void Resume(); + + CFbsBitGc* iGc; + CFbsDevice* iDevice; + CFbsBitmap* iBitGdiBmp; + CWindowGc* iWinGc; + RWindow* iWindow; + TInt iHandle; + }; + + +CDsaBitgdi::CDsaBitgdi(RWsSession& aSession) : CDsa(aSession) + { + } + +CDsaBitgdi::~CDsaBitgdi() + { + delete iWinGc; + delete iBitGdiBmp; + } + +void CDsaBitgdi::CompleteUpdate() + { + EpocSdlEnv::Request(CDsa::ERequestUpdate); + } + + +void CDsaBitgdi::UnlockHWSurfaceRequestComplete() + { + if(iHandle == 0) + return; + + if(iBitGdiBmp == NULL) + { + iBitGdiBmp = new CFbsBitmap(); + if(iBitGdiBmp == NULL) + return; + iBitGdiBmp->Duplicate(iHandle); + } + + iWindow->Invalidate(); + + iWindow->BeginRedraw(); + iWinGc->Activate(*iWindow); + iWinGc->BitBlt(TPoint(0, 0), iBitGdiBmp); + iWinGc->Deactivate(); + iWindow->EndRedraw(); + } + +void CDsaBitgdi::Resume() + { + Start(); + } + +CBitmapContext& CDsaBitgdi::Gc() + { + return *iGc; + } + + void CDsaBitgdi::ConstructL(RWindow& aWindow, CWsScreenDevice& aDevice) + { + + delete iBitGdiBmp; + iBitGdiBmp = NULL; + delete iWinGc; + iWinGc = NULL; + iHandle = 0; + + iWindow = &aWindow; + User::LeaveIfError(aDevice.CreateContext(iWinGc)); + CDsa::ConstructL(aWindow, aDevice); + Start(); + } + +void CDsaBitgdi::CreateSurfaceL(CFbsBitmap& aBmp) + { + iDevice = CFbsBitmapDevice::NewL(&aBmp); + User::LeaveIfError(iDevice->CreateContext(iGc)); + iHandle = aBmp.Handle(); + } + +void CDsaBitgdi::Free() + { + delete iGc; + iGc = NULL; + delete iDevice; + iDevice = NULL; + } + +//////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////// + +NONSHARABLE_CLASS(CDsaBase) : public CDsa, public MDirectScreenAccess + { +protected: + inline CDirectScreenAccess& Dsa() const; + CDsaBase(RWsSession& aSession); + ~CDsaBase(); + void ConstructL(RWindow& aWindow, CWsScreenDevice& aDevice); + void Stop(); + void Resume(); + CBitmapContext& Gc(); +protected: + CDirectScreenAccess* iDsa; +private: + void AbortNow(RDirectScreenAccess::TTerminationReasons aReason); + void Restart(RDirectScreenAccess::TTerminationReasons aReason); +private: + void RestartL(); + }; + + +inline CDirectScreenAccess& CDsaBase::Dsa() const + { + return *iDsa; + } + + +CDsaBase::CDsaBase(RWsSession& aSession) : CDsa(aSession) + { + } + +CBitmapContext& CDsaBase::Gc() + { + return *Dsa().Gc(); + } + +void CDsaBase::ConstructL(RWindow& aWindow, CWsScreenDevice& aDevice) + { + CDsa::ConstructL(aWindow, aDevice); + if(iDsa != NULL) + { + iDsa->Cancel(); + delete iDsa; + iDsa = NULL; + } + + iDsa = CDirectScreenAccess::NewL( + Session(), + aDevice, + aWindow, + *this); + RestartL(); + } + +void CDsaBase::Resume() + { + if(Stopped()) + Restart(RDirectScreenAccess::ETerminateRegion); + } + +CDsaBase::~CDsaBase() + { + if(iDsa != NULL) + { + iDsa->Cancel(); + } + delete iDsa; + } + + +void CDsaBase::RestartL() + { + + + iDsa->StartL(); + + const RRegion* r = iDsa->DrawingRegion(); + const TRect rect = r->BoundingRect(); + iDsa->Gc()->SetClippingRegion(r); + + if(rect != ScreenRect()) + { + return ; + } + + + SetTargetRect(); + RecreateL(); + + Start(); + + + } + +void CDsaBase::AbortNow(RDirectScreenAccess::TTerminationReasons /*aReason*/) + { + Stop(); + } + +void CDsaBase::Restart(RDirectScreenAccess::TTerminationReasons aReason) + { + if(aReason == RDirectScreenAccess::ETerminateRegion) //auto restart + { + TRAPD(err, RestartL()); + PANIC_IF_ERROR(err); + } + } + + +void CDsaBase::Stop() + { + CDsa::Stop(); + iDsa->Cancel(); + } + + + /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// +NONSHARABLE_CLASS(TDsa) + { + public: + inline TDsa(const CDsa& aDsa); + inline TBool IsFlip() const; + inline TBool IsTurn() const; + inline const TSize& SwSize() const; + inline void Copy(TUint32* aTarget, const TUint8* aSrc, TInt aBytes, TInt aHeight) const; + private: + const CDsa& iDsa; + }; + + + + +inline TDsa::TDsa(const CDsa& aDsa) : iDsa(aDsa) + { + } + +inline TBool TDsa::IsTurn() const + { + return iDsa.iStateFlags & CDsa::EOrientation90; + } + +inline TBool TDsa::IsFlip() const + { + return iDsa.iStateFlags & CDsa::EOrientation180; + } + +inline const TSize& TDsa::SwSize() const + { + return iDsa.SwSize(); + } + +inline void TDsa::Copy(TUint32* aTarget, const TUint8* aSrc, TInt aBytes, TInt aHeight) const + { + iDsa.iCopyFunction(iDsa, aTarget, aSrc, aBytes, aHeight); + } + +template<class T, class S> +void ClipCopy(const TDsa& iDsa, TUint8* aTarget, + const TUint8* aSource, + const TRect& aUpdateRect, + const TRect& aSourceRect) + { + const S* source = reinterpret_cast<const S*>(aSource); + const TInt lineWidth = aSourceRect.Width(); + + source += (aUpdateRect.iTl.iY * lineWidth); + const TInt sourceStartOffset = aUpdateRect.iTl.iX; + source += sourceStartOffset; + + T* targetPtr = reinterpret_cast<T*>(aTarget); + + const TInt scanLineWidth = iDsa.SwSize().iWidth; + + targetPtr += (aSourceRect.iTl.iY + aUpdateRect.iTl.iY ) * scanLineWidth; + const TInt targetStartOffset = (aUpdateRect.iTl.iX + aSourceRect.iTl.iX); + + targetPtr += targetStartOffset; + + + const TInt height = aUpdateRect.Height(); + + const TInt lineMove = iDsa.IsTurn() ? 1 : lineWidth; + const TInt copyLen = aUpdateRect.Width(); + + + if(iDsa.IsFlip()) + { + + targetPtr += scanLineWidth * (height - 1); + + for(TInt i = 0; i < height; i++) //source is always smaller + { + iDsa.Copy(reinterpret_cast<TUint32*>(targetPtr), reinterpret_cast<const TUint8*>(source), copyLen, height); + source += lineMove; + targetPtr -= scanLineWidth; + } + } + else + { + + + for(TInt i = 0; i < height; i++) //source is always smaller + { + iDsa.Copy(reinterpret_cast<TUint32*>(targetPtr), reinterpret_cast<const TUint8*>(source), copyLen, height); + source += lineMove; + targetPtr += scanLineWidth; // >> 2; + } + } + + } + + + +NONSHARABLE_CLASS(CDsaA) : public CDsaBase + { + public: + CDsaA(RWsSession& aSession); + protected: + void ConstructL(RWindow& aWindow, CWsScreenDevice& aDevice); + void CompleteUpdate(); + void CreateSurfaceL(CFbsBitmap& aBmp); + void Free(); + void UnlockHWSurfaceRequestComplete(); + }; + + +CDsaA::CDsaA(RWsSession& aSession) : CDsaBase(aSession) + { + } + + +void CDsaA::ConstructL(RWindow& aWindow, CWsScreenDevice& aDevice) + { + CDsaBase::ConstructL(aWindow, aDevice); + } + +void CDsaA::CompleteUpdate() + { + iDsa->ScreenDevice()->Update(); + } + +void CDsaA::CreateSurfaceL(CFbsBitmap& /*aBmp*/) + { + } + +void CDsaA::Free() + { + + } + +void CDsaA::UnlockHWSurfaceRequestComplete() + { + PANIC(KErrNotSupported); + } + + + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +NONSHARABLE_CLASS(MDsbObs) + { + public: + virtual void SurfaceReady() = 0; + virtual CDirectScreenBitmap& Dsb() = 0; + }; + +NONSHARABLE_CLASS(CDsbSurface) : public CActive + { + public: + CDsbSurface(MDsbObs& aDsb); + TUint8* Address(); + void Complete(); + ~CDsbSurface(); + private: + void RunL(); + void DoCancel(); + private: + MDsbObs& iDsb; + TUint8* iAddress; + }; + +CDsbSurface::CDsbSurface(MDsbObs& aDsb) : CActive(CActive::EPriorityHigh) , iDsb(aDsb) + { + CActiveScheduler::Add(this); + } + +CDsbSurface::~CDsbSurface() + { + Cancel(); + } + +void CDsbSurface::Complete() + { + if(iAddress != NULL && !IsActive()) + { + iAddress = NULL; + SetActive(); + iDsb.Dsb().EndUpdate(iStatus); + } + } + +TUint8* CDsbSurface::Address() + { + if(iAddress == NULL && !IsActive()) + { + TAcceleratedBitmapInfo info; + if(KErrNone == iDsb.Dsb().BeginUpdate(info)) + iAddress = info.iAddress; + } + return iAddress; + } + +void CDsbSurface::RunL() + { + iDsb.SurfaceReady(); + } + +void CDsbSurface::DoCancel() + { + //empty + } + +NONSHARABLE_CLASS(CDsaB) : public CDsaBase, + public MDsbObs + { + public: + CDsaB(RWsSession& aSession, TInt aFlags); + private: + ~CDsaB(); + TUint8* LockSurface(); + void UnlockHWSurfaceRequestComplete(); + void UnlockHwSurface(); + void CreateSurfaceL(); + void Wipe(TInt aLength); + void RecreateL(); + void ConstructL(RWindow& aWindow, CWsScreenDevice& aDevice); + CDirectScreenBitmap& Dsb(); + void SurfaceReady(); + TInt ExternalUpdate(); + private: + CDsbSurface* iSurface1; + CDsbSurface* iSurface2; + CDirectScreenBitmap* iDsb; + TInt iType; + }; + +CDsaB::CDsaB(RWsSession& aSession, TInt aFlags) : CDsaBase(aSession), iType(aFlags) + { + } + + + +void CDsaB::UnlockHWSurfaceRequestComplete() + { + iSurface1->Complete(); + if(iSurface2 != NULL) + iSurface2->Complete(); + } + +void CDsaB::CreateSurfaceL() + { + __ASSERT_ALWAYS(SwSize() == HwRect().Size(), PANIC(KErrNotSupported)); + } + +void CDsaB::Wipe(TInt aLength) //dont call in drawing + { + TUint8* addr = LockSurface(); + if(addr != NULL) + { + Mem::FillZ(addr, aLength); + UnlockHwSurface(); + } + } + + +void CDsaB::UnlockHwSurface() + { + EpocSdlEnv::Request(CDsa::ERequestUpdate); + } + +TUint8* CDsaB::LockSurface() + { + TUint8* addr = iSurface1->Address(); + if(addr == NULL && iSurface2 != NULL) + addr = iSurface2->Address(); + SetUpdating(addr == NULL); + return addr; + } + +void CDsaB::SurfaceReady() + { + SetUpdating(EFalse); + } + +CDirectScreenBitmap& CDsaB::Dsb() + { + return *iDsb; + } + +void CDsaB::ConstructL(RWindow& aWindow, CWsScreenDevice& aDevice) + { + if(iDsb == NULL) + iDsb = CDirectScreenBitmap::NewL(); + CDsaBase::ConstructL(aWindow, aDevice); + if(iSurface1 == NULL) + iSurface1 = new (ELeave) CDsbSurface(*this); + if(iSurface2 == NULL && iType & CDirectScreenBitmap::EDoubleBuffer) + iSurface2 = new (ELeave) CDsbSurface(*this); + } + +CDsaB::~CDsaB() + { + delete iSurface1; + delete iSurface2; + delete iDsb; + } + +void CDsaB::RecreateL() + { + iDsb->Close(); + iDsb->Create(HwRect(), CDirectScreenBitmap::TSettingsFlags(iType)); + } + +TInt CDsaB::ExternalUpdate() + { + if(LockSurface()) + { + UnlockHWSurfaceRequestComplete(); + return KErrNone; + } + return KErrNotReady; + } + + +///////////////////////////////////////////////////////////////////////////////////////////////////// + + + +CDsa* CDsa::CreateL(RWsSession& aSession) + { + if(EpocSdlEnv::Flags(CSDL::EDrawModeDSB)) + { + TInt flags = CDirectScreenBitmap::ENone; + if(EpocSdlEnv::Flags(CSDL::EDrawModeDSBDoubleBuffer)) + flags |= CDirectScreenBitmap::EDoubleBuffer; + if(EpocSdlEnv::Flags(CSDL::EDrawModeDSBIncrementalUpdate)) + flags |= CDirectScreenBitmap::EIncrementalUpdate; + return new (ELeave) CDsaB(aSession, flags); + } + else if(EpocSdlEnv::Flags(CSDL::EDrawModeGdi)) + { + return new (ELeave) CBitmapSurface<CDsaBitgdi>(aSession); + } + else + { + return new (ELeave) CBitmapSurface<CDsaA>(aSession); + } + } + + +void CDsa::RecreateL() + { + } + +void CDsa::Free() + { + } + +TSize CDsa::WindowSize() const + { + TSize size = iSwSize; + if(iStateFlags & EOrientation90) + { + const TInt tmp = size.iWidth; + size.iWidth = size.iHeight; + size.iHeight = tmp; + } + return size; + } + +void CDsa::SetSuspend() + { + iStateFlags |= ESdlThreadSuspend; + } + + +void CDsa::SetUpdating(TBool aUpdate) + { + if(aUpdate) + iStateFlags |= EUpdating; + else + iStateFlags &= ~EUpdating; + } + + +TBool CDsa::Stopped() const + { + return (iStateFlags & ESdlThreadExplicitStop); + } + +void CDsa::SetOrientation(CSDL::TOrientationMode aOrientation) + { + TInt flags = 0; + switch(aOrientation) + { + case CSDL::EOrientation90: + flags = EOrientation90; + break; + case CSDL::EOrientation180: + flags = EOrientation180; + break; + case CSDL::EOrientation270: + flags = EOrientation90 | EOrientation180; + break; + case CSDL::EOrientation0: + flags = 0; + break; + } + if(flags != (iStateFlags & EOrientationFlags)) + { + iStateFlags |= EOrientationChanged; + iNewFlags = flags; //cannot be set during drawing... + } + } + +CDsa::~CDsa() + { + iOverlays.Close(); + User::Free(iLut256); + } + +void CDsa::ConstructL(RWindow& aWindow, CWsScreenDevice& /*aDevice*/) + { + if(iLut256 == NULL) + iLut256 = (TUint32*) User::AllocL(256 * sizeof(TUint32)); + iTargetMode = aWindow.DisplayMode(); + iTargetBpp = BytesPerPixel(DisplayMode()); + iScreenRect = TRect(aWindow.Position(), aWindow.Size()); + SetTargetRect(); + } + +void CDsa::DrawOverlays() + { + const TInt last = iOverlays.Count() - 1; + for(TInt i = last; i >= 0 ; i--) + iOverlays[i].iOverlay->Draw(Gc(), HwRect(), SwSize()); + } + +TInt CDsa::AppendOverlay(MOverlay& aOverlay, TInt aPriority) + { + TInt i; + for(i = 0; i < iOverlays.Count() && iOverlays[i].iPriority < aPriority; i++) + {} + const TOverlay overlay = {&aOverlay, aPriority}; + return iOverlays.Insert(overlay, i); + } + +TInt CDsa::RemoveOverlay(MOverlay& aOverlay) + { + for(TInt i = 0; i < iOverlays.Count(); i++) + { + if(iOverlays[i].iOverlay == &aOverlay) + { + iOverlays.Remove(i); + return KErrNone; + } + } + return KErrNotFound; + } + +void CDsa::LockPalette(TBool aLock) + { + if(aLock) + iStateFlags |= EPaletteLocked; + else + iStateFlags &= ~EPaletteLocked; + } +TInt CDsa::SetPalette(TInt aFirst, TInt aCount, TUint32* aPalette) + { + if(iLut256 == NULL) + return KErrNotFound; + const TInt count = aCount - aFirst; + if(count > 256) + return KErrArgument; + if(iStateFlags & EPaletteLocked) + return KErrNone; + for(TInt i = aFirst; i < count; i++) //not so busy here:-) + { + iLut256[i] = aPalette[i]; + } + return KErrNone; + } + + + + + +CDsa::CDsa(RWsSession& aSession) : + iStateFlags(0), + iSession(aSession) + + { +// CActiveScheduler::Add(this); + iCFTable[0] = CopyMem; + iCFTable[1] = CopyMemFlipReversed; + iCFTable[2] = CopyMemReversed; + iCFTable[3] = CopyMemFlip; + + iCFTable[4] = Copy256; + iCFTable[5] = Copy256FlipReversed; + iCFTable[6] = Copy256Reversed; + iCFTable[7] = Copy256Flip; + + + iCFTable[8] = CopySlow; + iCFTable[9] = CopySlowFlipReversed; + iCFTable[10] = CopySlowReversed; + iCFTable[11] = CopySlowFlip; + } + +RWsSession& CDsa::Session() + { + return iSession; + } + +TInt CDsa::RedrawRequest() + { + if(!(iStateFlags & (EUpdating) && (iStateFlags & ERunning))) + { + return ExternalUpdate(); + } + return KErrNotReady; + } + +TUint8* CDsa::LockHwSurface() + { + if((iStateFlags & EUpdating) == 0) //else frame is skipped + { + return LockSurface(); + } + return NULL; + } + +/* +void CDsa::RunL() + { + iStateFlags &= ~EUpdating; + } + + +void CDsa::DoCancel() + { + iStateFlags &= ~EUpdating; + //nothing can do, just wait? + } +*/ + + +TInt CDsa::AllocSurface(TBool aHwSurface, const TSize& aSize, TDisplayMode aMode) + { + if(aHwSurface && aMode != DisplayMode()) + return KErrArgument; + + iSourceMode = aMode; + + iSourceBpp = BytesPerPixel(aMode); + + const TSize size = WindowSize(); + if(aSize.iWidth > size.iWidth) + return KErrTooBig; + if(aSize.iHeight > size.iHeight) + return KErrTooBig; + + TRAPD(err, CreateSurfaceL()); + if(err != KErrNone) + return err; + + SetCopyFunction(); + + return KErrNone; + } + + +void CDsa::CreateZoomerL(const TSize& aSize) + { + iSwSize = aSize; + iStateFlags |= EResizeRequest; + CreateSurfaceL(); + SetTargetRect(); + } + + +/* +void SaveBmp(const TDesC& aName, const TAny* aData, TInt aLength, const TSize& aSz, TDisplayMode aMode) + { + CFbsBitmap* s = new CFbsBitmap(); + s->Create(aSz, aMode); + s->LockHeap(); + TUint32* addr = s->DataAddress(); + Mem::Copy(addr, aData, aLength); + s->UnlockHeap(); + s->Save(aName); + s->Reset(); + delete s; + } + +void SaveBmp(const TDesC& aName, const TUint32* aData, const TSize& aSz) + { + CFbsBitmap* s = new CFbsBitmap(); + s->Create(aSz, EColor64K); + TBitmapUtil bmp(s); + bmp.Begin(TPoint(0, 0)); + for(TInt j = 0; j < aSz.iHeight; j++) + { + bmp.SetPos(TPoint(0, j)); + for(TInt i = 0; i < aSz.iWidth; i++) + { + bmp.SetPixel(*aData); + aData++; + bmp.IncXPos(); + } + } + bmp.End(); + s->Save(aName); + s->Reset(); + delete s; + } + +TBuf<16> FooName(TInt aFoo) + { + TBuf<16> b; + b.Format(_L("C:\\pic%d.mbm"), aFoo); + return b; + } + +*/ + + +void CDsa::ClipCopy(TUint8* aTarget, + const TUint8* aSource, + const TRect& aUpdateRect, + const TRect& aSourceRect) const + { + const TDsa dsa(*this); + switch(iSourceBpp) + { + case 1: + ::ClipCopy<TUint32, TUint8>(dsa, aTarget, aSource, aUpdateRect, aSourceRect); + break; + case 2: + ::ClipCopy<TUint32, TUint16>(dsa, aTarget, aSource, aUpdateRect, aSourceRect); + break; + case 4: + ::ClipCopy<TUint32, TUint32>(dsa, aTarget, aSource, aUpdateRect, aSourceRect); + break; + } + } + + +void CDsa::Wipe() //dont call in drawing + { + if(IsDsaAvailable()) + Wipe(iTargetBpp * SwSize().iWidth * SwSize().iHeight); + } + +void CDsa::SetCopyFunction() + { + //calculate offset to correct function in iCFTable according to given parameters + TInt function = 0; + const TInt KCopyFunctions = 4; + const TInt KOffsetToNative = 0; + const TInt KOffsetTo256 = KOffsetToNative + KCopyFunctions; + const TInt KOffsetToOtherModes = KOffsetTo256 + KCopyFunctions; + const TInt KOffsetTo90Functions = 1; + const TInt KOffsetTo180Functions = 2; + + if(iSourceMode == DisplayMode()) + function = KOffsetToNative; //0 + else if(iSourceMode == EColor256) + function = KOffsetTo256; //4 + else + function = KOffsetToOtherModes; //8 + + if(iStateFlags & EOrientation90) + function += KOffsetTo90Functions; // + 1 + if(iStateFlags & EOrientation180) + function += KOffsetTo180Functions; //+ 2 + + iCopyFunction = iCFTable[function]; + + Wipe(); + } + +inline void Rotate(TRect& aRect) + { + const TInt dx = aRect.iBr.iX - aRect.iTl.iX; + const TInt dy = aRect.iBr.iY - aRect.iTl.iY; + + aRect.iBr.iX = aRect.iTl.iX + dy; + aRect.iBr.iY = aRect.iTl.iY + dx; + + const TInt tmp = aRect.iTl.iX; + aRect.iTl.iX = aRect.iTl.iY; + aRect.iTl.iY = tmp; + } + +/* +int bar = 0; +*/ + +TBool CDsa::AddUpdateRect(const TUint8* aBits, const TRect& aUpdateRect, const TRect& aRect) + { + + if(iStateFlags & EOrientationChanged) + { + iStateFlags &= ~EOrientationFlags; + iStateFlags |= iNewFlags; + SetCopyFunction(); + iStateFlags &= ~EOrientationChanged; + EpocSdlEnv::WaitDeviceChange(); + return EFalse; //skip this frame as data is may be changed + } + + if(iTargetAddr == NULL) + { + iTargetAddr = LockHwSurface(); + } + + TUint8* target = iTargetAddr; + if(target == NULL) + return EFalse; + + + TRect targetRect = TRect(TPoint(0, 0), SwSize()); + + TRect sourceRect = aRect; + TRect updateRect = aUpdateRect; + +// TPoint move(0, 0); + + + if(iStateFlags & EOrientation90) + { + Rotate(sourceRect); + Rotate(updateRect); + } + + if(iSourceMode != DisplayMode() || targetRect != sourceRect || targetRect != updateRect || ((iStateFlags & EOrientationFlags) != 0)) + { + sourceRect.Intersection(targetRect); //so source always smaller or equal than target + //updateRect.Intersection(targetRect); + ClipCopy(target, aBits, updateRect, sourceRect); + } + else + { + const TInt byteCount = aRect.Width() * aRect.Height() * iSourceBpp; //this could be stored + Mem::Copy(target, aBits, byteCount); + } + + return ETrue; + } + + +void CDsa::UpdateSwSurface() + { + iTargetAddr = NULL; + UnlockHwSurface(); //could be faster if does not use AO, but only check status before redraw, then no context switch needed + } + + + + +void CDsa::DoStop() + { + if(IsDsaAvailable()) + iStateFlags |= ESdlThreadExplicitStop; + Stop(); + } + + +void CDsa::Stop() + { + iStateFlags &= ~ERunning; + } + +void CDsa::Start() + { + iStateFlags |= ERunning; + + iStateFlags &= ~ESdlThreadExplicitStop; + + if(iStateFlags & ESdlThreadSuspend) + { + EpocSdlEnv::Resume(); + iStateFlags &= ~ ESdlThreadSuspend; + } + EpocSdlEnv::ObserverEvent(MSDLObserver::EEventWindowReserved); + } + + +TBool CDsa::Blitter(CFbsBitmap& aBmp) + { + return iBlitter && iBlitter->BitBlt(Gc(), aBmp, HwRect(), SwSize()); + } + +void CDsa::SetBlitter(MBlitter* aBlitter) + { + iBlitter = aBlitter; + } + + +TPoint CDsa::WindowCoordinates(const TPoint& aPoint) const + { + TPoint pos = aPoint - iScreenRect.iTl; + const TSize asz = iScreenRect.Size(); + if(iStateFlags & EOrientation180) + { + pos.iX = asz.iWidth - pos.iX; + pos.iY = asz.iHeight - pos.iY; + } + if(iStateFlags & EOrientation90) + { + pos.iX = aPoint.iY; + pos.iY = aPoint.iX; + } + pos.iX <<= 16; + pos.iY <<= 16; + pos.iX /= asz.iWidth; + pos.iY /= asz.iHeight; + pos.iX *= iSwSize.iWidth; + pos.iY *= iSwSize.iHeight; + pos.iX >>= 16; + pos.iY >>= 16; + return pos; + } + +void CDsa::SetTargetRect() + { + iTargetRect = iScreenRect; + if(iStateFlags & EResizeRequest && EpocSdlEnv::Flags(CSDL::EAllowImageResizeKeepRatio)) + { + const TSize asz = iScreenRect.Size(); + const TSize sz = iSwSize; + + TRect rect; + + const TInt dh = (sz.iHeight << 16) / sz.iWidth; + + if((asz.iWidth * dh ) >> 16 <= asz.iHeight) + { + rect.SetRect(TPoint(0, 0), TSize(asz.iWidth, (asz.iWidth * dh) >> 16)); + } + else + { + const TInt dw = (sz.iWidth << 16) / sz.iHeight; + rect.SetRect(TPoint(0, 0), TSize((asz.iHeight * dw) >> 16, asz.iHeight)); + } + rect.Move((asz.iWidth - rect.Size().iWidth) >> 1, (asz.iHeight - rect.Size().iHeight) >> 1); + + iTargetRect = rect; + iTargetRect.Move(iScreenRect.iTl); + + } + if(!(iStateFlags & EResizeRequest)) + iSwSize = iScreenRect.Size(); + + } + + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +void CDsa::Copy256(const CDsa& aDsa, TUint32* aTarget, const TUint8* aSource, TInt aBytes, TInt) + { + TUint32* target = aTarget; + const TUint32* endt = target + aBytes; + const TUint8* source = aSource; + while(target < endt) + { + *target++ = aDsa.iLut256[*source++]; + } + } + +void CDsa::Copy256Reversed(const CDsa& aDsa, TUint32* aTarget, const TUint8* aSource, TInt aBytes, TInt) + { + const TUint32* target = aTarget; + TUint32* endt = aTarget + aBytes; + const TUint8* source = aSource; + while(target < endt) + { + *(--endt) = aDsa.iLut256[*source++]; + } + } + +void CDsa::Copy256Flip(const CDsa& aDsa, TUint32* aTarget, const TUint8* aSource, TInt aBytes, TInt aLineLen) + { + TUint32* target = aTarget; + const TUint32* endt = target + aBytes; + const TUint8* column = aSource; + + while(target < endt) + { + *target++ = aDsa.iLut256[*column]; + column += aLineLen; + } + } + +void CDsa::Copy256FlipReversed(const CDsa& aDsa, TUint32* aTarget, const TUint8* aSource, TInt aBytes, TInt aLineLen) + { + const TUint32* target = aTarget; + TUint32* endt = aTarget + aBytes; + const TUint8* column = aSource; + + while(target < endt) + { + *(--endt) = aDsa.iLut256[*column]; + column += aLineLen; + } + } + +void CDsa::CopyMem(const CDsa& /*aDsa*/, TUint32* aTarget, const TUint8* aSource, TInt aBytes, TInt) + { + const TUint32* src = reinterpret_cast<const TUint32*>(aSource); + Mem::Copy(aTarget, src, aBytes << 2); + } + +void CDsa::CopyMemFlip(const CDsa& /*aDsa*/, TUint32* aTarget, const TUint8* aSource, TInt aBytes, TInt aLineLen) + { + TUint32* target = aTarget; + const TUint32* endt = target + aBytes; + const TUint32* column = reinterpret_cast<const TUint32*>(aSource); + + while(target < endt) + { + *target++ = *column; + column += aLineLen; + } + } + +void CDsa::CopyMemReversed(const CDsa& /*aDsa*/, TUint32* aTarget, const TUint8* aSource, TInt aBytes, TInt) + { + const TUint32* target = aTarget; + TUint32* endt = aTarget + aBytes; + const TUint32* source = reinterpret_cast<const TUint32*>(aSource); + while(target < endt) + { + *(--endt) = *source++; + } + } + + +void CDsa::CopyMemFlipReversed(const CDsa& /*aDsa*/, TUint32* aTarget, const TUint8* aSource, TInt aBytes, TInt aLineLen) + { + const TUint32* target = aTarget; + TUint32* endt = aTarget + aBytes; + const TUint32* column = reinterpret_cast<const TUint32*>(aSource); + + while(target < endt) + { + *(--endt) = *column; + column += aLineLen; + } + } + +/* + +LOCAL_C TRgb rgb16MA(TInt aValue) + { + return TRgb::Color16MA(aValue); + } +*/ +NONSHARABLE_CLASS(MRgbCopy) + { + public: + virtual void Copy(TUint32* aTarget, const TUint8* aSource, TInt aBytes, TBool aReversed) = 0; + virtual void FlipCopy(TUint32* aTarget, const TUint8* aSource, TInt aBytes, TInt aLineLen, TBool aReversed) = 0; + }; + +template <class T> +NONSHARABLE_CLASS(TRgbCopy) : public MRgbCopy + { + public: + TRgbCopy(TDisplayMode aMode); + void* operator new(TUint aBytes, TAny* aMem); + void Copy(TUint32* aTarget, const TUint8* aSource, TInt aBytes, TBool aReversed); + void FlipCopy(TUint32* aTarget, const TUint8* aSource, TInt aBytes, TInt aLineLen, TBool aReversed); + static TUint32 Gray256(const TUint8& aPixel); + static TUint32 Color256(const TUint8& aPixel); + static TUint32 Color4K(const TUint16& aPixel); + static TUint32 Color64K(const TUint16& aPixel); + static TUint32 Color16M(const TUint32& aPixel); + static TUint32 Color16MU(const TUint32& aPixel); + static TUint32 Color16MA(const TUint32& aPixel); + private: + typedef TUint32 (*TRgbFunc) (const T& aValue); + TRgbFunc iFunc; + }; + + +template <class T> +void* TRgbCopy<T>::operator new(TUint /*aBytes*/, TAny* aMem) + { + return aMem; + } + +template <class T> +TRgbCopy<T>::TRgbCopy(TDisplayMode aMode) + { + switch(aMode) + { + case EGray256 : iFunc = (TRgbFunc) Gray256; break; + case EColor256 : iFunc = (TRgbFunc) Color256; break; + case EColor4K : iFunc = (TRgbFunc) Color4K; break; + case EColor64K : iFunc = (TRgbFunc) Color64K; break; + case EColor16M : iFunc = (TRgbFunc) Color16M; break; + case EColor16MU : iFunc = (TRgbFunc) Color16MU; break; + case EColor16MA : iFunc = (TRgbFunc) Color16MA; break; + default: + PANIC(KErrNotSupported); + } + } + +template <class T> +void TRgbCopy<T>::Copy(TUint32* aTarget, const TUint8* aSource, TInt aBytes, TBool aReversed) + { + const T* source = reinterpret_cast<const T*>(aSource); + TUint32* target = aTarget; + TUint32* endt = target + aBytes; + + if(aReversed) + { + while(target < endt) + { + const T value = *source++; + *(--endt) = iFunc(value);//iFunc(value).Value(); + } + } + else + { + while(target < endt) + { + const T value = *source++; + *target++ = iFunc(value);//iFunc(value).Value(); + } + } + } + +template <class T> +void TRgbCopy<T>::FlipCopy(TUint32* aTarget, const TUint8* aSource, TInt aBytes, TInt aLineLen, TBool aReversed) + { + const T* column = reinterpret_cast<const T*>(aSource); + TUint32* target = aTarget; + TUint32* endt = target + aBytes; + + if(aReversed) + { + while(target < endt) + { + *(--endt) = iFunc(*column); + column += aLineLen; + } + } + else + { + while(target < endt) + { + *target++ = iFunc(*column); + column += aLineLen; + } + } + } + +template <class T> TUint32 TRgbCopy<T>::Gray256(const TUint8& aPixel) + { + const TUint32 px = aPixel << 16 | aPixel << 8 | aPixel; + return px; + } + +template <class T> TUint32 TRgbCopy<T>::Color256(const TUint8& aPixel) + { + return TRgb::Color256(aPixel).Value(); + } + +template <class T> TUint32 TRgbCopy<T>::Color4K(const TUint16& aPixel) + { + TUint32 col = (aPixel & 0xF00) << 12; + col |= (aPixel & 0xF00) << 8; + + col |= (aPixel & 0x0F0) << 8; + col |= (aPixel & 0x0F0); + + col |= (aPixel & 0x00F) << 4; + col |= (aPixel & 0x00F); + + return col; + } + +template <class T> TUint32 TRgbCopy<T>::Color64K(const TUint16& aPixel) + { + TUint32 col = (aPixel & 0xF800)<< 8; + col |= (aPixel & 0xE000) << 3; + + col |= (aPixel & 0x07E0) << 5; + col |= (aPixel & 0xC0) >> 1; + + col |= (aPixel & 0x07E0) << 3; + col |= (aPixel & 0x1C) >> 2; + + return col; + } + +template <class T> TUint32 TRgbCopy<T>::Color16M(const TUint32& aPixel) + { + return TRgb::Color16M(aPixel).Value(); + } + +template <class T> TUint32 TRgbCopy<T>::Color16MU(const TUint32& aPixel) + { + return TRgb::Color16MU(aPixel).Value(); + } + +template <class T> TUint32 TRgbCopy<T>::Color16MA(const TUint32& aPixel) + { + return TRgb::Color16MA(aPixel).Value(); + } + +typedef TUint64 TStackMem; + +LOCAL_C MRgbCopy* GetCopy(TAny* mem, TDisplayMode aMode) + { + if(aMode == EColor256 || aMode == EGray256) + { + return new (mem) TRgbCopy<TUint8>(aMode); + } + if(aMode == EColor4K || aMode == EColor64K) + { + return new (mem) TRgbCopy<TUint16>(aMode); + } + if(aMode == EColor16M || aMode == EColor16MU || aMode == EColor16MA) + { + return new (mem) TRgbCopy<TUint32>(aMode); + } + PANIC(KErrNotSupported); + return NULL; + } + + +void CDsa::CopySlowFlipReversed(const CDsa& aDsa, TUint32* aTarget, const TUint8* aSource, TInt aBytes, TInt aLineLen) + { + TStackMem mem = 0; + GetCopy(&mem, aDsa.iSourceMode)->FlipCopy(aTarget, aSource, aBytes, aLineLen, ETrue); + } + +void CDsa::CopySlowFlip(const CDsa& aDsa, TUint32* aTarget, const TUint8* aSource, TInt aBytes, TInt aLineLen) + { + TStackMem mem = 0; + GetCopy(&mem, aDsa.iSourceMode)->FlipCopy(aTarget, aSource, aBytes, aLineLen, EFalse); + } + +void CDsa::CopySlow(const CDsa& aDsa, TUint32* aTarget, const TUint8* aSource, TInt aBytes, TInt) + { + TStackMem mem = 0; + GetCopy(&mem, aDsa.iSourceMode)->Copy(aTarget, aSource, aBytes, EFalse); + } + +void CDsa::CopySlowReversed(const CDsa& aDsa, TUint32* aTarget, const TUint8* aSource, TInt aBytes, TInt) + { + TStackMem mem = 0; + GetCopy(&mem, aDsa.iSourceMode)->Copy(aTarget, aSource, aBytes, ETrue); + } + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////7 diff --git a/3rdparty/SDL/src/video/symbian/EKA2/dsa_new.cpp b/3rdparty/SDL/src/video/symbian/EKA2/dsa_new.cpp new file mode 100644 index 0000000..638fbe8 --- /dev/null +++ b/3rdparty/SDL/src/video/symbian/EKA2/dsa_new.cpp @@ -0,0 +1,1443 @@ +#include "dsa.h" +#include "sdlepocapi.h" +#include <cdsb.h> + + +LOCAL_C TInt BytesPerPixel(TDisplayMode aMode) + { + return ((TDisplayModeUtils::NumDisplayModeBitsPerPixel(aMode) - 1) >> 3) + 1; + } + + +NONSHARABLE_CLASS(TDsa) + { + public: + inline TDsa(const CDsa& aDsa); + inline TBool IsFlip() const; + inline TBool IsTurn() const; + inline const TSize& SwSize() const; + inline void Copy(TUint32* aTarget, const TUint8* aSrc, TInt aBytes, TInt aHeight) const; + private: + const CDsa& iDsa; + }; + + +inline TDsa::TDsa(const CDsa& aDsa) : iDsa(aDsa) + { + } + +inline TBool TDsa::IsTurn() const + { + return iDsa.iStateFlags & CDsa::EOrientation90; + } + +inline TBool TDsa::IsFlip() const + { + return iDsa.iStateFlags & CDsa::EOrientation180; + } + +inline const TSize& TDsa::SwSize() const + { + return iDsa.SwSize(); + } + +inline void TDsa::Copy(TUint32* aTarget, const TUint8* aSrc, TInt aBytes, TInt aHeight) const + { + iDsa.iCopyFunction(iDsa, aTarget, aSrc, aBytes, aHeight); + } + +template<class T, class S> +void ClipCopy(const TDsa& iDsa, TUint8* aTarget, + const TUint8* aSource, + const TRect& aUpdateRect, + const TRect& aSourceRect) + { + const S* source = reinterpret_cast<const S*>(aSource); + const TInt lineWidth = aSourceRect.Width(); + + source += (aUpdateRect.iTl.iY * lineWidth); + const TInt sourceStartOffset = aUpdateRect.iTl.iX; + source += sourceStartOffset; + + T* targetPtr = reinterpret_cast<T*>(aTarget); + + const TInt scanLineWidth = iDsa.SwSize().iWidth; + + targetPtr += (aSourceRect.iTl.iY + aUpdateRect.iTl.iY ) * scanLineWidth; + const TInt targetStartOffset = (aUpdateRect.iTl.iX + aSourceRect.iTl.iX); + + targetPtr += targetStartOffset; + + + const TInt height = aUpdateRect.Height(); + + const TInt lineMove = iDsa.IsTurn() ? 1 : lineWidth; + const TInt copyLen = aUpdateRect.Width(); + + + if(iDsa.IsFlip()) + { + + targetPtr += scanLineWidth * (height - 1); + + for(TInt i = 0; i < height; i++) //source is always smaller + { + iDsa.Copy(reinterpret_cast<TUint32*>(targetPtr), reinterpret_cast<const TUint8*>(source), copyLen, height); + source += lineMove; + targetPtr -= scanLineWidth; + } + } + else + { + + + for(TInt i = 0; i < height; i++) //source is always smaller + { + iDsa.Copy(reinterpret_cast<TUint32*>(targetPtr), reinterpret_cast<const TUint8*>(source), copyLen, height); + source += lineMove; + targetPtr += scanLineWidth; // >> 2; + } + } + + } + + + +NONSHARABLE_CLASS(CDsaA) : public CDsa + { + public: + CDsaA(RWsSession& aSession); + private: + ~CDsaA(); + TUint8* LockSurface(); + void UnlockHWSurfaceRequestComplete(); + void UnlockHwSurface(); + void CreateSurfaceL(); + void Wipe(TInt aLength); + void Free(); + void Update(CFbsBitmap& aBmp); + void ConstructL(RWindow& aWindow, CWsScreenDevice& aDevice); + TInt ExternalUpdate(); + // void ExternalUpdate(); + protected: + CFbsBitmap* iBmp; + CFbsBitmap* iCopyBmp; + }; + + +CDsaA::CDsaA(RWsSession& aSession) : CDsa(aSession) + { + } + + +void CDsaA::Free() + { + delete iBmp; + iBmp = NULL; + } + +CDsaA::~CDsaA() + { + __ASSERT_DEBUG(iBmp == NULL, PANIC(KErrNotReady)); + delete iCopyBmp; + } + +TUint8* CDsaA::LockSurface() + { + iBmp->LockHeap(); + return reinterpret_cast<TUint8*>(iBmp->DataAddress()); + } + +void CDsaA::UnlockHWSurfaceRequestComplete() + { + PANIC(KErrNotSupported); + } + +void CDsaA::UnlockHwSurface() + { + iBmp->UnlockHeap(); + SetUpdating(EFalse); + Update(*iBmp); + } + +void CDsaA::Update(CFbsBitmap& aBmp) + { + if(!Blitter(aBmp)) + { + if(SwSize() == HwRect().Size()) + Dsa().Gc()->BitBlt(HwRect().iTl, &aBmp); + else + Dsa().Gc()->DrawBitmap(HwRect(), &aBmp); + } + DrawOverlays(); + Dsa().ScreenDevice()->Update(); + } +void CDsaA::CreateSurfaceL() + { + delete iBmp; + iBmp = NULL; + iBmp = new (ELeave) CFbsBitmap(); + User::LeaveIfError(iBmp->Create(SwSize(), DisplayMode())); + } + +void CDsaA::Wipe(TInt aLength) //dont call in drawing + { + iBmp->LockHeap(); + Mem::FillZ(iBmp->DataAddress(), aLength); + iBmp->UnlockHeap(); + } + + + +TInt CDsaA::ExternalUpdate() + { + if(iCopyBmp->Handle() == 0) + { + const TInt err = iCopyBmp->Duplicate(iBmp->Handle()); + if(err != KErrNone) + return err; + } + Update(*iCopyBmp); + return KErrNone; + } + +void CDsaA::ConstructL(RWindow& aWindow, CWsScreenDevice& aDevice) + { + iCopyBmp = new (ELeave) CFbsBitmap(); + CDsa::ConstructL(aWindow, aDevice); + } + + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +NONSHARABLE_CLASS(MDsbObs) + { + public: + virtual void SurfaceReady() = 0; + virtual CDirectScreenBitmap& Dsb() = 0; + }; + +NONSHARABLE_CLASS(CDsbSurface) : public CActive + { + public: + CDsbSurface(MDsbObs& aDsb); + TUint8* Address(); + void Complete(); + ~CDsbSurface(); + private: + void RunL(); + void DoCancel(); + private: + MDsbObs& iDsb; + TUint8* iAddress; + }; + +CDsbSurface::CDsbSurface(MDsbObs& aDsb) : CActive(CActive::EPriorityHigh) , iDsb(aDsb) + { + CActiveScheduler::Add(this); + } + +CDsbSurface::~CDsbSurface() + { + Cancel(); + } + +void CDsbSurface::Complete() + { + if(iAddress != NULL && !IsActive()) + { + iAddress = NULL; + SetActive(); + iDsb.Dsb().EndUpdate(iStatus); + } + } + +TUint8* CDsbSurface::Address() + { + if(iAddress == NULL && !IsActive()) + { + TAcceleratedBitmapInfo info; + if(KErrNone == iDsb.Dsb().BeginUpdate(info)) + iAddress = info.iAddress; + } + return iAddress; + } + +void CDsbSurface::RunL() + { + iDsb.SurfaceReady(); + } + +void CDsbSurface::DoCancel() + { + //empty + } + +NONSHARABLE_CLASS(CDsaB) : public CDsa, public MDsbObs + { + public: + CDsaB(RWsSession& aSession, TInt aFlags); + private: + ~CDsaB(); + TUint8* LockSurface(); + void UnlockHWSurfaceRequestComplete(); + void UnlockHwSurface(); + void CreateSurfaceL(); + void Wipe(TInt aLength); + void RecreateL(); + void ConstructL(RWindow& aWindow, CWsScreenDevice& aDevice); + CDirectScreenBitmap& Dsb(); + void SurfaceReady(); + TInt ExternalUpdate(); + private: + CDsbSurface* iSurface1; + CDsbSurface* iSurface2; + CDirectScreenBitmap* iDsb; + TInt iType; + }; + +CDsaB::CDsaB(RWsSession& aSession, TInt aFlags) : CDsa(aSession), iType(aFlags) + { + } + + + +void CDsaB::UnlockHWSurfaceRequestComplete() + { + iSurface1->Complete(); + if(iSurface2 != NULL) + iSurface2->Complete(); + } + +void CDsaB::CreateSurfaceL() + { + __ASSERT_ALWAYS(SwSize() == HwRect().Size(), PANIC(KErrNotSupported)); + } + +void CDsaB::Wipe(TInt aLength) //dont call in drawing + { + TUint8* addr = LockSurface(); + if(addr != NULL) + { + Mem::FillZ(addr, aLength); + UnlockHwSurface(); + } + } + + +void CDsaB::UnlockHwSurface() + { + EpocSdlEnv::Request(CDsa::ERequestUpdate); + } + +TUint8* CDsaB::LockSurface() + { + TUint8* addr = iSurface1->Address(); + if(addr == NULL && iSurface2 != NULL) + addr = iSurface2->Address(); + SetUpdating(addr == NULL); + return addr; + } + +void CDsaB::SurfaceReady() + { + SetUpdating(EFalse); + } + +CDirectScreenBitmap& CDsaB::Dsb() + { + return *iDsb; + } + +void CDsaB::ConstructL(RWindow& aWindow, CWsScreenDevice& aDevice) + { + if(iDsb == NULL) + iDsb = CDirectScreenBitmap::NewL(); + CDsa::ConstructL(aWindow, aDevice); + if(iSurface1 == NULL) + iSurface1 = new (ELeave) CDsbSurface(*this); + if(iSurface2 == NULL && iType & CDirectScreenBitmap::EDoubleBuffer) + iSurface2 = new (ELeave) CDsbSurface(*this); + } + +CDsaB::~CDsaB() + { + delete iSurface1; + delete iSurface2; + delete iDsb; + } + +void CDsaB::RecreateL() + { + iDsb->Close(); + iDsb->Create(HwRect(), CDirectScreenBitmap::TSettingsFlags(iType)); + } + +TInt CDsaB::ExternalUpdate() + { + if(LockSurface()) + { + UnlockHWSurfaceRequestComplete(); + return KErrNone; + } + return KErrNotReady; + } + + +///////////////////////////////////////////////////////////////////////////////////////////////////// + + +CDsa* CDsa::CreateL(RWsSession& aSession) + { + if(EpocSdlEnv::Flags(CSDL::EDrawModeDSB)) + { + TInt flags = CDirectScreenBitmap::ENone; + if(EpocSdlEnv::Flags(CSDL::EDrawModeDSBDoubleBuffer)) + flags |= CDirectScreenBitmap::EDoubleBuffer; + if(EpocSdlEnv::Flags(CSDL::EDrawModeDSBIncrentalUpdate)) + flags |= CDirectScreenBitmap::EIncrementalUpdate; + return new (ELeave) CDsaB(aSession, flags); + } + else + return new (ELeave) CDsaA(aSession); + } + + +void CDsa::RecreateL() + { + } + +void CDsa::Free() + { + } + +TSize CDsa::WindowSize() const + { + TSize size = iSwSize; + if(iStateFlags & EOrientation90) + { + const TInt tmp = size.iWidth; + size.iWidth = size.iHeight; + size.iHeight = tmp; + } + return size; + } + +void CDsa::SetSuspend() + { + iStateFlags |= ESdlThreadSuspend; + } + +void CDsa::ReleaseStop() + { + iStateFlags &= ~ESdlThreadExplicitStop; + } + + +TBool CDsa::Stopped() const + { + return (iStateFlags & ESdlThreadExplicitStop); + } + +void CDsa::SetOrientation(CSDL::TOrientationMode aOrientation) + { + TInt flags = 0; + switch(aOrientation) + { + case CSDL::EOrientation90: + flags = EOrientation90; + break; + case CSDL::EOrientation180: + flags = EOrientation180; + break; + case CSDL::EOrientation270: + flags = EOrientation90 | EOrientation180; + break; + case CSDL::EOrientation0: + flags = 0; + break; + } + if(flags != (iStateFlags & EOrientationFlags)) + { + iStateFlags |= EOrientationChanged; + iNewFlags = flags; //cannot be set during drawing... + } + } + +CDsa::~CDsa() + { + if(iDsa != NULL) + { + iDsa->Cancel(); + } + iOverlays.Close(); + delete iDsa; + User::Free(iLut256); + } + +void CDsa::ConstructL(RWindow& aWindow, CWsScreenDevice& aDevice) + { + if(iDsa != NULL) + { + iDsa->Cancel(); + delete iDsa; + iDsa = NULL; + } + + iDsa = CDirectScreenAccess::NewL( + iSession, + aDevice, + aWindow, + *this); + + if(iLut256 == NULL) + iLut256 = (TUint32*) User::AllocL(256 * sizeof(TUint32)); + iTargetMode = aWindow.DisplayMode(); + iTargetBpp = BytesPerPixel(DisplayMode()); + iScreenRect = TRect(aWindow.Position(), aWindow.Size()); + SetTargetRect(); + RestartL(); + } + +void CDsa::DrawOverlays() + { + const TInt last = iOverlays.Count() - 1; + for(TInt i = last; i >= 0 ; i--) + iOverlays[i].iOverlay->Draw(*iDsa->Gc(), HwRect(), SwSize()); + } + +TInt CDsa::AppendOverlay(MOverlay& aOverlay, TInt aPriority) + { + TInt i; + for(i = 0; i < iOverlays.Count() && iOverlays[i].iPriority < aPriority; i++) + {} + const TOverlay overlay = {&aOverlay, aPriority}; + return iOverlays.Insert(overlay, i); + } + +TInt CDsa::RemoveOverlay(MOverlay& aOverlay) + { + for(TInt i = 0; i < iOverlays.Count(); i++) + { + if(iOverlays[i].iOverlay == &aOverlay) + { + iOverlays.Remove(i); + return KErrNone; + } + } + return KErrNotFound; + } + +void CDsa::LockPalette(TBool aLock) + { + if(aLock) + iStateFlags |= EPaletteLocked; + else + iStateFlags &= ~EPaletteLocked; + } +TInt CDsa::SetPalette(TInt aFirst, TInt aCount, TUint32* aPalette) + { + if(iLut256 == NULL) + return KErrNotFound; + const TInt count = aCount - aFirst; + if(count > 256) + return KErrArgument; + if(iStateFlags & EPaletteLocked) + return KErrNone; + for(TInt i = aFirst; i < count; i++) //not so busy here:-) + { + iLut256[i] = aPalette[i]; + } + return KErrNone; + } + + + +void CDsa::RestartL() + { + //const TBool active = iDsa->IsActive(); + + //if(!active) + + iDsa->StartL(); + + const RRegion* r = iDsa->DrawingRegion(); + const TRect rect = r->BoundingRect(); + iDsa->Gc()->SetClippingRegion(r); + + if(rect != iScreenRect) + { + // iDsa->Cancel(); + return ; + } + + + + //iScreenRect = rect; //to ensure properly set, albeit may not(?) match to value SDL has - therefore may has to clip + //targetrect shall no change + SetTargetRect(); + RecreateL(); + + iStateFlags |= ERunning; + + ReleaseStop(); + if(iStateFlags & ESdlThreadSuspend) + { + EpocSdlEnv::Resume(); + iStateFlags &= ~ ESdlThreadSuspend; + } + EpocSdlEnv::ObserverEvent(MSDLObserver::EEventWindowReserved); + } + +CDsa::CDsa(RWsSession& aSession) : + iSession(aSession), + iStateFlags(0) + { +// CActiveScheduler::Add(this); + iCFTable[0] = CopyMem; + iCFTable[1] = CopyMemFlipReversed; + iCFTable[2] = CopyMemReversed; + iCFTable[3] = CopyMemFlip; + + iCFTable[4] = Copy256; + iCFTable[5] = Copy256FlipReversed; + iCFTable[6] = Copy256Reversed; + iCFTable[7] = Copy256Flip; + + + iCFTable[8] = CopySlow; + iCFTable[9] = CopySlowFlipReversed; + iCFTable[10] = CopySlowReversed; + iCFTable[11] = CopySlowFlip; + } + +RWsSession& CDsa::Session() + { + return iSession; + } + +TInt CDsa::RedrawRequest() + { + if(!(iStateFlags & (EUpdating) && (iStateFlags & ERunning))) + { + return ExternalUpdate(); + } + return KErrNotReady; + } + +TUint8* CDsa::LockHwSurface() + { + if((iStateFlags & EUpdating) == 0) //else frame is skipped + { + return LockSurface(); + } + return NULL; + } + +/* +void CDsa::RunL() + { + iStateFlags &= ~EUpdating; + } + + +void CDsa::DoCancel() + { + iStateFlags &= ~EUpdating; + //nothing can do, just wait? + } +*/ + + +TInt CDsa::AllocSurface(TBool aHwSurface, const TSize& aSize, TDisplayMode aMode) + { + if(aHwSurface && aMode != DisplayMode()) + return KErrArgument; + + iSourceMode = aMode; + + iSourceBpp = BytesPerPixel(aMode); + + const TSize size = WindowSize(); + if(aSize.iWidth > size.iWidth) + return KErrTooBig; + if(aSize.iHeight > size.iHeight) + return KErrTooBig; + + TRAPD(err, CreateSurfaceL()); + if(err != KErrNone) + return err; + + SetCopyFunction(); + + return KErrNone; + } + + +void CDsa::CreateZoomerL(const TSize& aSize) + { + iSwSize = aSize; + iStateFlags |= EResizeRequest; + CreateSurfaceL(); + SetTargetRect(); + } + + +/* +void SaveBmp(const TDesC& aName, const TAny* aData, TInt aLength, const TSize& aSz, TDisplayMode aMode) + { + CFbsBitmap* s = new CFbsBitmap(); + s->Create(aSz, aMode); + s->LockHeap(); + TUint32* addr = s->DataAddress(); + Mem::Copy(addr, aData, aLength); + s->UnlockHeap(); + s->Save(aName); + s->Reset(); + delete s; + } + +void SaveBmp(const TDesC& aName, const TUint32* aData, const TSize& aSz) + { + CFbsBitmap* s = new CFbsBitmap(); + s->Create(aSz, EColor64K); + TBitmapUtil bmp(s); + bmp.Begin(TPoint(0, 0)); + for(TInt j = 0; j < aSz.iHeight; j++) + { + bmp.SetPos(TPoint(0, j)); + for(TInt i = 0; i < aSz.iWidth; i++) + { + bmp.SetPixel(*aData); + aData++; + bmp.IncXPos(); + } + } + bmp.End(); + s->Save(aName); + s->Reset(); + delete s; + } + +TBuf<16> FooName(TInt aFoo) + { + TBuf<16> b; + b.Format(_L("C:\\pic%d.mbm"), aFoo); + return b; + } + +void ClipCopy(TUint8* aTarget, const TUint8* aSource, const TRect& aRect, const TPoint& aTargetPos) + { + const TInt iSourceBpp = 1; + const TInt iTargetBpp = 4; + const TInt iScanLineWidth = 800; + + TUint8* target = aTarget; + const TUint8* source = aSource; + const TInt lineWidth = aRect.Width(); + source += iSourceBpp * (aRect.iTl.iY * lineWidth); + const TInt sourceStartOffset = iSourceBpp * aRect.iTl.iX; + source += sourceStartOffset; + target += iTargetBpp * ((aTargetPos.iY + aRect.iTl.iY ) * lineWidth); + const TInt targetStartOffset = iTargetBpp * (aRect.iTl.iX + aTargetPos.iX); + target += targetStartOffset; + TUint32* targetPtr = reinterpret_cast<TUint32*>(target); + const TInt targetWidth = iScanLineWidth >> 2; + const TInt height = aRect.Height(); + } +*/ +/* +void CDsa::ClipCopy(TUint8* aTarget, + const TUint8* aSource, + const TRect& aUpdateRect, + const TRect& aSourceRect) const + { + //TUint8* target = aTarget; + const TUint32* source = (const TUint32*) aSource; + const TInt lineWidth = aSourceRect.Width(); + + source += (aUpdateRect.iTl.iY * lineWidth); + const TInt sourceStartOffset = aUpdateRect.iTl.iX; + source += sourceStartOffset; + + TUint32* targetPtr = reinterpret_cast<TUint32*>(aTarget); + + targetPtr += (aSourceRect.iTl.iY + aUpdateRect.iTl.iY ) * SwSize().iWidth; + const TInt targetStartOffset = (aUpdateRect.iTl.iX + aSourceRect.iTl.iX); + + targetPtr += targetStartOffset; + +// TUint32* targetPtr = reinterpret_cast<TUint32*>(target); + + const TInt targetWidth32 = SwSize().iWidth; + + const TInt height = aUpdateRect.Height(); + + const TInt lineMove = iStateFlags & EOrientation90 ? 1 : lineWidth; + const TInt copyLen = aUpdateRect.Width(); + + + if(iStateFlags & EOrientation180) + { + + targetPtr += targetWidth32 * (height - 1); + + for(TInt i = 0; i < height; i++) //source is always smaller + { + iCopyFunction(*this, targetPtr, (TUint8*)source, copyLen, height); + source += lineMove; + targetPtr -= targetWidth32; + } + } + else + { + + + for(TInt i = 0; i < height; i++) //source is always smaller + { + iCopyFunction(*this, targetPtr, (TUint8*)source, copyLen, height); + source += lineMove; + targetPtr += targetWidth32; // >> 2; + } + } + + } + +*/ + +void CDsa::ClipCopy(TUint8* aTarget, const TUint8* aSource, const TRect& aRect, const TPoint& aTargetPos) const + { + TUint8* target = aTarget; + const TUint8* source = aSource; + const TInt lineWidth = aRect.Width(); + source += iSourceBpp * (aRect.iTl.iY * lineWidth); + TInt sourceStartOffset = iSourceBpp * aRect.iTl.iX; + source += sourceStartOffset; + target += iTargetBpp * ((aTargetPos.iY + aRect.iTl.iY ) * lineWidth); + TInt targetStartOffset = iTargetBpp * (aRect.iTl.iX + aTargetPos.iX); + target += targetStartOffset; + TUint32* targetPtr = reinterpret_cast<TUint32*>(target); + const TInt targetWidth = iScanLineWidth >> 2; + const TInt height = aRect.Height(); + + TInt lineMove = iStateFlags & EOrientation90 ? 1 : lineWidth; + + if(iStateFlags & EOrientation180) + { + + targetPtr += targetWidth * (height - 1); + + for(TInt i = 0; i < height; i++) //source is always smaller + { + iCopyFunction(*this, targetPtr, source, lineWidth, height); + source += lineMove; + targetPtr -= targetWidth; + } + } + else + { + + + for(TInt i = 0; i < height; i++) //source is always smaller + { + iCopyFunction(*this, targetPtr, source, lineWidth, height); + source += lineMove; + targetPtr += targetWidth; + } + } + + } + + + + /* +void CDsa::ClipCopy(TUint8* aTarget, + const TUint8* aSource, + const TRect& aUpdateRect, + const TRect& aSourceRect) const + { + const TDsa dsa(*this); + switch(iSourceBpp) + { + case 1: + ::ClipCopy<TUint32, TUint8>(dsa, aTarget, aSource, aUpdateRect, aSourceRect); + break; + case 2: + ::ClipCopy<TUint32, TUint16>(dsa, aTarget, aSource, aUpdateRect, aSourceRect); + break; + case 4: + ::ClipCopy<TUint32, TUint32>(dsa, aTarget, aSource, aUpdateRect, aSourceRect); + break; + } + } + + +*/ + + + +void CDsa::Wipe() //dont call in drawing + { + if(IsDsaAvailable()) + Wipe(iTargetBpp * SwSize().iWidth * SwSize().iHeight); + } + +void CDsa::SetCopyFunction() + { + //calculate offset to correct function in iCFTable according to given parameters + TInt function = 0; + const TInt KCopyFunctions = 4; + const TInt KOffsetToNative = 0; + const TInt KOffsetTo256 = KOffsetToNative + KCopyFunctions; + const TInt KOffsetToOtherModes = KOffsetTo256 + KCopyFunctions; + const TInt KOffsetTo90Functions = 1; + const TInt KOffsetTo180Functions = 2; + + if(iSourceMode == DisplayMode()) + function = KOffsetToNative; //0 + else if(iSourceMode == EColor256) + function = KOffsetTo256; //4 + else + function = KOffsetToOtherModes; //8 + + if(iStateFlags & EOrientation90) + function += KOffsetTo90Functions; // + 1 + if(iStateFlags & EOrientation180) + function += KOffsetTo180Functions; //+ 2 + + iCopyFunction = iCFTable[function]; + + Wipe(); + } + +inline void Rotate(TRect& aRect) + { + const TInt dx = aRect.iBr.iX - aRect.iTl.iX; + const TInt dy = aRect.iBr.iY - aRect.iTl.iY; + + aRect.iBr.iX = aRect.iTl.iX + dy; + aRect.iBr.iY = aRect.iTl.iY + dx; + + const TInt tmp = aRect.iTl.iX; + aRect.iTl.iX = aRect.iTl.iY; + aRect.iTl.iY = tmp; + } + +/* +int bar = 0; +*/ +/* +TBool CDsa::AddUpdateRect(const TUint8* aBits, const TRect& aUpdateRect, const TRect& aRect) + { + + if(iStateFlags & EOrientationChanged) + { + iStateFlags &= ~EOrientationFlags; + iStateFlags |= iNewFlags; + SetCopyFunction(); + iStateFlags &= ~EOrientationChanged; + EpocSdlEnv::WaitDeviceChange(); + return EFalse; //skip this frame as data is may be changed + } + + if(iTargetAddr == NULL) + { + iTargetAddr = LockHwSurface(); + } + + TUint8* target = iTargetAddr; + if(target == NULL) + return EFalse; + + + TRect targetRect = TRect(TPoint(0, 0), SwSize()); + + TRect sourceRect = aRect; + TRect updateRect = aUpdateRect; + +// TPoint move(0, 0); + + + if(iStateFlags & EOrientation90) + { + Rotate(sourceRect); + Rotate(updateRect); + } + + if(iSourceMode != DisplayMode() || targetRect != sourceRect || targetRect != updateRect || ((iStateFlags & EOrientationFlags) != 0)) + { + sourceRect.Intersection(targetRect); //so source always smaller or equal than target + //updateRect.Intersection(targetRect); + ClipCopy(target, aBits, updateRect, sourceRect); + } + else + { + const TInt byteCount = aRect.Width() * aRect.Height() * iSourceBpp; //this could be stored + Mem::Copy(target, aBits, byteCount); + } + + return ETrue; + } + */ + +TBool CDsa::AddUpdateRect(const TUint8* aBits, const TRect& aUpdateRect, const TRect& aRect) + { + + if(iStateFlags & EOrientationChanged) + { + iStateFlags &= ~EOrientationFlags; + iStateFlags |= iNewFlags; + SetCopyFunction(); + iStateFlags &= ~EOrientationChanged; + EpocSdlEnv::WaitDeviceChange(); + return EFalse; //skip this frame as data is may be changed + } + + if(iTargetAddr == NULL) + { + iTargetAddr = LockHwSurface(); + } + TUint8* target = iTargetAddr; + if(target == NULL) + return EFalse; + + + TRect targetRect = Rect(); + TRect sourceRect = aRect; + TRect updateRect = aUpdateRect; + + if(iStateFlags & EOrientation90) + { + Rotate(sourceRect); + Rotate(updateRect); + } + + if(iSourceMode != DisplayMode() || targetRect != sourceRect || targetRect != updateRect || ((iStateFlags & EOrientationFlags) != 0)) + { + sourceRect.Intersection(targetRect); //so source always smaller or equal than target + updateRect.Intersection(targetRect); + ClipCopy(target, aBits, updateRect, sourceRect.iTl); + } + else + { + const TInt byteCount = aRect.Width() * aRect.Height() * iSourceBpp; //this could be stored + Mem::Copy(target, aBits, byteCount); + } + + return ETrue; + } +void CDsa::UpdateSwSurface() + { + iTargetAddr = NULL; + UnlockHwSurface(); //could be faster if does not use AO, but only check status before redraw, then no context switch needed + } + + +void CDsa::Resume() + { + if(Stopped()) + Restart(RDirectScreenAccess::ETerminateRegion); + } + +void CDsa::DoStop() + { + if(IsDsaAvailable()) + iStateFlags |= ESdlThreadExplicitStop; + Stop(); + } + +void CDsa::Stop() + { + iStateFlags &= ~ERunning; +// Cancel(); //can be called only from main! + iDsa->Cancel(); + } + +void CDsa::AbortNow(RDirectScreenAccess::TTerminationReasons /*aReason*/) + { +// iStateFlags |= EChangeNotify; + Stop(); + } + +void CDsa::Restart(RDirectScreenAccess::TTerminationReasons aReason) + { + if(aReason == RDirectScreenAccess::ETerminateRegion) //auto restart + { + TRAPD(err, RestartL()); + PANIC_IF_ERROR(err); + } + } + +void CDsa::SetBlitter(MBlitter* aBlitter) + { + iBlitter = aBlitter; + } + + +TPoint CDsa::WindowCoordinates(const TPoint& aPoint) const + { + TPoint pos = aPoint - iScreenRect.iTl; + const TSize asz = iScreenRect.Size(); + if(iStateFlags & EOrientation180) + { + pos.iX = asz.iWidth - pos.iX; + pos.iY = asz.iHeight - pos.iY; + } + if(iStateFlags & EOrientation90) + { + pos.iX = aPoint.iY; + pos.iY = aPoint.iX; + } + pos.iX <<= 16; + pos.iY <<= 16; + pos.iX /= asz.iWidth; + pos.iY /= asz.iHeight; + pos.iX *= iSwSize.iWidth; + pos.iY *= iSwSize.iHeight; + pos.iX >>= 16; + pos.iY >>= 16; + return pos; + } + +void CDsa::SetTargetRect() + { + iTargetRect = iScreenRect; + if(iStateFlags & EResizeRequest && EpocSdlEnv::Flags(CSDL::EAllowImageResizeKeepRatio)) + { + const TSize asz = iScreenRect.Size(); + const TSize sz = iSwSize; + + TRect rect; + + const TInt dh = (sz.iHeight << 16) / sz.iWidth; + + if((asz.iWidth * dh ) >> 16 <= asz.iHeight) + { + rect.SetRect(TPoint(0, 0), TSize(asz.iWidth, (asz.iWidth * dh) >> 16)); + } + else + { + const TInt dw = (sz.iWidth << 16) / sz.iHeight; + rect.SetRect(TPoint(0, 0), TSize((asz.iHeight * dw) >> 16, asz.iHeight)); + } + rect.Move((asz.iWidth - rect.Size().iWidth) >> 1, (asz.iHeight - rect.Size().iHeight) >> 1); + + iTargetRect = rect; + iTargetRect.Move(iScreenRect.iTl); + + } + if(!(iStateFlags & EResizeRequest)) + iSwSize = iScreenRect.Size(); +// iScanLineWidth = /*iTargetBpp **/ SwSize().iWidth; + } + +/*) +TBool CDsa::ChangeTrigger() + { + const TBool change = iStateFlags & EChangeNotify; + iStateFlags &= ~EChangeNotify; + return change; + } +*/ +///////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +void CDsa::Copy256(const CDsa& aDsa, TUint32* aTarget, const TUint8* aSource, TInt aBytes, TInt) + { + TUint32* target = aTarget; + const TUint32* endt = target + aBytes; + const TUint8* source = aSource; + while(target < endt) + { + *target++ = aDsa.iLut256[*source++]; + } + } + +void CDsa::Copy256Reversed(const CDsa& aDsa, TUint32* aTarget, const TUint8* aSource, TInt aBytes, TInt) + { + const TUint32* target = aTarget; + TUint32* endt = aTarget + aBytes; + const TUint8* source = aSource; + while(target < endt) + { + *(--endt) = aDsa.iLut256[*source++]; + } + } + +void CDsa::Copy256Flip(const CDsa& aDsa, TUint32* aTarget, const TUint8* aSource, TInt aBytes, TInt aLineLen) + { + TUint32* target = aTarget; + const TUint32* endt = target + aBytes; + const TUint8* column = aSource; + + while(target < endt) + { + *target++ = aDsa.iLut256[*column]; + column += aLineLen; + } + } + +void CDsa::Copy256FlipReversed(const CDsa& aDsa, TUint32* aTarget, const TUint8* aSource, TInt aBytes, TInt aLineLen) + { + const TUint32* target = aTarget; + TUint32* endt = aTarget + aBytes; + const TUint8* column = aSource; + + while(target < endt) + { + *(--endt) = aDsa.iLut256[*column]; + column += aLineLen; + } + } + +void CDsa::CopyMem(const CDsa& /*aDsa*/, TUint32* aTarget, const TUint8* aSource, TInt aBytes, TInt) + { + const TUint32* src = reinterpret_cast<const TUint32*>(aSource); + Mem::Copy(aTarget, src, aBytes << 2); + } + +void CDsa::CopyMemFlip(const CDsa& /*aDsa*/, TUint32* aTarget, const TUint8* aSource, TInt aBytes, TInt aLineLen) + { + TUint32* target = aTarget; + const TUint32* endt = target + aBytes; + const TUint32* column = reinterpret_cast<const TUint32*>(aSource); + + while(target < endt) + { + *target++ = *column; + column += aLineLen; + } + } + +void CDsa::CopyMemReversed(const CDsa& /*aDsa*/, TUint32* aTarget, const TUint8* aSource, TInt aBytes, TInt) + { + const TUint32* target = aTarget; + TUint32* endt = aTarget + aBytes; + const TUint32* source = reinterpret_cast<const TUint32*>(aSource); + while(target < endt) + { + *(--endt) = *source++; + } + } + + +void CDsa::CopyMemFlipReversed(const CDsa& /*aDsa*/, TUint32* aTarget, const TUint8* aSource, TInt aBytes, TInt aLineLen) + { + const TUint32* target = aTarget; + TUint32* endt = aTarget + aBytes; + const TUint32* column = reinterpret_cast<const TUint32*>(aSource); + + while(target < endt) + { + *(--endt) = *column; + column += aLineLen; + } + } + +/* + +LOCAL_C TRgb rgb16MA(TInt aValue) + { + return TRgb::Color16MA(aValue); + } +*/ +NONSHARABLE_CLASS(MRgbCopy) + { + public: + virtual void Copy(TUint32* aTarget, const TUint8* aSource, TInt aBytes, TBool aReversed) = 0; + virtual void FlipCopy(TUint32* aTarget, const TUint8* aSource, TInt aBytes, TInt aLineLen, TBool aReversed) = 0; + }; + +template <class T> +NONSHARABLE_CLASS(TRgbCopy) : public MRgbCopy + { + public: + TRgbCopy(TDisplayMode aMode); + void* operator new(TUint aBytes, TAny* aMem); + void Copy(TUint32* aTarget, const TUint8* aSource, TInt aBytes, TBool aReversed); + void FlipCopy(TUint32* aTarget, const TUint8* aSource, TInt aBytes, TInt aLineLen, TBool aReversed); + static TUint32 Gray256(const TUint8& aPixel); + static TUint32 Color256(const TUint8& aPixel); + static TUint32 Color4K(const TUint16& aPixel); + static TUint32 Color64K(const TUint16& aPixel); + static TUint32 Color16M(const TUint32& aPixel); + static TUint32 Color16MU(const TUint32& aPixel); + static TUint32 Color16MA(const TUint32& aPixel); + private: + typedef TUint32 (*TRgbFunc) (const T& aValue); + TRgbFunc iFunc; + }; + + +template <class T> +void* TRgbCopy<T>::operator new(TUint /*aBytes*/, TAny* aMem) + { + return aMem; + } + +template <class T> +TRgbCopy<T>::TRgbCopy(TDisplayMode aMode) + { + switch(aMode) + { + case EGray256 : iFunc = (TRgbFunc) Gray256; break; + case EColor256 : iFunc = (TRgbFunc) Color256; break; + case EColor4K : iFunc = (TRgbFunc) Color4K; break; + case EColor64K : iFunc = (TRgbFunc) Color64K; break; + case EColor16M : iFunc = (TRgbFunc) Color16M; break; + case EColor16MU : iFunc = (TRgbFunc) Color16MU; break; + case EColor16MA : iFunc = (TRgbFunc) Color16MA; break; + default: + PANIC(KErrNotSupported); + } + } + +template <class T> +void TRgbCopy<T>::Copy(TUint32* aTarget, const TUint8* aSource, TInt aBytes, TBool aReversed) + { + const T* source = reinterpret_cast<const T*>(aSource); + TUint32* target = aTarget; + TUint32* endt = target + aBytes; + + if(aReversed) + { + while(target < endt) + { + const T value = *source++; + *(--endt) = iFunc(value);//iFunc(value).Value(); + } + } + else + { + while(target < endt) + { + const T value = *source++; + *target++ = iFunc(value);//iFunc(value).Value(); + } + } + } + +template <class T> +void TRgbCopy<T>::FlipCopy(TUint32* aTarget, const TUint8* aSource, TInt aBytes, TInt aLineLen, TBool aReversed) + { + const T* column = reinterpret_cast<const T*>(aSource); + TUint32* target = aTarget; + TUint32* endt = target + aBytes; + + if(aReversed) + { + while(target < endt) + { + *(--endt) = iFunc(*column); + column += aLineLen; + } + } + else + { + while(target < endt) + { + *target++ = iFunc(*column); + column += aLineLen; + } + } + } + +template <class T> TUint32 TRgbCopy<T>::Gray256(const TUint8& aPixel) + { + const TUint32 px = aPixel << 16 | aPixel << 8 | aPixel; + return px; + } + +template <class T> TUint32 TRgbCopy<T>::Color256(const TUint8& aPixel) + { + return TRgb::Color256(aPixel).Value(); + } + +template <class T> TUint32 TRgbCopy<T>::Color4K(const TUint16& aPixel) + { + TUint32 col = (aPixel & 0xF00) << 12; + col |= (aPixel & 0xF00) << 8; + + col |= (aPixel & 0x0F0) << 8; + col |= (aPixel & 0x0F0); + + col |= (aPixel & 0x00F) << 4; + col |= (aPixel & 0x00F); + + return col; + } + +template <class T> TUint32 TRgbCopy<T>::Color64K(const TUint16& aPixel) + { + TUint32 col = (aPixel & 0xF800)<< 8; + col |= (aPixel & 0xE000) << 3; + + col |= (aPixel & 0x07E0) << 5; + col |= (aPixel & 0xC0) >> 1; + + col |= (aPixel & 0x07E0) << 3; + col |= (aPixel & 0x1C) >> 2; + + return col; + } + +template <class T> TUint32 TRgbCopy<T>::Color16M(const TUint32& aPixel) + { + return TRgb::Color16M(aPixel).Value(); + } + +template <class T> TUint32 TRgbCopy<T>::Color16MU(const TUint32& aPixel) + { + return TRgb::Color16MU(aPixel).Value(); + } + +template <class T> TUint32 TRgbCopy<T>::Color16MA(const TUint32& aPixel) + { + return TRgb::Color16MA(aPixel).Value(); + } + +typedef TUint64 TStackMem; + +LOCAL_C MRgbCopy* GetCopy(TAny* mem, TDisplayMode aMode) + { + if(aMode == EColor256 || aMode == EGray256) + { + return new (mem) TRgbCopy<TUint8>(aMode); + } + if(aMode == EColor4K || aMode == EColor64K) + { + return new (mem) TRgbCopy<TUint16>(aMode); + } + if(aMode == EColor16M || aMode == EColor16MU || aMode == EColor16MA) + { + return new (mem) TRgbCopy<TUint32>(aMode); + } + PANIC(KErrNotSupported); + return NULL; + } + + +void CDsa::CopySlowFlipReversed(const CDsa& aDsa, TUint32* aTarget, const TUint8* aSource, TInt aBytes, TInt aLineLen) + { + TStackMem mem = 0; + GetCopy(&mem, aDsa.iSourceMode)->FlipCopy(aTarget, aSource, aBytes, aLineLen, ETrue); + } + +void CDsa::CopySlowFlip(const CDsa& aDsa, TUint32* aTarget, const TUint8* aSource, TInt aBytes, TInt aLineLen) + { + TStackMem mem = 0; + GetCopy(&mem, aDsa.iSourceMode)->FlipCopy(aTarget, aSource, aBytes, aLineLen, EFalse); + } + +void CDsa::CopySlow(const CDsa& aDsa, TUint32* aTarget, const TUint8* aSource, TInt aBytes, TInt) + { + TStackMem mem = 0; + GetCopy(&mem, aDsa.iSourceMode)->Copy(aTarget, aSource, aBytes, EFalse); + } + +void CDsa::CopySlowReversed(const CDsa& aDsa, TUint32* aTarget, const TUint8* aSource, TInt aBytes, TInt) + { + TStackMem mem = 0; + GetCopy(&mem, aDsa.iSourceMode)->Copy(aTarget, aSource, aBytes, ETrue); + } + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////7 diff --git a/3rdparty/SDL/src/video/symbian/EKA2/dsa_old.cpp b/3rdparty/SDL/src/video/symbian/EKA2/dsa_old.cpp new file mode 100644 index 0000000..7e32de2 --- /dev/null +++ b/3rdparty/SDL/src/video/symbian/EKA2/dsa_old.cpp @@ -0,0 +1,1075 @@ +#include "dsa.h" +#include "sdlepocapi.h" +#include <cdsb.h> + +LOCAL_C TInt BytesPerPixel(TDisplayMode aMode) + { + return ((TDisplayModeUtils::NumDisplayModeBitsPerPixel(aMode) - 1) >> 3) + 1; + } + + +//////////////////////////////////////////////////////////////////////////////////////////////// + +NONSHARABLE_CLASS(CDsaA) : public CDsa + { + public: + CDsaA(RWsSession& aSession); + private: + ~CDsaA(); + TUint8* LockSurface(); + void UnlockHWSurfaceRequestComplete(); + void UnlockHwSurface(); + void CreateSurfaceL(); + void Wipe(TInt aLength); + void RecreateL(); + void Free(); + TInt ExternalUpdate() {return 0;} + private: + CFbsBitmap* iBmp; + }; + + +CDsaA::CDsaA(RWsSession& aSession) : CDsa(aSession) + { + } + +void CDsaA::Free() + { + delete iBmp; + iBmp = NULL; + } + +CDsaA::~CDsaA() + { + __ASSERT_DEBUG(iBmp == NULL, PANIC(KErrNotReady)); + } + +TUint8* CDsaA::LockSurface() + { + iBmp->LockHeap(); + return reinterpret_cast<TUint8*>(iBmp->DataAddress()); + } + +void CDsaA::UnlockHWSurfaceRequestComplete() + { + PANIC(KErrNotSupported); + } + +void CDsaA::UnlockHwSurface() + { + iBmp->UnlockHeap(); + SetUpdating(EFalse); + Dsa().Gc()->BitBlt(HwRect().iTl, iBmp); + Dsa().ScreenDevice()->Update(); + } + +void CDsaA::CreateSurfaceL() + { + delete iBmp; + iBmp = NULL; + iBmp = new (ELeave) CFbsBitmap(); + User::LeaveIfError(iBmp->Create(HwRect().Size(), DisplayMode())); + } + +void CDsaA::Wipe(TInt aLength) //dont call in drawing + { + iBmp->LockHeap(); + Mem::FillZ(iBmp->DataAddress(), aLength); + iBmp->UnlockHeap(); + } + +void CDsaA::RecreateL() + { + } + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +NONSHARABLE_CLASS(MDsbObs) + { + public: + virtual void SurfaceReady() = 0; + virtual CDirectScreenBitmap& Dsb() = 0; + }; + +NONSHARABLE_CLASS(CDsbSurface) : public CActive + { + public: + CDsbSurface(MDsbObs& aDsb); + TUint8* Address(); + void Complete(); + ~CDsbSurface(); + private: + void RunL(); + void DoCancel(); + private: + MDsbObs& iDsb; + TUint8* iAddress; + }; + +CDsbSurface::CDsbSurface(MDsbObs& aDsb) : CActive(CActive::EPriorityHigh) , iDsb(aDsb) + { + CActiveScheduler::Add(this); + } + +CDsbSurface::~CDsbSurface() + { + Cancel(); + } + +void CDsbSurface::Complete() + { + if(iAddress != NULL && !IsActive()) + { + iAddress = NULL; + SetActive(); + iDsb.Dsb().EndUpdate(iStatus); + } + } + +TUint8* CDsbSurface::Address() + { + if(iAddress == NULL && !IsActive()) + { + TAcceleratedBitmapInfo info; + if(KErrNone == iDsb.Dsb().BeginUpdate(info)) + iAddress = info.iAddress; + } + return iAddress; + } + +void CDsbSurface::RunL() + { + iDsb.SurfaceReady(); + } + +void CDsbSurface::DoCancel() + { + //empty + } + +NONSHARABLE_CLASS(CDsaB) : public CDsa, public MDsbObs + { + public: + CDsaB(RWsSession& aSession); + private: + ~CDsaB(); + TUint8* LockSurface(); + void UnlockHWSurfaceRequestComplete(); + void UnlockHwSurface(); + void CreateSurfaceL(); + void Wipe(TInt aLength); + void RecreateL(); + void ConstructL(RWindow& aWindow, CWsScreenDevice& aDevice); + void Free(); + CDirectScreenBitmap& Dsb(); + void SurfaceReady(); + TInt ExternalUpdate() {return 0;} + private: + CDsbSurface* iSurface1; + CDsbSurface* iSurface2; + CDirectScreenBitmap* iDsb; + }; + +CDsaB::CDsaB(RWsSession& aSession) : CDsa(aSession) + { + } + +void CDsaB::Free() + { + } + +void CDsaB::UnlockHWSurfaceRequestComplete() + { + iSurface1->Complete(); + iSurface2->Complete(); + } + +void CDsaB::CreateSurfaceL() + { + } + +void CDsaB::Wipe(TInt aLength) //dont call in drawing + { + TUint8* addr = LockSurface(); + if(addr != NULL) + { + Mem::FillZ(addr, aLength); + UnlockHwSurface(); + } + } + +void CDsaB::UnlockHwSurface() + { + EpocSdlEnv::Request(CDsa::ERequestUpdate); + } + +TUint8* CDsaB::LockSurface() + { + TUint8* addr = iSurface1->Address(); + if(addr == NULL) + addr = iSurface2->Address(); + SetUpdating(addr == NULL); + return addr; + } + +void CDsaB::SurfaceReady() + { + SetUpdating(EFalse); + } + +CDirectScreenBitmap& CDsaB::Dsb() + { + return *iDsb; + } + +void CDsaB::ConstructL(RWindow& aWindow, CWsScreenDevice& aDevice) + { + if(iDsb == NULL) + iDsb = CDirectScreenBitmap::NewL(); + CDsa::ConstructL(aWindow, aDevice); + iSurface1 = new (ELeave) CDsbSurface(*this); + iSurface2 = new (ELeave) CDsbSurface(*this); + } + +CDsaB::~CDsaB() + { + delete iSurface1; + delete iSurface2; + delete iDsb; + } + +void CDsaB::RecreateL() + { + iDsb->Close(); + iDsb->Create(HwRect(), CDirectScreenBitmap::EDoubleBuffer); + } + +///////////////////////////////////////////////////////////////////////////////////////////////////// + + +TSize CDsa::WindowSize() const + { + TSize size = HwRect().Size(); + if(iStateFlags & EOrientation90) + { + const TInt tmp = size.iWidth; + size.iWidth = size.iHeight; + size.iHeight = tmp; + } + return size; + } + +void CDsa::SetSuspend() + { + iStateFlags |= ESdlThreadSuspend; + } + +void CDsa::ReleaseStop() + { + iStateFlags &= ~ESdlThreadExplicitStop; + } + + +TBool CDsa::Stopped() const + { + return (iStateFlags & ESdlThreadExplicitStop); + } + +void CDsa::SetOrientation(CSDL::TOrientationMode aOrientation) + { + TInt flags = 0; + switch(aOrientation) + { + case CSDL::EOrientation90: + flags = EOrientation90; + break; + case CSDL::EOrientation180: + flags = EOrientation180; + break; + case CSDL::EOrientation270: + flags = EOrientation90 | EOrientation180; + break; + case CSDL::EOrientation0: + flags = 0; + break; + } + if(flags != (iStateFlags & EOrientationFlags)) + { + iStateFlags |= EOrientationChanged; + iNewFlags = flags; //cannot be set during drawing... + } + } + +CDsa::~CDsa() + { + if(iDsa != NULL) + { + iDsa->Cancel(); + } + delete iDsa; + User::Free(iLut256); + } + +void CDsa::ConstructL(RWindow& aWindow, CWsScreenDevice& aDevice) + { + if(iDsa != NULL) + { + iDsa->Cancel(); + delete iDsa; + iDsa = NULL; + } + + + iDsa = CDirectScreenAccess::NewL( + iSession, + aDevice, + aWindow, + *this); + + if(iLut256 == NULL) + iLut256 = (TUint32*) User::AllocL(256 * sizeof(TUint32)); + iTargetMode = aWindow.DisplayMode(); + iTargetBpp = BytesPerPixel(DisplayMode()); + iTargetRect = TRect(aWindow.Position(), aWindow.Size()); + RestartL(); + } + +void CDsa::LockPalette(TBool aLock) + { + if(aLock) + iStateFlags |= EPaletteLocked; + else + iStateFlags &= ~EPaletteLocked; + } +TInt CDsa::SetPalette(TInt aFirst, TInt aCount, TUint32* aPalette) + { + if(iLut256 == NULL) + return KErrNotFound; + const TInt count = aCount - aFirst; + if(count > 256) + return KErrArgument; + if(iStateFlags & EPaletteLocked) + return KErrNone; + for(TInt i = aFirst; i < count; i++) //not so busy here:-) + { + iLut256[i] = aPalette[i]; + } + return KErrNone; + } + + + + +void CDsa::RestartL() + { + //const TBool active = iDsa->IsActive(); + + //if(!active) + iDsa->StartL(); + + RRegion* r = iDsa->DrawingRegion(); + iDsa->Gc()->SetClippingRegion(r); + TRect rect = r->BoundingRect(); + + if(rect.IsEmpty()) + { + return; + } + + iScreenRect = rect; //to ensure properly set, albeit may not(?) match to value SDL has - therefore may has to clip + + RecreateL(); + + iStateFlags |= ERunning; +// iScanLineWidth = iTargetBpp * HwRect().Width(); + ReleaseStop(); + if(iStateFlags & ESdlThreadSuspend) + { + EpocSdlEnv::Resume(); + iStateFlags &= ~ ESdlThreadSuspend; + } + } + +CDsa::CDsa(RWsSession& aSession) : + iSession(aSession), + iStateFlags(0) + { +// CActiveScheduler::Add(this); + iCFTable[0] = CopyMem; + iCFTable[1] = CopyMemFlipReversed; + iCFTable[2] = CopyMemReversed; + iCFTable[3] = CopyMemFlip; + + iCFTable[4] = Copy256; + iCFTable[5] = Copy256FlipReversed; + iCFTable[6] = Copy256Reversed; + iCFTable[7] = Copy256Flip; + + + iCFTable[8] = CopySlow; + iCFTable[9] = CopySlowFlipReversed; + iCFTable[10] = CopySlowReversed; + iCFTable[11] = CopySlowFlip; + } + +RWsSession& CDsa::Session() + { + return iSession; + } + + + +TUint8* CDsa::LockHwSurface() + { + if((iStateFlags & EUpdating) == 0) //else frame is skipped + { + return LockSurface(); + } + return NULL; + } + +/* +void CDsa::RunL() + { + iStateFlags &= ~EUpdating; + } + + +void CDsa::DoCancel() + { + iStateFlags &= ~EUpdating; + //nothing can do, just wait? + } +*/ + +TInt CDsa::AllocSurface(TBool aHwSurface, const TSize& aSize, TDisplayMode aMode) + { + if(aHwSurface && aMode != DisplayMode()) + return KErrArgument; + + iSourceMode = aMode; + + iSourceBpp = BytesPerPixel(aMode); + + const TSize size = WindowSize(); + if(aSize.iWidth > size.iWidth) + return KErrTooBig; + if(aSize.iHeight > size.iHeight) + return KErrTooBig; + + TRAPD(err, CreateSurfaceL()); + if(err != KErrNone) + return err; + + + SetCopyFunction(); + + EpocSdlEnv::ObserverEvent(MSDLObserver::EEventWindowReserved); + + return KErrNone; + } + + +/* +void SaveBmp(const TDesC& aName, const TAny* aData, TInt aLength, const TSize& aSz, TDisplayMode aMode) + { + CFbsBitmap* s = new CFbsBitmap(); + s->Create(aSz, aMode); + s->LockHeap(); + TUint32* addr = s->DataAddress(); + Mem::Copy(addr, aData, aLength); + s->UnlockHeap(); + s->Save(aName); + s->Reset(); + delete s; + } + +void SaveBmp(const TDesC& aName, const TUint32* aData, const TSize& aSz) + { + CFbsBitmap* s = new CFbsBitmap(); + s->Create(aSz, EColor64K); + TBitmapUtil bmp(s); + bmp.Begin(TPoint(0, 0)); + for(TInt j = 0; j < aSz.iHeight; j++) + { + bmp.SetPos(TPoint(0, j)); + for(TInt i = 0; i < aSz.iWidth; i++) + { + bmp.SetPixel(*aData); + aData++; + bmp.IncXPos(); + } + } + bmp.End(); + s->Save(aName); + s->Reset(); + delete s; + } + +TBuf<16> FooName(TInt aFoo) + { + TBuf<16> b; + b.Format(_L("C:\\pic%d.mbm"), aFoo); + return b; + } +*/ +void CDsa::ClipCopy(TUint8* aTarget, const TUint8* aSource, const TRect& aRect, const TRect& aTargetPos) const + { + TUint8* target = aTarget; + const TUint8* source = aSource; + const TInt lineWidth = aRect.Width(); + source += iSourceBpp * (aRect.iTl.iY * lineWidth); + TInt sourceStartOffset = iSourceBpp * aRect.iTl.iX; + source += sourceStartOffset; + target += iTargetBpp * ((aTargetPos.iTl.iY + aRect.iTl.iY ) * lineWidth); + TInt targetStartOffset = iTargetBpp * (aRect.iTl.iX + aTargetPos.iTl.iX); + target += targetStartOffset; + TUint32* targetPtr = reinterpret_cast<TUint32*>(target); + const TInt targetWidth = HwRect().Size().iWidth; + const TInt height = aRect.Height(); + + TInt lineMove = iStateFlags & EOrientation90 ? 1 : lineWidth; + + if(iStateFlags & EOrientation180) + { + + targetPtr += targetWidth * (height - 1); + + for(TInt i = 0; i < height; i++) //source is always smaller + { + iCopyFunction(*this, targetPtr, source, lineWidth, height); + source += lineMove; + targetPtr -= targetWidth; + } + } + else + { + + + for(TInt i = 0; i < height; i++) //source is always smaller + { + iCopyFunction(*this, targetPtr, source, lineWidth, height); + source += lineMove; + targetPtr += targetWidth; + } + } + + } + + + + +void CDsa::Wipe() //dont call in drawing + { + if(IsDsaAvailable()) + Wipe(iTargetBpp * iScreenRect.Width() * iScreenRect.Height()); + } + +void CDsa::SetCopyFunction() + { + //calculate offset to correct function in iCFTable according to given parameters + TInt function = 0; + const TInt KCopyFunctions = 4; + const TInt KOffsetToNative = 0; + const TInt KOffsetTo256 = KOffsetToNative + KCopyFunctions; + const TInt KOffsetToOtherModes = KOffsetTo256 + KCopyFunctions; + const TInt KOffsetTo90Functions = 1; + const TInt KOffsetTo180Functions = 2; + + if(iSourceMode == DisplayMode()) + function = KOffsetToNative; //0 + else if(iSourceMode == EColor256) + function = KOffsetTo256; //4 + else + function = KOffsetToOtherModes; //8 + + if(iStateFlags & EOrientation90) + function += KOffsetTo90Functions; // + 1 + if(iStateFlags & EOrientation180) + function += KOffsetTo180Functions; //+ 2 + + iCopyFunction = iCFTable[function]; + + Wipe(); + } + +inline void Rotate(TRect& aRect) + { + const TInt dx = aRect.iBr.iX - aRect.iTl.iX; + const TInt dy = aRect.iBr.iY - aRect.iTl.iY; + + aRect.iBr.iX = aRect.iTl.iX + dy; + aRect.iBr.iY = aRect.iTl.iY + dx; + + const TInt tmp = aRect.iTl.iX; + aRect.iTl.iX = aRect.iTl.iY; + aRect.iTl.iY = tmp; + } + +/* +int bar = 0; +*/ +TBool CDsa::AddUpdateRect(const TUint8* aBits, const TRect& aUpdateRect, const TRect& aRect) + { + + if(iStateFlags & EOrientationChanged) + { + iStateFlags &= ~EOrientationFlags; + iStateFlags |= iNewFlags; + SetCopyFunction(); + iStateFlags &= ~EOrientationChanged; + EpocSdlEnv::WaitDeviceChange(); + return EFalse; //skip this frame as data is may be changed + } + + if(iTargetAddr == NULL) + { + iTargetAddr = LockHwSurface(); + } + TUint8* target = iTargetAddr; + if(target == NULL) + return EFalse; + + + TRect targetRect = HwRect(); + TRect sourceRect = aRect; + TRect updateRect = aUpdateRect; + + if(iStateFlags & EOrientation90) + { + Rotate(sourceRect); + Rotate(updateRect); + } + + if(iSourceMode != DisplayMode() || targetRect != sourceRect || targetRect != updateRect || ((iStateFlags & EOrientationFlags) != 0)) + { + sourceRect.Intersection(targetRect); //so source always smaller or equal than target + updateRect.Intersection(targetRect); + ClipCopy(target, aBits, updateRect, sourceRect); + } + else + { + const TInt byteCount = aRect.Width() * aRect.Height() * iSourceBpp; //this could be stored + Mem::Copy(target, aBits, byteCount); + } + + return ETrue; + } + +CDsa* CDsa::CreateL(RWsSession& aSession) + { + if(EpocSdlEnv::Flags(CSDL::EDrawModeDSB)) + { + TInt flags = CDirectScreenBitmap::ENone; + if(EpocSdlEnv::Flags(CSDL::EDrawModeDSBDoubleBuffer)) + flags |= CDirectScreenBitmap::EDoubleBuffer; + if(EpocSdlEnv::Flags(CSDL::EDrawModeDSBIncrentalUpdate)) + flags |= CDirectScreenBitmap::EIncrementalUpdate; + return new (ELeave) CDsaB(aSession); + } + else + return new (ELeave) CDsaA(aSession); + } + +void CDsa::CreateZoomerL(const TSize& aSize) + { + iSwSize = aSize; + iStateFlags |= EResizeRequest; + CreateSurfaceL(); + SetTargetRect(); + } + +TPoint CDsa::WindowCoordinates(const TPoint& aPoint) const + { + TPoint pos = aPoint - iScreenRect.iTl; + const TSize asz = iScreenRect.Size(); + if(iStateFlags & EOrientation180) + { + pos.iX = asz.iWidth - pos.iX; + pos.iY = asz.iHeight - pos.iY; + } + if(iStateFlags & EOrientation90) + { + pos.iX = aPoint.iY; + pos.iY = aPoint.iX; + } + pos.iX <<= 16; + pos.iY <<= 16; + pos.iX /= asz.iWidth; + pos.iY /= asz.iHeight; + pos.iX *= iSwSize.iWidth; + pos.iY *= iSwSize.iHeight; + pos.iX >>= 16; + pos.iY >>= 16; + return pos; + } + +void CDsa::SetTargetRect() + { + iTargetRect = iScreenRect; + if(iStateFlags & EResizeRequest && EpocSdlEnv::Flags(CSDL::EAllowImageResizeKeepRatio)) + { + const TSize asz = iScreenRect.Size(); + const TSize sz = iSwSize; + + TRect rect; + + const TInt dh = (sz.iHeight << 16) / sz.iWidth; + + if((asz.iWidth * dh ) >> 16 <= asz.iHeight) + { + rect.SetRect(TPoint(0, 0), TSize(asz.iWidth, (asz.iWidth * dh) >> 16)); + } + else + { + const TInt dw = (sz.iWidth << 16) / sz.iHeight; + rect.SetRect(TPoint(0, 0), TSize((asz.iHeight * dw) >> 16, asz.iHeight)); + } + rect.Move((asz.iWidth - rect.Size().iWidth) >> 1, (asz.iHeight - rect.Size().iHeight) >> 1); + + iTargetRect = rect; + iTargetRect.Move(iScreenRect.iTl); + + } + if(!(iStateFlags & EResizeRequest)) + iSwSize = iScreenRect.Size(); +// iScanLineWidth = /*iTargetBpp **/ SwSize().iWidth; + } + +void CDsa::RecreateL() + { + } + +void CDsa::Free() + { + } + +void CDsa::UpdateSwSurface() + { + iTargetAddr = NULL; + UnlockHwSurface(); //could be faster if does not use AO, but only check status before redraw, then no context switch needed + } + +void CDsa::SetBlitter(MBlitter* aBlitter) + { + iBlitter = aBlitter; + } + +void CDsa::DrawOverlays() + { + const TInt last = iOverlays.Count() - 1; + for(TInt i = last; i >= 0 ; i--) + iOverlays[i].iOverlay->Draw(*iDsa->Gc(), HwRect(), SwSize()); + } + +TInt CDsa::AppendOverlay(MOverlay& aOverlay, TInt aPriority) + { + TInt i; + for(i = 0; i < iOverlays.Count() && iOverlays[i].iPriority < aPriority; i++) + {} + const TOverlay overlay = {&aOverlay, aPriority}; + return iOverlays.Insert(overlay, i); + } + +TInt CDsa::RemoveOverlay(MOverlay& aOverlay) + { + for(TInt i = 0; i < iOverlays.Count(); i++) + { + if(iOverlays[i].iOverlay == &aOverlay) + { + iOverlays.Remove(i); + return KErrNone; + } + } + return KErrNotFound; + } + +TInt CDsa::RedrawRequest() + { + if(!(iStateFlags & (EUpdating) && (iStateFlags & ERunning))) + { + return ExternalUpdate(); + } + return KErrNotReady; + } + + +void CDsa::Resume() + { + if(Stopped()) + Restart(RDirectScreenAccess::ETerminateRegion); + } + +void CDsa::DoStop() + { + if(IsDsaAvailable()) + iStateFlags |= ESdlThreadExplicitStop; + Stop(); + } + +void CDsa::Stop() + { + iStateFlags &= ~ERunning; +// Cancel(); //can be called only from main! + iDsa->Cancel(); + } + +void CDsa::AbortNow(RDirectScreenAccess::TTerminationReasons /*aReason*/) + { +// iStateFlags |= EChangeNotify; + Stop(); + } + +void CDsa::Restart(RDirectScreenAccess::TTerminationReasons aReason) + { + if(aReason == RDirectScreenAccess::ETerminateRegion) //auto restart + { + TRAPD(err, RestartL()); + PANIC_IF_ERROR(err); + } + } +/*) +TBool CDsa::ChangeTrigger() + { + const TBool change = iStateFlags & EChangeNotify; + iStateFlags &= ~EChangeNotify; + return change; + } +*/ +///////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +void CDsa::Copy256(const CDsa& aDsa, TUint32* aTarget, const TUint8* aSource, TInt aBytes, TInt) + { + TUint32* target = aTarget; + const TUint32* endt = target + aBytes; + const TUint8* source = aSource; + while(target < endt) + { + *target++ = aDsa.iLut256[*source++]; + } + } + +void CDsa::Copy256Reversed(const CDsa& aDsa, TUint32* aTarget, const TUint8* aSource, TInt aBytes, TInt) + { + const TUint32* target = aTarget; + TUint32* endt = aTarget + aBytes; + const TUint8* source = aSource; + while(target < endt) + { + *(--endt) = aDsa.iLut256[*source++]; + } + } + +void CDsa::Copy256Flip(const CDsa& aDsa, TUint32* aTarget, const TUint8* aSource, TInt aBytes, TInt aLineLen) + { + TUint32* target = aTarget; + const TUint32* endt = target + aBytes; + const TUint8* column = aSource; + + while(target < endt) + { + *target++ = aDsa.iLut256[*column]; + column += aLineLen; + } + } + +void CDsa::Copy256FlipReversed(const CDsa& aDsa, TUint32* aTarget, const TUint8* aSource, TInt aBytes, TInt aLineLen) + { + const TUint32* target = aTarget; + TUint32* endt = aTarget + aBytes; + const TUint8* column = aSource; + + while(target < endt) + { + *(--endt) = aDsa.iLut256[*column]; + column += aLineLen; + } + } + +void CDsa::CopyMem(const CDsa& /*aDsa*/, TUint32* aTarget, const TUint8* aSource, TInt aBytes, TInt) + { + Mem::Copy(aTarget, aSource, aBytes); + } + +void CDsa::CopyMemFlip(const CDsa& /*aDsa*/, TUint32* aTarget, const TUint8* aSource, TInt aBytes, TInt aLineLen) + { + TUint32* target = aTarget; + const TUint32* endt = target + aBytes; + const TUint32* column = reinterpret_cast<const TUint32*>(aSource); + + while(target < endt) + { + *target++ = *column; + column += aLineLen; + } + } + +void CDsa::CopyMemReversed(const CDsa& /*aDsa*/, TUint32* aTarget, const TUint8* aSource, TInt aBytes, TInt) + { + const TUint32* target = aTarget; + TUint32* endt = aTarget + aBytes; + const TUint32* source = reinterpret_cast<const TUint32*>(aSource); + while(target < endt) + { + *(--endt) = *source++; + } + } + + +void CDsa::CopyMemFlipReversed(const CDsa& /*aDsa*/, TUint32* aTarget, const TUint8* aSource, TInt aBytes, TInt aLineLen) + { + const TUint32* target = aTarget; + TUint32* endt = aTarget + aBytes; + const TUint32* column = reinterpret_cast<const TUint32*>(aSource); + + while(target < endt) + { + *(--endt) = *column; + column += aLineLen; + } + } + + +typedef TRgb (*TRgbFunc) (TInt aValue); + +LOCAL_C TRgb rgb16MA(TInt aValue) + { + return TRgb::Color16MA(aValue); + } + +NONSHARABLE_CLASS(MRgbCopy) + { + public: + virtual void Copy(TUint32* aTarget, const TUint8* aSource, TInt aBytes, TBool aReversed) = 0; + virtual void FlipCopy(TUint32* aTarget, const TUint8* aSource, TInt aBytes, TInt aLineLen, TBool aReversed) = 0; + }; +template <class T> +NONSHARABLE_CLASS(TRgbCopy) : public MRgbCopy + { + public: + TRgbCopy(TDisplayMode aMode); + void* operator new(TUint aBytes, TAny* aMem); + void Copy(TUint32* aTarget, const TUint8* aSource, TInt aBytes, TBool aReversed); + void FlipCopy(TUint32* aTarget, const TUint8* aSource, TInt aBytes, TInt aLineLen, TBool aReversed); + private: + TRgbFunc iFunc; + }; + +template <class T> +void* TRgbCopy<T>::operator new(TUint /*aBytes*/, TAny* aMem) + { + return aMem; + } + +template <class T> +TRgbCopy<T>::TRgbCopy(TDisplayMode aMode) + { + switch(aMode) + { + case EGray256 : iFunc = TRgb::Gray256; break; + case EColor256 : iFunc = TRgb::Color256; break; + case EColor4K : iFunc = TRgb::Color4K; break; + case EColor64K : iFunc = TRgb::Color64K; break; + case EColor16M : iFunc = TRgb::Color16M; break; + case EColor16MU : iFunc = TRgb::Color16MU; break; + case EColor16MA : iFunc = rgb16MA; break; + default: + PANIC(KErrNotSupported); + } + } + +template <class T> +void TRgbCopy<T>::Copy(TUint32* aTarget, const TUint8* aSource, TInt aBytes, TBool aReversed) + { + const T* source = reinterpret_cast<const T*>(aSource); + TUint32* target = aTarget; + TUint32* endt = target + aBytes; + + if(aReversed) + { + while(target < endt) + { + TUint32 value = *source++; + *(--endt) = iFunc(value).Value(); + } + } + else + { + while(target < endt) + { + TUint32 value = *source++; + *target++ = iFunc(value).Value(); + } + } + } + +template <class T> +void TRgbCopy<T>::FlipCopy(TUint32* aTarget, const TUint8* aSource, TInt aBytes, TInt aLineLen, TBool aReversed) + { + const T* column = reinterpret_cast<const T*>(aSource); + TUint32* target = aTarget; + TUint32* endt = target + aBytes; + + if(aReversed) + { + while(target < endt) + { + *(--endt) = iFunc(*column).Value(); + column += aLineLen; + } + } + else + { + while(target < endt) + { + *target++ = iFunc(*column).Value(); + column += aLineLen; + } + } + } + + +typedef TUint64 TStackMem; + +LOCAL_C MRgbCopy* GetCopy(TAny* mem, TDisplayMode aMode) + { + if(aMode == EColor256 || aMode == EGray256) + { + return new (mem) TRgbCopy<TUint8>(aMode); + } + if(aMode == EColor4K || aMode == EColor64K) + { + return new (mem) TRgbCopy<TUint16>(aMode); + } + if(aMode == EColor16M || aMode == EColor16MU || aMode == EColor16MA) + { + return new (mem) TRgbCopy<TUint32>(aMode); + } + PANIC(KErrNotSupported); + return NULL; + } + + +void CDsa::CopySlowFlipReversed(const CDsa& aDsa, TUint32* aTarget, const TUint8* aSource, TInt aBytes, TInt aLineLen) + { + TStackMem mem = 0; + GetCopy(&mem, aDsa.iSourceMode)->FlipCopy(aTarget, aSource, aBytes, aLineLen, ETrue); + } + +void CDsa::CopySlowFlip(const CDsa& aDsa, TUint32* aTarget, const TUint8* aSource, TInt aBytes, TInt aLineLen) + { + TStackMem mem = 0; + GetCopy(&mem, aDsa.iSourceMode)->FlipCopy(aTarget, aSource, aBytes, aLineLen, EFalse); + } + +void CDsa::CopySlow(const CDsa& aDsa, TUint32* aTarget, const TUint8* aSource, TInt aBytes, TInt) + { + TStackMem mem = 0; + GetCopy(&mem, aDsa.iSourceMode)->Copy(aTarget, aSource, aBytes, EFalse); + } + +void CDsa::CopySlowReversed(const CDsa& aDsa, TUint32* aTarget, const TUint8* aSource, TInt aBytes, TInt) + { + TStackMem mem = 0; + GetCopy(&mem, aDsa.iSourceMode)->Copy(aTarget, aSource, aBytes, ETrue); + }
\ No newline at end of file diff --git a/3rdparty/SDL/src/video/symbian/SDL_epocevents_c.h b/3rdparty/SDL/src/video/symbian/SDL_epocevents_c.h new file mode 100644 index 0000000..8e10a04 --- /dev/null +++ b/3rdparty/SDL/src/video/symbian/SDL_epocevents_c.h @@ -0,0 +1,60 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Sam Lantinga + slouken@devolution.com +*/ + +/* + SDL_epocevents_c.h + Handle the event stream, converting Epoc events into SDL events + + Epoc version by Hannu Viitala (hannu.j.viitala@mbnet.fi) and Markus Mertama + +*/ + + +#ifdef SAVE_RCSID +static char rcsid = + "@(#) $Id: SDL_aaevents_c.h,v 1.1.2.2 2000/03/16 15:20:39 hercules Exp $"; +#endif + +extern "C" { +#include "SDL_sysvideo.h" +//#include "SDL_epocvideo.h" +} + + + +#define MAX_SCANCODE 255 + +/* Variables and functions exported by SDL_sysevents.c to other parts + of the native video subsystem (SDL_sysvideo.c) +*/ + +/* Hidden "this" pointer for the video functions */ +#define _THIS SDL_VideoDevice *_this +#define Private _this->hidden + +extern "C" { +extern void EPOC_InitOSKeymap(_THIS); +extern void EPOC_PumpEvents(_THIS); +} + +extern TBool isCursorVisible; + diff --git a/3rdparty/SDL/src/video/vgl/SDL_vglevents.c b/3rdparty/SDL/src/video/vgl/SDL_vglevents.c new file mode 100644 index 0000000..fa6c9e7 --- /dev/null +++ b/3rdparty/SDL/src/video/vgl/SDL_vglevents.c @@ -0,0 +1,299 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* Handle the event stream, converting X11 events into SDL events */ + +#include <stdio.h> + +#include <sys/fbio.h> +#include <sys/consio.h> +#include <sys/kbio.h> +#include <vgl.h> + +#include "SDL.h" +#include "SDL_thread.h" +#include "../../events/SDL_sysevents.h" +#include "../../events/SDL_events_c.h" +#include "SDL_vglvideo.h" +#include "SDL_vglevents_c.h" + +/* The translation tables from a console scancode to a SDL keysym */ +/* FIXME: Free the keymap when we shut down the video mode */ +static keymap_t *vga_keymap = NULL; +static SDLKey keymap[128]; +static SDL_keysym *TranslateKey(int scancode, SDL_keysym *keysym); + +static int posted = 0; +static int oldx = -1; +static int oldy = -1; +static struct mouse_info mouseinfo; + +/* Ugh, we have to duplicate the kernel's keysym mapping code... + Oh, it's not so bad. :-) + + FIXME: Add keyboard LED handling code + */ +int VGL_initkeymaps(int fd) +{ + vga_keymap = SDL_malloc(sizeof(keymap_t)); + if ( ! vga_keymap ) { + SDL_OutOfMemory(); + return(-1); + } + if (ioctl(fd, GIO_KEYMAP, vga_keymap) == -1) { + SDL_free(vga_keymap); + vga_keymap = NULL; + SDL_SetError("Unable to get keyboard map"); + return(-1); + } + return(0); +} + +static void handle_keyboard(_THIS) +{ + SDL_keysym keysym; + int c, pressed, scancode; + + while ((c = VGLKeyboardGetCh()) != 0) { + scancode = c & 0x7F; + if (c & 0x80) { + pressed = SDL_RELEASED; + } else { + pressed = SDL_PRESSED; + } + + posted += SDL_PrivateKeyboard(pressed, + TranslateKey(scancode, &keysym)); + } +} + +int VGL_initmouse(int fd) +{ + mouseinfo.operation = MOUSE_GETINFO; + if (ioctl(fd, CONS_MOUSECTL, &mouseinfo) != 0) + return -1; + + return 0; +} + +static void handle_mouse(_THIS) +{ + char buttons; + int x, y; + int button_state, state_changed, state; + int i; + + ioctl(0, CONS_MOUSECTL, &mouseinfo); + x = mouseinfo.u.data.x; + y = mouseinfo.u.data.y; + buttons = mouseinfo.u.data.buttons; + + if ((x != oldx) || (y != oldy)) { + posted += SDL_PrivateMouseMotion(0, 0, x, y); + oldx = x; + oldy = y; + } + + /* See what's changed */ + button_state = SDL_GetMouseState(NULL, NULL); + state_changed = button_state ^ buttons; + for (i = 0; i < 8; i++) { + if (state_changed & (1<<i)) { + if (buttons & (1<<i)) { + state = SDL_PRESSED; + } else { + state = SDL_RELEASED; + } + posted += SDL_PrivateMouseButton(state, i + 1, 0, 0); + } + } +} + + +void VGL_PumpEvents(_THIS) +{ + do { + posted = 0; + handle_keyboard(this); + handle_mouse(this); + } while (posted != 0); +} + +void VGL_InitOSKeymap(_THIS) +{ + int i; + + /* Initialize the BeOS key translation table */ + for ( i=0; i<SDL_arraysize(keymap); ++i ) + keymap[i] = SDLK_UNKNOWN; + + keymap[SCANCODE_ESCAPE] = SDLK_ESCAPE; + keymap[SCANCODE_1] = SDLK_1; + keymap[SCANCODE_2] = SDLK_2; + keymap[SCANCODE_3] = SDLK_3; + keymap[SCANCODE_4] = SDLK_4; + keymap[SCANCODE_5] = SDLK_5; + keymap[SCANCODE_6] = SDLK_6; + keymap[SCANCODE_7] = SDLK_7; + keymap[SCANCODE_8] = SDLK_8; + keymap[SCANCODE_9] = SDLK_9; + keymap[SCANCODE_0] = SDLK_0; + keymap[SCANCODE_MINUS] = SDLK_MINUS; + keymap[SCANCODE_EQUAL] = SDLK_EQUALS; + keymap[SCANCODE_BACKSPACE] = SDLK_BACKSPACE; + keymap[SCANCODE_TAB] = SDLK_TAB; + keymap[SCANCODE_Q] = SDLK_q; + keymap[SCANCODE_W] = SDLK_w; + keymap[SCANCODE_E] = SDLK_e; + keymap[SCANCODE_R] = SDLK_r; + keymap[SCANCODE_T] = SDLK_t; + keymap[SCANCODE_Y] = SDLK_y; + keymap[SCANCODE_U] = SDLK_u; + keymap[SCANCODE_I] = SDLK_i; + keymap[SCANCODE_O] = SDLK_o; + keymap[SCANCODE_P] = SDLK_p; + keymap[SCANCODE_BRACKET_LEFT] = SDLK_LEFTBRACKET; + keymap[SCANCODE_BRACKET_RIGHT] = SDLK_RIGHTBRACKET; + keymap[SCANCODE_ENTER] = SDLK_RETURN; + keymap[SCANCODE_LEFTCONTROL] = SDLK_LCTRL; + keymap[SCANCODE_A] = SDLK_a; + keymap[SCANCODE_S] = SDLK_s; + keymap[SCANCODE_D] = SDLK_d; + keymap[SCANCODE_F] = SDLK_f; + keymap[SCANCODE_G] = SDLK_g; + keymap[SCANCODE_H] = SDLK_h; + keymap[SCANCODE_J] = SDLK_j; + keymap[SCANCODE_K] = SDLK_k; + keymap[SCANCODE_L] = SDLK_l; + keymap[SCANCODE_SEMICOLON] = SDLK_SEMICOLON; + keymap[SCANCODE_APOSTROPHE] = SDLK_QUOTE; + keymap[SCANCODE_GRAVE] = SDLK_BACKQUOTE; + keymap[SCANCODE_LEFTSHIFT] = SDLK_LSHIFT; + keymap[SCANCODE_BACKSLASH] = SDLK_BACKSLASH; + keymap[SCANCODE_Z] = SDLK_z; + keymap[SCANCODE_X] = SDLK_x; + keymap[SCANCODE_C] = SDLK_c; + keymap[SCANCODE_V] = SDLK_v; + keymap[SCANCODE_B] = SDLK_b; + keymap[SCANCODE_N] = SDLK_n; + keymap[SCANCODE_M] = SDLK_m; + keymap[SCANCODE_COMMA] = SDLK_COMMA; + keymap[SCANCODE_PERIOD] = SDLK_PERIOD; + keymap[SCANCODE_SLASH] = SDLK_SLASH; + keymap[SCANCODE_RIGHTSHIFT] = SDLK_RSHIFT; + keymap[SCANCODE_KEYPADMULTIPLY] = SDLK_KP_MULTIPLY; + keymap[SCANCODE_LEFTALT] = SDLK_LALT; + keymap[SCANCODE_SPACE] = SDLK_SPACE; + keymap[SCANCODE_CAPSLOCK] = SDLK_CAPSLOCK; + keymap[SCANCODE_F1] = SDLK_F1; + keymap[SCANCODE_F2] = SDLK_F2; + keymap[SCANCODE_F3] = SDLK_F3; + keymap[SCANCODE_F4] = SDLK_F4; + keymap[SCANCODE_F5] = SDLK_F5; + keymap[SCANCODE_F6] = SDLK_F6; + keymap[SCANCODE_F7] = SDLK_F7; + keymap[SCANCODE_F8] = SDLK_F8; + keymap[SCANCODE_F9] = SDLK_F9; + keymap[SCANCODE_F10] = SDLK_F10; + keymap[SCANCODE_NUMLOCK] = SDLK_NUMLOCK; + keymap[SCANCODE_SCROLLLOCK] = SDLK_SCROLLOCK; + keymap[SCANCODE_KEYPAD7] = SDLK_KP7; + keymap[SCANCODE_CURSORUPLEFT] = SDLK_KP7; + keymap[SCANCODE_KEYPAD8] = SDLK_KP8; + keymap[SCANCODE_CURSORUP] = SDLK_KP8; + keymap[SCANCODE_KEYPAD9] = SDLK_KP9; + keymap[SCANCODE_CURSORUPRIGHT] = SDLK_KP9; + keymap[SCANCODE_KEYPADMINUS] = SDLK_KP_MINUS; + keymap[SCANCODE_KEYPAD4] = SDLK_KP4; + keymap[SCANCODE_CURSORLEFT] = SDLK_KP4; + keymap[SCANCODE_KEYPAD5] = SDLK_KP5; + keymap[SCANCODE_KEYPAD6] = SDLK_KP6; + keymap[SCANCODE_CURSORRIGHT] = SDLK_KP6; + keymap[SCANCODE_KEYPADPLUS] = SDLK_KP_PLUS; + keymap[SCANCODE_KEYPAD1] = SDLK_KP1; + keymap[SCANCODE_CURSORDOWNLEFT] = SDLK_KP1; + keymap[SCANCODE_KEYPAD2] = SDLK_KP2; + keymap[SCANCODE_CURSORDOWN] = SDLK_KP2; + keymap[SCANCODE_KEYPAD3] = SDLK_KP3; + keymap[SCANCODE_CURSORDOWNRIGHT] = SDLK_KP3; + keymap[SCANCODE_KEYPAD0] = SDLK_KP0; + keymap[SCANCODE_KEYPADPERIOD] = SDLK_KP_PERIOD; + keymap[SCANCODE_LESS] = SDLK_LESS; + keymap[SCANCODE_F11] = SDLK_F11; + keymap[SCANCODE_F12] = SDLK_F12; + keymap[SCANCODE_KEYPADENTER] = SDLK_KP_ENTER; + keymap[SCANCODE_RIGHTCONTROL] = SDLK_RCTRL; + keymap[SCANCODE_CONTROL] = SDLK_RCTRL; + keymap[SCANCODE_KEYPADDIVIDE] = SDLK_KP_DIVIDE; + keymap[SCANCODE_PRINTSCREEN] = SDLK_PRINT; + keymap[SCANCODE_RIGHTALT] = SDLK_RALT; + keymap[SCANCODE_BREAK] = SDLK_BREAK; + keymap[SCANCODE_BREAK_ALTERNATIVE] = SDLK_UNKNOWN; + keymap[SCANCODE_HOME] = SDLK_HOME; + keymap[SCANCODE_CURSORBLOCKUP] = SDLK_UP; + keymap[SCANCODE_PAGEUP] = SDLK_PAGEUP; + keymap[SCANCODE_CURSORBLOCKLEFT] = SDLK_LEFT; + keymap[SCANCODE_CURSORBLOCKRIGHT] = SDLK_RIGHT; + keymap[SCANCODE_END] = SDLK_END; + keymap[SCANCODE_CURSORBLOCKDOWN] = SDLK_DOWN; + keymap[SCANCODE_PAGEDOWN] = SDLK_PAGEDOWN; + keymap[SCANCODE_INSERT] = SDLK_INSERT; + keymap[SCANCODE_REMOVE] = SDLK_DELETE; + keymap[119] = SDLK_PAUSE; + keymap[SCANCODE_RIGHTWIN] = SDLK_RSUPER; + keymap[SCANCODE_LEFTWIN] = SDLK_LSUPER; + keymap[127] = SDLK_MENU; +} + +static SDL_keysym *TranslateKey(int scancode, SDL_keysym *keysym) +{ + /* Set the keysym information */ + keysym->scancode = scancode; + keysym->sym = keymap[scancode]; + keysym->mod = KMOD_NONE; + + /* If UNICODE is on, get the UNICODE value for the key */ + keysym->unicode = 0; + if ( SDL_TranslateUNICODE && vga_keymap ) { + int map; + SDLMod modstate; + + modstate = SDL_GetModState(); + map = 0; + if ( modstate & KMOD_SHIFT ) { + map += 1; + } + if ( modstate & KMOD_CTRL ) { + map += 2; + } + if ( modstate & KMOD_ALT ) { + map += 4; + } + if ( !(vga_keymap->key[scancode].spcl & (0x80 >> map)) ) { + keysym->unicode = vga_keymap->key[scancode].map[map]; + } + + } + return(keysym); +} + diff --git a/3rdparty/SDL/src/video/vgl/SDL_vglevents_c.h b/3rdparty/SDL/src/video/vgl/SDL_vglevents_c.h new file mode 100644 index 0000000..614cab5 --- /dev/null +++ b/3rdparty/SDL/src/video/vgl/SDL_vglevents_c.h @@ -0,0 +1,155 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#include "SDL_vglvideo.h" + +/* Variables and functions exported by SDL_sysevents.c to other parts + of the native video subsystem (SDL_sysvideo.c) +*/ +extern int VGL_initkeymaps(int fd); +extern int VGL_initmouse(int fd); +extern void VGL_keyboardcallback(int scancode, int pressed); + +extern void VGL_InitOSKeymap(_THIS); +extern void VGL_PumpEvents(_THIS); + +/* Mouse buttons */ +#define MOUSE_LEFTBUTTON 0x01 +#define MOUSE_MIDDLEBUTTON 0x02 +#define MOUSE_RIGHTBUTTON 0x04 + +/* Scancodes */ +#define SCANCODE_ESCAPE 1 +#define SCANCODE_1 2 +#define SCANCODE_2 3 +#define SCANCODE_3 4 +#define SCANCODE_4 5 +#define SCANCODE_5 6 +#define SCANCODE_6 7 +#define SCANCODE_7 8 +#define SCANCODE_8 9 +#define SCANCODE_9 10 +#define SCANCODE_0 11 +#define SCANCODE_MINUS 12 +#define SCANCODE_EQUAL 13 +#define SCANCODE_BACKSPACE 14 +#define SCANCODE_TAB 15 +#define SCANCODE_Q 16 +#define SCANCODE_W 17 +#define SCANCODE_E 18 +#define SCANCODE_R 19 +#define SCANCODE_T 20 +#define SCANCODE_Y 21 +#define SCANCODE_U 22 +#define SCANCODE_I 23 +#define SCANCODE_O 24 +#define SCANCODE_P 25 +#define SCANCODE_BRACKET_LEFT 26 +#define SCANCODE_BRACKET_RIGHT 27 +#define SCANCODE_ENTER 28 +#define SCANCODE_LEFTCONTROL 29 +#define SCANCODE_A 30 +#define SCANCODE_S 31 +#define SCANCODE_D 32 +#define SCANCODE_F 33 +#define SCANCODE_G 34 +#define SCANCODE_H 35 +#define SCANCODE_J 36 +#define SCANCODE_K 37 +#define SCANCODE_L 38 +#define SCANCODE_SEMICOLON 39 +#define SCANCODE_APOSTROPHE 40 +#define SCANCODE_GRAVE 41 +#define SCANCODE_LEFTSHIFT 42 +#define SCANCODE_BACKSLASH 43 +#define SCANCODE_Z 44 +#define SCANCODE_X 45 +#define SCANCODE_C 46 +#define SCANCODE_V 47 +#define SCANCODE_B 48 +#define SCANCODE_N 49 +#define SCANCODE_M 50 +#define SCANCODE_COMMA 51 +#define SCANCODE_PERIOD 52 +#define SCANCODE_SLASH 53 +#define SCANCODE_RIGHTSHIFT 54 +#define SCANCODE_KEYPADMULTIPLY 55 +#define SCANCODE_LEFTALT 56 +#define SCANCODE_SPACE 57 +#define SCANCODE_CAPSLOCK 58 +#define SCANCODE_F1 59 +#define SCANCODE_F2 60 +#define SCANCODE_F3 61 +#define SCANCODE_F4 62 +#define SCANCODE_F5 63 +#define SCANCODE_F6 64 +#define SCANCODE_F7 65 +#define SCANCODE_F8 66 +#define SCANCODE_F9 67 +#define SCANCODE_F10 68 +#define SCANCODE_NUMLOCK 69 +#define SCANCODE_SCROLLLOCK 70 +#define SCANCODE_KEYPAD7 71 +#define SCANCODE_CURSORUPLEFT 71 +#define SCANCODE_KEYPAD8 72 +#define SCANCODE_CURSORUP 72 +#define SCANCODE_KEYPAD9 73 +#define SCANCODE_CURSORUPRIGHT 73 +#define SCANCODE_KEYPADMINUS 74 +#define SCANCODE_KEYPAD4 75 +#define SCANCODE_CURSORLEFT 75 +#define SCANCODE_KEYPAD5 76 +#define SCANCODE_KEYPAD6 77 +#define SCANCODE_CURSORRIGHT 77 +#define SCANCODE_KEYPADPLUS 78 +#define SCANCODE_KEYPAD1 79 +#define SCANCODE_CURSORDOWNLEFT 79 +#define SCANCODE_KEYPAD2 80 +#define SCANCODE_CURSORDOWN 80 +#define SCANCODE_KEYPAD3 81 +#define SCANCODE_CURSORDOWNRIGHT 81 +#define SCANCODE_KEYPAD0 82 +#define SCANCODE_KEYPADPERIOD 83 +#define SCANCODE_LESS 86 +#define SCANCODE_F11 87 +#define SCANCODE_F12 88 +#define SCANCODE_KEYPADENTER 89 +#define SCANCODE_RIGHTCONTROL 90 +#define SCANCODE_CONTROL 107 +#define SCANCODE_KEYPADDIVIDE 91 +#define SCANCODE_PRINTSCREEN 92 +#define SCANCODE_RIGHTALT 93 +#define SCANCODE_BREAK 104 /* Beware: is 119 */ +#define SCANCODE_BREAK_ALTERNATIVE 104 /* on some keyboards! */ +#define SCANCODE_HOME 94 +#define SCANCODE_CURSORBLOCKUP 95 /* Cursor key block */ +#define SCANCODE_PAGEUP 96 +#define SCANCODE_CURSORBLOCKLEFT 97 /* Cursor key block */ +#define SCANCODE_CURSORBLOCKRIGHT 98 /* Cursor key block */ +#define SCANCODE_END 99 +#define SCANCODE_CURSORBLOCKDOWN 100 /* Cursor key block */ +#define SCANCODE_PAGEDOWN 101 +#define SCANCODE_INSERT 102 +#define SCANCODE_REMOVE 103 +#define SCANCODE_RIGHTWIN 106 +#define SCANCODE_LEFTWIN 105 diff --git a/3rdparty/SDL/src/video/vgl/SDL_vglmouse.c b/3rdparty/SDL/src/video/vgl/SDL_vglmouse.c new file mode 100644 index 0000000..466f1c5 --- /dev/null +++ b/3rdparty/SDL/src/video/vgl/SDL_vglmouse.c @@ -0,0 +1,56 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#include "SDL_mouse.h" +#include "../../events/SDL_events_c.h" +#include "SDL_vglvideo.h" +#include "SDL_vglmouse_c.h" + + +/* The implementation dependent data for the window manager cursor */ +struct WMcursor { + int unused; +}; + + +void VGL_FreeWMCursor(_THIS, WMcursor *cursor) +{ + return; +} + +WMcursor *VGL_CreateWMCursor(_THIS, + Uint8 *data, Uint8 *mask, int w, int h, int hot_x, int hot_y) +{ + return(NULL); +} + +int VGL_ShowWMCursor(_THIS, WMcursor *cursor) +{ + return(0); +} + +void VGL_WarpWMCursor(_THIS, Uint16 x, Uint16 y) +{ + SDL_PrivateMouseMotion(0, 0, x, y); +} + diff --git a/3rdparty/SDL/src/video/vgl/SDL_vglmouse_c.h b/3rdparty/SDL/src/video/vgl/SDL_vglmouse_c.h new file mode 100644 index 0000000..f579d65 --- /dev/null +++ b/3rdparty/SDL/src/video/vgl/SDL_vglmouse_c.h @@ -0,0 +1,32 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#include "SDL_vglvideo.h" + +/* Functions to be exported */ +extern void VGL_FreeWMCursor(_THIS, WMcursor *cursor); +extern WMcursor *VGL_CreateWMCursor(_THIS, + Uint8 *data, Uint8 *mask, int w, int h, int hot_x, int hot_y); +extern int VGL_ShowWMCursor(_THIS, WMcursor *cursor); +extern void VGL_WarpWMCursor(_THIS, Uint16 x, Uint16 y); + diff --git a/3rdparty/SDL/src/video/vgl/SDL_vglvideo.c b/3rdparty/SDL/src/video/vgl/SDL_vglvideo.c new file mode 100644 index 0000000..0b61615 --- /dev/null +++ b/3rdparty/SDL/src/video/vgl/SDL_vglvideo.c @@ -0,0 +1,624 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* libvga based SDL video driver implementation. +*/ + +#include <err.h> +#include <osreldate.h> +#include <unistd.h> +#include <sys/stat.h> + +#include <sys/fbio.h> +#include <sys/consio.h> +#include <sys/kbio.h> +#include <vgl.h> + +#include "SDL_video.h" +#include "SDL_mouse.h" +#include "../SDL_sysvideo.h" +#include "../SDL_pixels_c.h" +#include "../../events/SDL_events_c.h" +#include "SDL_vglvideo.h" +#include "SDL_vglevents_c.h" +#include "SDL_vglmouse_c.h" + + +/* Initialization/Query functions */ +static int VGL_VideoInit(_THIS, SDL_PixelFormat *vformat); +static SDL_Rect **VGL_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags); +static SDL_Surface *VGL_SetVideoMode(_THIS, SDL_Surface *current, int width, int height, int bpp, Uint32 flags); +static int VGL_SetColors(_THIS, int firstcolor, int ncolors, + SDL_Color *colors); +static void VGL_VideoQuit(_THIS); + +/* Hardware surface functions */ +static int VGL_AllocHWSurface(_THIS, SDL_Surface *surface); +static int VGL_LockHWSurface(_THIS, SDL_Surface *surface); +static int VGL_FlipHWSurface(_THIS, SDL_Surface *surface); +static void VGL_UnlockHWSurface(_THIS, SDL_Surface *surface); +static void VGL_FreeHWSurface(_THIS, SDL_Surface *surface); + +/* Misc function */ +static VGLMode ** VGLListModes(int depth, int mem_model); + +/* VGL driver bootstrap functions */ + +static int VGL_Available(void) +{ + /* + * Check to see if we are root and stdin is a + * virtual console. Also try to ensure that + * modes other than 320x200 are available + */ + int console, hires_available, i; + VGLMode **modes; + + console = STDIN_FILENO; + if ( console >= 0 ) { + struct stat sb; + struct vt_mode dummy; + + if ( (fstat(console, &sb) < 0) || + (ioctl(console, VT_GETMODE, &dummy) < 0) ) { + console = -1; + } + } + if (geteuid() != 0 && console == -1) + return 0; + + modes = VGLListModes(8, V_INFO_MM_DIRECT | V_INFO_MM_PACKED); + hires_available = 0; + for (i = 0; modes[i] != NULL; i++) { + if ((modes[i]->ModeInfo.Xsize > 320) && + (modes[i]->ModeInfo.Ysize > 200) && + ((modes[i]->ModeInfo.Type == VIDBUF8) || + (modes[i]->ModeInfo.Type == VIDBUF16) || + (modes[i]->ModeInfo.Type == VIDBUF32))) { + hires_available = 1; + break; + } + } + return hires_available; +} + +static void VGL_DeleteDevice(SDL_VideoDevice *device) +{ + SDL_free(device->hidden); + SDL_free(device); +} + +static SDL_VideoDevice *VGL_CreateDevice(int devindex) +{ + SDL_VideoDevice *device; + + /* Initialize all variables that we clean on shutdown */ + device = (SDL_VideoDevice *)SDL_malloc(sizeof(SDL_VideoDevice)); + if ( device ) { + SDL_memset(device, 0, (sizeof *device)); + device->hidden = (struct SDL_PrivateVideoData *) + SDL_malloc((sizeof *device->hidden)); + } + if ( (device == NULL) || (device->hidden == NULL) ) { + SDL_OutOfMemory(); + if ( device ) { + SDL_free(device); + } + return(0); + } + SDL_memset(device->hidden, 0, (sizeof *device->hidden)); + + /* Set the function pointers */ + device->VideoInit = VGL_VideoInit; + device->ListModes = VGL_ListModes; + device->SetVideoMode = VGL_SetVideoMode; + device->SetColors = VGL_SetColors; + device->UpdateRects = NULL; + device->VideoQuit = VGL_VideoQuit; + device->AllocHWSurface = VGL_AllocHWSurface; + device->CheckHWBlit = NULL; + device->FillHWRect = NULL; + device->SetHWColorKey = NULL; + device->SetHWAlpha = NULL; + device->LockHWSurface = VGL_LockHWSurface; + device->UnlockHWSurface = VGL_UnlockHWSurface; + device->FlipHWSurface = VGL_FlipHWSurface; + device->FreeHWSurface = VGL_FreeHWSurface; + device->SetIcon = NULL; + device->SetCaption = NULL; + device->GetWMInfo = NULL; + device->FreeWMCursor = VGL_FreeWMCursor; + device->CreateWMCursor = VGL_CreateWMCursor; + device->ShowWMCursor = VGL_ShowWMCursor; + device->WarpWMCursor = VGL_WarpWMCursor; + device->InitOSKeymap = VGL_InitOSKeymap; + device->PumpEvents = VGL_PumpEvents; + + device->free = VGL_DeleteDevice; + + return device; +} + +VideoBootStrap VGL_bootstrap = { + "vgl", "FreeBSD libVGL", + VGL_Available, VGL_CreateDevice +}; + +static int VGL_AddMode(_THIS, VGLMode *inmode) +{ + SDL_Rect *mode; + + int i, index; + int next_mode; + + /* Check to see if we already have this mode */ + if (inmode->Depth < 8) { /* Not supported */ + return 0; + } + index = ((inmode->Depth + 7) / 8) - 1; + for (i=0; i<SDL_nummodes[index]; ++i) { + mode = SDL_modelist[index][i]; + if ((mode->w == inmode->ModeInfo.Xsize) && + (mode->h == inmode->ModeInfo.Ysize)) + return 0; + } + + /* Set up the new video mode rectangle */ + mode = (SDL_Rect *)SDL_malloc(sizeof *mode); + if (mode == NULL) { + SDL_OutOfMemory(); + return -1; + } + mode->x = 0; + mode->y = 0; + mode->w = inmode->ModeInfo.Xsize; + mode->h = inmode->ModeInfo.Ysize; + + /* Allocate the new list of modes, and fill in the new mode */ + next_mode = SDL_nummodes[index]; + SDL_modelist[index] = (SDL_Rect **) + SDL_realloc(SDL_modelist[index], (1+next_mode+1)*sizeof(SDL_Rect *)); + if (SDL_modelist[index] == NULL) { + SDL_OutOfMemory(); + SDL_nummodes[index] = 0; + SDL_free(mode); + return -1; + } + SDL_modelist[index][next_mode] = mode; + SDL_modelist[index][next_mode+1] = NULL; + SDL_nummodes[index]++; + + return 0; +} + +static void VGL_UpdateVideoInfo(_THIS) +{ + this->info.wm_available = 0; + this->info.hw_available = 1; + this->info.video_mem = 0; + if (VGLCurMode == NULL) { + return; + } + if (VGLCurMode->ModeInfo.PixelBytes > 0) { + this->info.video_mem = VGLCurMode->ModeInfo.PixelBytes * + VGLCurMode->ModeInfo.Xsize * + VGLCurMode->ModeInfo.Ysize; + } +} + +int VGL_VideoInit(_THIS, SDL_PixelFormat *vformat) +{ + int i; + int total_modes; + VGLMode **modes; + + /* Initialize all variables that we clean on shutdown */ + for ( i=0; i<NUM_MODELISTS; ++i ) { + SDL_nummodes[i] = 0; + SDL_modelist[i] = NULL; + } + + /* Enable mouse and keyboard support */ + if (SDL_getenv("SDL_NO_RAWKBD") == NULL) { + if (VGLKeyboardInit(VGL_CODEKEYS) != 0) { + SDL_SetError("Unable to initialize keyboard"); + return -1; + } + } else { + warnx("Requiest to put keyboard into a raw mode ignored"); + } + if (VGL_initkeymaps(STDIN_FILENO) != 0) { + SDL_SetError("Unable to initialize keymap"); + return -1; + } + if (VGL_initmouse(STDIN_FILENO) != 0) { + SDL_SetError("Unable to initialize mouse"); + return -1; + } + + /* Determine the current screen size */ + if (VGLCurMode != NULL) { + this->info.current_w = VGLCurMode->ModeInfo.Xsize; + this->info.current_h = VGLCurMode->ModeInfo.Ysize; + } + + /* Determine the screen depth */ + if (VGLCurMode != NULL) + vformat->BitsPerPixel = VGLCurMode->Depth; + else + vformat->BitsPerPixel = 16; /* Good default */ + + /* Query for the list of available video modes */ + total_modes = 0; + modes = VGLListModes(-1, V_INFO_MM_DIRECT | V_INFO_MM_PACKED); + for (i = 0; modes[i] != NULL; i++) { + if ((modes[i]->ModeInfo.Type == VIDBUF8) || + (modes[i]->ModeInfo.Type == VIDBUF16) || + (modes[i]->ModeInfo.Type == VIDBUF32)) { + VGL_AddMode(this, modes[i]); + total_modes++; + } + } + if (total_modes == 0) { + SDL_SetError("No linear video modes available"); + return -1; + } + + /* Fill in our hardware acceleration capabilities */ + VGL_UpdateVideoInfo(this); + + /* Create the hardware surface lock mutex */ + hw_lock = SDL_CreateMutex(); + if (hw_lock == NULL) { + SDL_SetError("Unable to create lock mutex"); + VGL_VideoQuit(this); + return -1; + } + + /* We're done! */ + return 0; +} + +SDL_Rect **VGL_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags) +{ + return SDL_modelist[((format->BitsPerPixel+7)/8)-1]; +} + +/* Various screen update functions available */ +static void VGL_DirectUpdate(_THIS, int numrects, SDL_Rect *rects); + +SDL_Surface *VGL_SetVideoMode(_THIS, SDL_Surface *current, + int width, int height, int bpp, Uint32 flags) +{ + int mode_found; + int i; + VGLMode **modes; + + modes = VGLListModes(bpp, V_INFO_MM_DIRECT | V_INFO_MM_PACKED); + mode_found = 0; + for (i = 0; modes[i] != NULL; i++) { + if ((modes[i]->ModeInfo.Xsize == width) && + (modes[i]->ModeInfo.Ysize == height) && + ((modes[i]->ModeInfo.Type == VIDBUF8) || + (modes[i]->ModeInfo.Type == VIDBUF16) || + (modes[i]->ModeInfo.Type == VIDBUF32))) { + mode_found = 1; + break; + } + } + if (mode_found == 0) { + SDL_SetError("No matching video mode found"); + return NULL; + } + + /* Shutdown previous videomode (if any) */ + if (VGLCurMode != NULL) + VGLEnd(); + + /* Try to set the requested linear video mode */ + if (VGLInit(modes[i]->ModeId) != 0) { + SDL_SetError("Unable to switch to requested mode"); + return NULL; + } + + VGLCurMode = SDL_realloc(VGLCurMode, sizeof(VGLMode)); + VGLCurMode->ModeInfo = *VGLDisplay; + VGLCurMode->Depth = modes[i]->Depth; + VGLCurMode->ModeId = modes[i]->ModeId; + VGLCurMode->Rmask = modes[i]->Rmask; + VGLCurMode->Gmask = modes[i]->Gmask; + VGLCurMode->Bmask = modes[i]->Bmask; + + /* Workaround a bug in libvgl */ + if (VGLCurMode->ModeInfo.PixelBytes == 0) + (VGLCurMode->ModeInfo.PixelBytes = 1); + + current->w = VGLCurMode->ModeInfo.Xsize; + current->h = VGLCurMode->ModeInfo.Ysize; + current->pixels = VGLCurMode->ModeInfo.Bitmap; + current->pitch = VGLCurMode->ModeInfo.Xsize * + VGLCurMode->ModeInfo.PixelBytes; + current->flags = (SDL_FULLSCREEN | SDL_HWSURFACE); + + /* Check if we are in a pseudo-color mode */ + if (VGLCurMode->ModeInfo.Type == VIDBUF8) + current->flags |= SDL_HWPALETTE; + + /* Check if we can do doublebuffering */ + if (flags & SDL_DOUBLEBUF) { + if (VGLCurMode->ModeInfo.Xsize * 2 <= + VGLCurMode->ModeInfo.VYsize) { + current->flags |= SDL_DOUBLEBUF; + flip_page = 0; + flip_address[0] = (byte *)current->pixels; + flip_address[1] = (byte *)current->pixels + + current->h * current->pitch; + VGL_FlipHWSurface(this, current); + } + } + + if (! SDL_ReallocFormat(current, modes[i]->Depth, VGLCurMode->Rmask, + VGLCurMode->Gmask, VGLCurMode->Bmask, 0)) { + return NULL; + } + + /* Update hardware acceleration info */ + VGL_UpdateVideoInfo(this); + + /* Set the blit function */ + this->UpdateRects = VGL_DirectUpdate; + + /* We're done */ + return current; +} + +/* We don't actually allow hardware surfaces other than the main one */ +static int VGL_AllocHWSurface(_THIS, SDL_Surface *surface) +{ + return -1; +} +static void VGL_FreeHWSurface(_THIS, SDL_Surface *surface) +{ + return; +} + +/* We need to wait for vertical retrace on page flipped displays */ +static int VGL_LockHWSurface(_THIS, SDL_Surface *surface) +{ + if (surface == SDL_VideoSurface) { + SDL_mutexP(hw_lock); + } + return 0; +} +static void VGL_UnlockHWSurface(_THIS, SDL_Surface *surface) +{ + if (surface == SDL_VideoSurface) { + SDL_mutexV(hw_lock); + } +} + +static int VGL_FlipHWSurface(_THIS, SDL_Surface *surface) +{ + if (VGLPanScreen(VGLDisplay, 0, flip_page * surface->h) < 0) { + SDL_SetError("VGLPanSreen() failed"); + return -1; + } + + flip_page = !flip_page; + surface->pixels = flip_address[flip_page]; + + return 0; +} + +static void VGL_DirectUpdate(_THIS, int numrects, SDL_Rect *rects) +{ + return; +} + +int VGL_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors) +{ + int i; + + for(i = 0; i < ncolors; i++) { + VGLSetPaletteIndex(firstcolor + i, + colors[i].r>>2, + colors[i].g>>2, + colors[i].b>>2); + } + return 1; +} + +/* Note: If we are terminated, this could be called in the middle of + another SDL video routine -- notably UpdateRects. +*/ +void VGL_VideoQuit(_THIS) +{ + int i, j; + + /* Return the keyboard to the normal state */ + VGLKeyboardEnd(); + + /* Reset the console video mode if we actually initialised one */ + if (VGLCurMode != NULL) { + VGLEnd(); + SDL_free(VGLCurMode); + VGLCurMode = NULL; + } + + /* Clear the lock mutex */ + if (hw_lock != NULL) { + SDL_DestroyMutex(hw_lock); + hw_lock = NULL; + } + + /* Free video mode lists */ + for (i = 0; i < NUM_MODELISTS; i++) { + if (SDL_modelist[i] != NULL) { + for (j = 0; SDL_modelist[i][j] != NULL; ++j) { + SDL_free(SDL_modelist[i][j]); + } + SDL_free(SDL_modelist[i]); + SDL_modelist[i] = NULL; + } + } + + if ( this->screen && (this->screen->flags & SDL_HWSURFACE) ) { + /* Direct screen access, not a memory buffer */ + this->screen->pixels = NULL; + } +} + +#define VGL_RED_INDEX 0 +#define VGL_GREEN_INDEX 1 +#define VGL_BLUE_INDEX 2 + +static VGLMode ** +VGLListModes(int depth, int mem_model) +{ + static VGLMode **modes = NULL; + + VGLBitmap *vminfop; + VGLMode **modesp, *modescp; + video_info_t minfo; + int adptype, i, modenum; + + if (modes == NULL) { + modes = SDL_malloc(sizeof(VGLMode *) * M_VESA_MODE_MAX); + bzero(modes, sizeof(VGLMode *) * M_VESA_MODE_MAX); + } + modesp = modes; + + for (modenum = 0; modenum < M_VESA_MODE_MAX; modenum++) { + minfo.vi_mode = modenum; + if (ioctl(0, CONS_MODEINFO, &minfo) || ioctl(0, CONS_CURRENT, &adptype)) + continue; + if (minfo.vi_mode != modenum) + continue; + if ((minfo.vi_flags & V_INFO_GRAPHICS) == 0) + continue; + if ((mem_model != -1) && ((minfo.vi_mem_model & mem_model) == 0)) + continue; + if ((depth > 1) && (minfo.vi_depth != depth)) + continue; + + /* reallocf can fail */ + if ((*modesp = reallocf(*modesp, sizeof(VGLMode))) == NULL) + return NULL; + modescp = *modesp; + + vminfop = &(modescp->ModeInfo); + bzero(vminfop, sizeof(VGLBitmap)); + + vminfop->Type = NOBUF; + + vminfop->PixelBytes = 1; /* Good default value */ + switch (minfo.vi_mem_model) { + case V_INFO_MM_PLANAR: + /* we can handle EGA/VGA planar modes only */ + if (!(minfo.vi_depth != 4 || minfo.vi_planes != 4 + || (adptype != KD_EGA && adptype != KD_VGA))) + vminfop->Type = VIDBUF4; + break; + case V_INFO_MM_PACKED: + /* we can do only 256 color packed modes */ + if (minfo.vi_depth == 8) + vminfop->Type = VIDBUF8; + break; + case V_INFO_MM_VGAX: + vminfop->Type = VIDBUF8X; + break; +#if defined(__FREEBSD__) && (defined(__DragonFly__) || __FreeBSD_version >= 500000) + case V_INFO_MM_DIRECT: + vminfop->PixelBytes = minfo.vi_pixel_size; + switch (vminfop->PixelBytes) { + case 2: + vminfop->Type = VIDBUF16; + break; +#if notyet + case 3: + vminfop->Type = VIDBUF24; + break; +#endif + case 4: + vminfop->Type = VIDBUF32; + break; + default: + break; + } +#endif + default: + break; + } + if (vminfop->Type == NOBUF) + continue; + + switch (vminfop->Type) { + case VIDBUF16: + case VIDBUF32: + modescp->Rmask = ((1 << minfo.vi_pixel_fsizes[VGL_RED_INDEX]) - 1) << + minfo.vi_pixel_fields[VGL_RED_INDEX]; + modescp->Gmask = ((1 << minfo.vi_pixel_fsizes[VGL_GREEN_INDEX]) - 1) << + minfo.vi_pixel_fields[VGL_GREEN_INDEX]; + modescp->Bmask = ((1 << minfo.vi_pixel_fsizes[VGL_BLUE_INDEX]) - 1) << + minfo.vi_pixel_fields[VGL_BLUE_INDEX]; + break; + + default: + break; + } + + vminfop->Xsize = minfo.vi_width; + vminfop->Ysize = minfo.vi_height; + modescp->Depth = minfo.vi_depth; + + /* XXX */ + if (minfo.vi_mode >= M_VESA_BASE) + modescp->ModeId = _IO('V', minfo.vi_mode - M_VESA_BASE); + else + modescp->ModeId = _IO('S', minfo.vi_mode); + + /* Sort list */ + for (i = 0; modes + i < modesp ; i++) { + if (modes[i]->ModeInfo.Xsize * modes[i]->ModeInfo.Ysize > + vminfop->Xsize * modes[i]->ModeInfo.Ysize) + continue; + if ((modes[i]->ModeInfo.Xsize * modes[i]->ModeInfo.Ysize == + vminfop->Xsize * vminfop->Ysize) && + (modes[i]->Depth >= modescp->Depth)) + continue; + *modesp = modes[i]; + modes[i] = modescp; + modescp = *modesp; + vminfop = &(modescp->ModeInfo); + } + + modesp++; + } + + if (*modesp != NULL) { + SDL_free(*modesp); + *modesp = NULL; + } + + return modes; +} diff --git a/3rdparty/SDL/src/video/vgl/SDL_vglvideo.h b/3rdparty/SDL/src/video/vgl/SDL_vglvideo.h new file mode 100644 index 0000000..9fc3569 --- /dev/null +++ b/3rdparty/SDL/src/video/vgl/SDL_vglvideo.h @@ -0,0 +1,65 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#ifndef _SDL_vglvideo_h +#define _SDL_vglvideo_h + +#include <sys/fbio.h> +#include <sys/consio.h> +#include <vgl.h> + +#include "SDL_mouse.h" +#include "SDL_mutex.h" +#include "../SDL_sysvideo.h" + +/* Hidden "this" pointer for the video functions */ +#define _THIS SDL_VideoDevice *this + +typedef struct { + int ModeId; + int Depth; + int Rmask; + int Gmask; + int Bmask; + VGLBitmap ModeInfo; +} VGLMode; + +/* Private display data */ +struct SDL_PrivateVideoData { +#define NUM_MODELISTS 4 /* 8, 16, 24, and 32 bits-per-pixel */ + int SDL_nummodes[NUM_MODELISTS]; + SDL_Rect **SDL_modelist[NUM_MODELISTS]; + SDL_mutex *hw_lock; + VGLMode *VGLCurMode; + int flip_page; + byte *flip_address[2]; +}; +/* Old variable names */ +#define SDL_nummodes (this->hidden->SDL_nummodes) +#define SDL_modelist (this->hidden->SDL_modelist) +#define hw_lock (this->hidden->hw_lock) +#define VGLCurMode (this->hidden->VGLCurMode) +#define flip_page (this->hidden->flip_page) +#define flip_address (this->hidden->flip_address) + +#endif /* _SDL_vglvideo_h */ diff --git a/3rdparty/SDL/src/video/wincommon/SDL_lowvideo.h b/3rdparty/SDL/src/video/wincommon/SDL_lowvideo.h new file mode 100644 index 0000000..89d1a88 --- /dev/null +++ b/3rdparty/SDL/src/video/wincommon/SDL_lowvideo.h @@ -0,0 +1,152 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#ifndef _SDL_lowvideo_h +#define _SDL_lowvideo_h + +#define WIN32_LEAN_AND_MEAN +#include <windows.h> + +#ifndef SetClassLongPtr +#define SetClassLongPtr SetClassLong +#endif +#ifndef GetWindowLongPtr +#define GetWindowLongPtr GetWindowLong +#endif +#ifndef SetWindowLongPtr +#define SetWindowLongPtr SetWindowLong +#endif +#ifndef GWLP_WNDPROC +#define GWLP_WNDPROC GWL_WNDPROC +#endif +#ifndef GWLP_HINSTANCE +#define GWLP_HINSTANCE GWL_HINSTANCE +#endif +#ifndef GCLP_HICON +#define GCLP_HICON GCL_HICON +#endif + +#include "../SDL_sysvideo.h" + +/* Hidden "this" pointer for the video functions */ +#define _THIS SDL_VideoDevice *this + +#define FULLSCREEN() \ + ((SDL_VideoSurface->flags & SDL_FULLSCREEN) == SDL_FULLSCREEN) + +#define WINDIB_FULLSCREEN() \ +( \ + SDL_VideoSurface && \ + FULLSCREEN() && \ + (((SDL_VideoSurface->flags & SDL_OPENGL ) == SDL_OPENGL ) || \ + ((SDL_strcmp(this->name, "windib") == 0) || \ + (SDL_strcmp(this->name, "gapi") == 0))) \ +) +#define DDRAW_FULLSCREEN() \ +( \ + SDL_VideoSurface && \ + FULLSCREEN() && \ + ((SDL_VideoSurface->flags & SDL_OPENGL ) != SDL_OPENGL ) && \ + (SDL_strcmp(this->name, "directx") == 0) \ +) + +#define DINPUT_FULLSCREEN() \ +( \ + FULLSCREEN() && \ + (strcmp(this->name, "directx") == 0) \ +) + +#define DINPUT() (strcmp(this->name, "directx") == 0) + +/* The main window -- and a function to set it for the audio */ +#ifdef _WIN32_WCE +extern LPWSTR SDL_Appname; +#else +extern LPSTR SDL_Appname; +#endif +extern HINSTANCE SDL_Instance; +extern HWND SDL_Window; +extern BOOL SDL_windowid; + +/* Variables and functions exported to other parts of the native video + subsystem (SDL_sysevents.c) +*/ +extern void WIN_FlushMessageQueue(); + +/* Called by windows message loop when application is activated */ +extern void (*WIN_Activate)(_THIS, BOOL active, BOOL minimized); + +/* Called by windows message loop when system palette is available */ +extern void (*WIN_RealizePalette)(_THIS); + +/* Called by windows message loop when the system palette changes */ +extern void (*WIN_PaletteChanged)(_THIS, HWND window); + +/* Called by windows message loop when a portion of the screen needs update */ +extern void (*WIN_WinPAINT)(_THIS, HDC hdc); + +/* Called by windows message loop when the message isn't handled */ +extern LONG (*HandleMessage)(_THIS, HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam); + +/* The window cursor (from SDL_sysmouse.c) */ +extern HCURSOR SDL_hcursor; + +/* The bounds of the window in screen coordinates */ +extern RECT SDL_bounds; + +/* The position of the window in windowed mode */ +extern int SDL_windowX; +extern int SDL_windowY; + +/* Flag -- SDL is performing a resize, rather than the user */ +extern int SDL_resizing; + +/* Flag -- the mouse is in relative motion mode */ +extern int mouse_relative; + +/* The GDI fullscreen mode currently active */ +#ifndef NO_CHANGEDISPLAYSETTINGS +extern DEVMODE SDL_desktop_mode; +extern DEVMODE SDL_fullscreen_mode; +#endif + +/* The system gamma ramp for GDI modes */ +extern WORD *gamma_saved; + +/* This is really from SDL_dx5audio.c */ +extern void DX5_SoundFocus(HWND window); + +/* DJM: This is really from SDL_sysevents.c, we need it in + GDL_CreateWindow as well */ +LRESULT CALLBACK WinMessage(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam); + +#ifdef _WIN64 +#define SDL_ToUnicode ToUnicode +#else +/* JFP: Implementation of ToUnicode() that works on 9x/ME/2K/XP */ +typedef int (WINAPI *ToUnicodeFN)(UINT, UINT, const BYTE *, LPWSTR, int, UINT); + +extern ToUnicodeFN SDL_ToUnicode; +#endif + +#endif /* SDL_lowvideo_h */ diff --git a/3rdparty/SDL/src/video/wincommon/SDL_sysevents.c b/3rdparty/SDL/src/video/wincommon/SDL_sysevents.c new file mode 100644 index 0000000..76c67a1 --- /dev/null +++ b/3rdparty/SDL/src/video/wincommon/SDL_sysevents.c @@ -0,0 +1,855 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#define WIN32_LEAN_AND_MEAN +#include <windows.h> + +/* Make sure XBUTTON stuff is defined that isn't in older Platform SDKs... */ +#ifndef WM_XBUTTONDOWN +#define WM_XBUTTONDOWN 0x020B +#endif +#ifndef WM_XBUTTONUP +#define WM_XBUTTONUP 0x020C +#endif +#ifndef GET_XBUTTON_WPARAM +#define GET_XBUTTON_WPARAM(w) (HIWORD(w)) +#endif + +#include "SDL_events.h" +#include "SDL_video.h" +#include "SDL_syswm.h" +#include "../SDL_sysvideo.h" +#include "../../events/SDL_sysevents.h" +#include "../../events/SDL_events_c.h" +#include "SDL_lowvideo.h" +#include "SDL_syswm_c.h" +#include "SDL_main.h" +#include "SDL_loadso.h" + +#ifdef WMMSG_DEBUG +#include "wmmsg.h" +#endif + +#include "../windib/SDL_gapidibvideo.h" + +#ifdef SDL_VIDEO_DRIVER_GAPI +#include "../gapi/SDL_gapivideo.h" +#endif + +#ifdef _WIN32_WCE +#define IsZoomed(HWND) 1 +#define NO_GETKEYBOARDSTATE +#if _WIN32_WCE < 420 +#define NO_CHANGEDISPLAYSETTINGS +#endif +#endif + +/* The window we use for everything... */ +#ifdef _WIN32_WCE +LPWSTR SDL_Appname = NULL; +#else +LPSTR SDL_Appname = NULL; +#endif +Uint32 SDL_Appstyle = 0; +HINSTANCE SDL_Instance = NULL; +HWND SDL_Window = NULL; +RECT SDL_bounds = {0, 0, 0, 0}; +int SDL_windowX = 0; +int SDL_windowY = 0; +int SDL_resizing = 0; +int mouse_relative = 0; +int posted = 0; +#ifndef NO_CHANGEDISPLAYSETTINGS +DEVMODE SDL_desktop_mode; +DEVMODE SDL_fullscreen_mode; +#endif +WORD *gamma_saved = NULL; + + +/* Functions called by the message processing function */ +LONG (*HandleMessage)(_THIS, HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)=NULL; +void (*WIN_Activate)(_THIS, BOOL active, BOOL iconic); +void (*WIN_RealizePalette)(_THIS); +void (*WIN_PaletteChanged)(_THIS, HWND window); +void (*WIN_WinPAINT)(_THIS, HDC hdc); +extern void DIB_SwapGamma(_THIS); + +#ifndef NO_GETKEYBOARDSTATE +#ifndef _WIN64 +/* Variables and support functions for SDL_ToUnicode() */ +static int codepage; +static int Is9xME(); +static int GetCodePage(); +static int WINAPI ToUnicode9xME(UINT vkey, UINT scancode, const BYTE *keystate, LPWSTR wchars, int wsize, UINT flags); + +ToUnicodeFN SDL_ToUnicode = ToUnicode9xME; +#endif +#endif /* !NO_GETKEYBOARDSTATE */ + + +#if defined(_WIN32_WCE) + +//AdjustWindowRect is not available under WinCE 2003 +#define AdjustWindowRect(a,b,c) (AdjustWindowRectEx((a),(b),(c),0)) + +// dynamically load aygshell dll because we want SDL to work on HPC and be300 +HINSTANCE aygshell = NULL; +BOOL (WINAPI *SHFullScreen)(HWND hwndRequester, DWORD dwState) = 0; + +#define SHFS_SHOWTASKBAR 0x0001 +#define SHFS_HIDETASKBAR 0x0002 +#define SHFS_SHOWSIPBUTTON 0x0004 +#define SHFS_HIDESIPBUTTON 0x0008 +#define SHFS_SHOWSTARTICON 0x0010 +#define SHFS_HIDESTARTICON 0x0020 + +static void LoadAygshell(void) +{ + if( !aygshell ) + aygshell = SDL_LoadObject("aygshell.dll"); + if( (aygshell != 0) && (SHFullScreen == 0) ) + { + SHFullScreen = (int (WINAPI *)(struct HWND__ *,unsigned long)) SDL_LoadFunction(aygshell, "SHFullScreen"); + } +} + +#endif + +/* JC 14 Mar 2006 + This is used all over the place, in the windib driver and in the dx5 driver + So we may as well stick it here instead of having multiple copies scattered + about +*/ +void WIN_FlushMessageQueue() +{ + MSG msg; + while ( PeekMessage(&msg, NULL, 0, 0, PM_REMOVE) ) { + if ( msg.message == WM_QUIT ) break; + TranslateMessage( &msg ); + DispatchMessage( &msg ); + } +} + +static void SDL_RestoreGameMode(void) +{ +#ifdef _WIN32_WCE //Under ce we don't minimize, therefore no restore + +#ifdef SDL_VIDEO_DRIVER_GAPI + SDL_VideoDevice *this = current_video; + if(SDL_strcmp(this->name, "gapi") == 0) + { + if( this->hidden->gapiInfo->suspended ) + { + this->hidden->gapiInfo->suspended = 0; + } + } +#endif + +#else + ShowWindow(SDL_Window, SW_RESTORE); +#endif + +#ifndef NO_CHANGEDISPLAYSETTINGS +#ifndef _WIN32_WCE + ChangeDisplaySettings(&SDL_fullscreen_mode, CDS_FULLSCREEN); +#endif +#endif /* NO_CHANGEDISPLAYSETTINGS */ +} +static void SDL_RestoreDesktopMode(void) +{ + +#ifdef _WIN32_WCE + +#ifdef SDL_VIDEO_DRIVER_GAPI + SDL_VideoDevice *this = current_video; + if(SDL_strcmp(this->name, "gapi") == 0) + { + if( !this->hidden->gapiInfo->suspended ) + { + this->hidden->gapiInfo->suspended = 1; + } + } +#endif + +#else + /* WinCE does not have a taskbar, so minimizing is not convenient */ + ShowWindow(SDL_Window, SW_MINIMIZE); +#endif + +#ifndef NO_CHANGEDISPLAYSETTINGS +#ifndef _WIN32_WCE + ChangeDisplaySettings(NULL, 0); +#endif +#endif /* NO_CHANGEDISPLAYSETTINGS */ +} + +#ifdef WM_MOUSELEAVE +/* + Special code to handle mouse leave events - this sucks... + http://support.microsoft.com/support/kb/articles/q183/1/07.asp + + TrackMouseEvent() is only available on Win98 and WinNT. + _TrackMouseEvent() is available on Win95, but isn't yet in the mingw32 + development environment, and only works on systems that have had IE 3.0 + or newer installed on them (which is not the case with the base Win95). + Therefore, we implement our own version of _TrackMouseEvent() which + uses our own implementation if TrackMouseEvent() is not available. +*/ +static BOOL (WINAPI *_TrackMouseEvent)(TRACKMOUSEEVENT *ptme) = NULL; + +static VOID CALLBACK +TrackMouseTimerProc(HWND hWnd, UINT uMsg, UINT idEvent, DWORD dwTime) +{ + union { RECT rect; POINT pt; } rectpt; /* prevent type-punning issue. */ + POINT pt; + + GetClientRect(hWnd, &rectpt.rect); + MapWindowPoints(hWnd, NULL, &rectpt.pt, 2); + GetCursorPos(&pt); + if ( !PtInRect(&rectpt.rect, pt) || (WindowFromPoint(pt) != hWnd) ) { + if ( !KillTimer(hWnd, idEvent) ) { + /* Error killing the timer! */ + } + PostMessage(hWnd, WM_MOUSELEAVE, 0, 0); + } +} +static BOOL WINAPI WIN_TrackMouseEvent(TRACKMOUSEEVENT *ptme) +{ + if ( ptme->dwFlags == TME_LEAVE ) { + return SetTimer(ptme->hwndTrack, ptme->dwFlags, 100, + (TIMERPROC)TrackMouseTimerProc) != 0; + } + return FALSE; +} +#endif /* WM_MOUSELEAVE */ + +int sysevents_mouse_pressed = 0; + +/* The main Win32 event handler +DJM: This is no longer static as (DX5/DIB)_CreateWindow needs it +*/ +LRESULT CALLBACK WinMessage(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) +{ + SDL_VideoDevice *this = current_video; +#ifdef WMMSG_DEBUG + fprintf(stderr, "Received windows message: "); + if ( msg > MAX_WMMSG ) { + fprintf(stderr, "%d", msg); + } else { + fprintf(stderr, "%s", wmtab[msg]); + } + fprintf(stderr, " -- 0x%X, 0x%X\n", wParam, lParam); +#endif + switch (msg) { + + case WM_ACTIVATE: { + SDL_VideoDevice *this = current_video; + BOOL active, minimized; + Uint8 appstate; + + minimized = HIWORD(wParam); + active = (LOWORD(wParam) != WA_INACTIVE) && !minimized; + if ( active ) { + /* Gain the following states */ + appstate = SDL_APPACTIVE|SDL_APPINPUTFOCUS; + if ( !(SDL_GetAppState() & SDL_APPINPUTFOCUS) ) { + if ( this->input_grab != SDL_GRAB_OFF ) { + WIN_GrabInput(this, SDL_GRAB_ON); + } + if ( ! DDRAW_FULLSCREEN() ) { + DIB_SwapGamma(this); + } + if ( WINDIB_FULLSCREEN() ) { + SDL_RestoreGameMode(); + } + } +#if defined(_WIN32_WCE) + if ( WINDIB_FULLSCREEN() ) { + LoadAygshell(); + if( SHFullScreen ) + SHFullScreen(SDL_Window, SHFS_HIDESTARTICON|SHFS_HIDETASKBAR|SHFS_HIDESIPBUTTON); + else + ShowWindow(FindWindow(TEXT("HHTaskBar"),NULL),SW_HIDE); + } +#endif + posted = SDL_PrivateAppActive(1, appstate); + } else { + /* Lose the following states */ + appstate = SDL_APPINPUTFOCUS; + if ( minimized ) { + appstate |= SDL_APPACTIVE; + } + + if ( SDL_GetAppState() & SDL_APPINPUTFOCUS ) { + if ( this->input_grab != SDL_GRAB_OFF ) { + WIN_GrabInput(this, SDL_GRAB_OFF); + } + if ( ! DDRAW_FULLSCREEN() ) { + DIB_SwapGamma(this); + } + if ( WINDIB_FULLSCREEN() ) { + appstate |= SDL_APPMOUSEFOCUS; + SDL_RestoreDesktopMode(); + /* A fullscreen app gets hidden but will not get a minimize event */ + appstate |= (SDL_APPACTIVE | SDL_APPMOUSEFOCUS); +#if defined(_WIN32_WCE) + LoadAygshell(); + if( SHFullScreen ) + SHFullScreen(SDL_Window, SHFS_SHOWSTARTICON|SHFS_SHOWTASKBAR|SHFS_SHOWSIPBUTTON); + else + ShowWindow(FindWindow(TEXT("HHTaskBar"),NULL),SW_SHOW); +#endif + } + } + posted = SDL_PrivateAppActive(0, appstate); + } + WIN_Activate(this, active, minimized); + return(0); + } + break; + + case WM_MOUSEMOVE: { + +#ifdef WM_MOUSELEAVE + if ( SDL_VideoSurface ) { + /* mouse has entered the window */ + + if ( !(SDL_GetAppState() & SDL_APPMOUSEFOCUS) ) { + TRACKMOUSEEVENT tme; + + tme.cbSize = sizeof(tme); + tme.dwFlags = TME_LEAVE; + tme.hwndTrack = SDL_Window; + _TrackMouseEvent(&tme); + } + } +#endif /* WM_MOUSELEAVE */ + + /* Mouse motion is handled in DIB_PumpEvents or + * DX5_PumpEvents, depending on the video driver + * in use */ + + posted = SDL_PrivateAppActive(1, SDL_APPMOUSEFOCUS); + } + return(0); + +#ifdef WM_MOUSELEAVE + case WM_MOUSELEAVE: { + + if ( SDL_VideoSurface ) { + /* mouse has left the window */ + posted = SDL_PrivateAppActive(0, SDL_APPMOUSEFOCUS); + } + } + return(0); +#endif /* WM_MOUSELEAVE */ + + case WM_LBUTTONDOWN: + case WM_LBUTTONUP: + case WM_MBUTTONDOWN: + case WM_MBUTTONUP: + case WM_RBUTTONDOWN: + case WM_RBUTTONUP: + case WM_XBUTTONDOWN: + case WM_XBUTTONUP: { + /* Mouse is handled by DirectInput when fullscreen */ + if ( SDL_VideoSurface && ! DINPUT() ) { + WORD xbuttonval = 0; + Uint8 button, state; + int x, y; + + /* DJM: + We want the SDL window to take focus so that + it acts like a normal windows "component" + (e.g. gains keyboard focus on a mouse click). + */ + SetFocus(SDL_Window); + + /* Figure out which button to use */ + switch (msg) { + case WM_LBUTTONDOWN: + button = SDL_BUTTON_LEFT; + state = SDL_PRESSED; + break; + case WM_LBUTTONUP: + button = SDL_BUTTON_LEFT; + state = SDL_RELEASED; + break; + case WM_MBUTTONDOWN: + button = SDL_BUTTON_MIDDLE; + state = SDL_PRESSED; + break; + case WM_MBUTTONUP: + button = SDL_BUTTON_MIDDLE; + state = SDL_RELEASED; + break; + case WM_RBUTTONDOWN: + button = SDL_BUTTON_RIGHT; + state = SDL_PRESSED; + break; + case WM_RBUTTONUP: + button = SDL_BUTTON_RIGHT; + state = SDL_RELEASED; + break; + case WM_XBUTTONDOWN: + xbuttonval = GET_XBUTTON_WPARAM(wParam); + button = SDL_BUTTON_X1 + xbuttonval - 1; + state = SDL_PRESSED; + break; + case WM_XBUTTONUP: + xbuttonval = GET_XBUTTON_WPARAM(wParam); + button = SDL_BUTTON_X1 + xbuttonval - 1; + state = SDL_RELEASED; + break; + default: + /* Eh? Unknown button? */ + return(0); + } + if ( state == SDL_PRESSED ) { + /* Grab mouse so we get up events */ + if ( ++sysevents_mouse_pressed > 0 ) { + SetCapture(hwnd); + } + } else { + /* Release mouse after all up events */ + if ( --sysevents_mouse_pressed <= 0 ) { + ReleaseCapture(); + sysevents_mouse_pressed = 0; + } + } + if ( mouse_relative ) { + /* RJR: March 28, 2000 + report internal mouse position if in relative mode */ + x = 0; y = 0; + } else { + x = (Sint16)LOWORD(lParam); + y = (Sint16)HIWORD(lParam); +#ifdef _WIN32_WCE + if (SDL_VideoSurface) + GapiTransform(this->hidden->userOrientation, +this->hidden->hiresFix, &x, &y); +#endif + } + posted = SDL_PrivateMouseButton( + state, button, x, y); + + /* + * MSDN says: + * "Unlike the WM_LBUTTONUP, WM_MBUTTONUP, and WM_RBUTTONUP + * messages, an application should return TRUE from [an + * XBUTTON message] if it processes it. Doing so will allow + * software that simulates this message on Microsoft Windows + * systems earlier than Windows 2000 to determine whether + * the window procedure processed the message or called + * DefWindowProc to process it. + */ + if (xbuttonval > 0) + return(TRUE); + } + } + return(0); + + +#if (_WIN32_WINNT >= 0x0400) || (_WIN32_WINDOWS > 0x0400) + case WM_MOUSEWHEEL: + if ( SDL_VideoSurface && ! DINPUT() ) { + int move = (short)HIWORD(wParam); + if ( move ) { + Uint8 button; + if ( move > 0 ) + button = SDL_BUTTON_WHEELUP; + else + button = SDL_BUTTON_WHEELDOWN; + posted = SDL_PrivateMouseButton( + SDL_PRESSED, button, 0, 0); + posted |= SDL_PrivateMouseButton( + SDL_RELEASED, button, 0, 0); + } + } + return(0); +#endif + +#ifdef WM_GETMINMAXINFO + /* This message is sent as a way for us to "check" the values + * of a position change. If we don't like it, we can adjust + * the values before they are changed. + */ + case WM_GETMINMAXINFO: { + MINMAXINFO *info; + RECT size; + int x, y; + int style; + int width; + int height; + + /* We don't want to clobber an internal resize */ + if ( SDL_resizing ) + return(0); + + /* We allow resizing with the SDL_RESIZABLE flag */ + if ( SDL_PublicSurface && + (SDL_PublicSurface->flags & SDL_RESIZABLE) ) { + return(0); + } + + /* Get the current position of our window */ + GetWindowRect(SDL_Window, &size); + x = size.left; + y = size.top; + + /* Calculate current width and height of our window */ + size.top = 0; + size.left = 0; + if ( SDL_PublicSurface != NULL ) { + size.bottom = SDL_PublicSurface->h; + size.right = SDL_PublicSurface->w; + } else { + size.bottom = 0; + size.right = 0; + } + + /* DJM - according to the docs for GetMenu(), the + return value is undefined if hwnd is a child window. + Aparently it's too difficult for MS to check + inside their function, so I have to do it here. + */ + style = GetWindowLong(hwnd, GWL_STYLE); + AdjustWindowRect( + &size, + style, + style & WS_CHILDWINDOW ? FALSE + : GetMenu(hwnd) != NULL); + + width = size.right - size.left; + height = size.bottom - size.top; + + /* Fix our size to the current size */ + info = (MINMAXINFO *)lParam; + info->ptMaxSize.x = width; + info->ptMaxSize.y = height; + info->ptMaxPosition.x = x; + info->ptMaxPosition.y = y; + info->ptMinTrackSize.x = width; + info->ptMinTrackSize.y = height; + info->ptMaxTrackSize.x = width; + info->ptMaxTrackSize.y = height; + } + return(0); +#endif /* WM_GETMINMAXINFO */ + + case WM_WINDOWPOSCHANGING: { + WINDOWPOS *windowpos = (WINDOWPOS*)lParam; + + /* When menu is at the side or top, Windows likes + to try to reposition the fullscreen window when + changing video modes. + */ + if ( !SDL_resizing && + SDL_PublicSurface && + (SDL_PublicSurface->flags & SDL_FULLSCREEN) ) { + windowpos->x = 0; + windowpos->y = 0; + } + } + return(0); + + case WM_WINDOWPOSCHANGED: { + SDL_VideoDevice *this = current_video; + POINT pt; + int w, h; + + GetClientRect(SDL_Window, &SDL_bounds); + + /* avoiding type-punning here... */ + pt.x = SDL_bounds.left; + pt.y = SDL_bounds.top; + ClientToScreen(SDL_Window, &pt); + SDL_bounds.left = pt.x; + SDL_bounds.top = pt.y; + + pt.x = SDL_bounds.right; + pt.y = SDL_bounds.bottom; + ClientToScreen(SDL_Window, &pt); + SDL_bounds.right = pt.x; + SDL_bounds.bottom = pt.y; + + if ( !SDL_resizing && !IsZoomed(SDL_Window) && + SDL_PublicSurface && + !(SDL_PublicSurface->flags & SDL_FULLSCREEN) ) { + SDL_windowX = SDL_bounds.left; + SDL_windowY = SDL_bounds.top; + } + w = SDL_bounds.right-SDL_bounds.left; + h = SDL_bounds.bottom-SDL_bounds.top; + if ( this->input_grab != SDL_GRAB_OFF ) { + ClipCursor(&SDL_bounds); + } + if ( SDL_PublicSurface && + (SDL_PublicSurface->flags & SDL_RESIZABLE) ) { + SDL_PrivateResize(w, h); + } + } + break; + + /* We need to set the cursor */ + case WM_SETCURSOR: { + Uint16 hittest; + + hittest = LOWORD(lParam); + if ( hittest == HTCLIENT ) { + SetCursor(SDL_hcursor); + return(TRUE); + } + } + break; + + /* We are about to get palette focus! */ + case WM_QUERYNEWPALETTE: { + WIN_RealizePalette(current_video); + return(TRUE); + } + break; + + /* Another application changed the palette */ + case WM_PALETTECHANGED: { + WIN_PaletteChanged(current_video, (HWND)wParam); + } + break; + + /* We were occluded, refresh our display */ + case WM_PAINT: { + HDC hdc; + PAINTSTRUCT ps; + + hdc = BeginPaint(SDL_Window, &ps); + if ( current_video->screen && + !(current_video->screen->flags & SDL_OPENGL) ) { + WIN_WinPAINT(current_video, hdc); + } + EndPaint(SDL_Window, &ps); + } + return(0); + + /* DJM: Send an expose event in this case */ + case WM_ERASEBKGND: { + posted = SDL_PrivateExpose(); + } + return(0); + + case WM_CLOSE: { + if ( (posted = SDL_PrivateQuit()) ) + PostQuitMessage(0); + } + return(0); + + case WM_DESTROY: { + PostQuitMessage(0); + } + return(0); + +#ifndef NO_GETKEYBOARDSTATE + case WM_INPUTLANGCHANGE: +#ifndef _WIN64 + codepage = GetCodePage(); +#endif + return(TRUE); +#endif + + default: { + /* Special handling by the video driver */ + if (HandleMessage) { + return(HandleMessage(current_video, + hwnd, msg, wParam, lParam)); + } + } + break; + } + return(DefWindowProc(hwnd, msg, wParam, lParam)); +} + +/* Allow the application handle to be stored and retrieved later */ +static void *SDL_handle = NULL; + +void SDL_SetModuleHandle(void *handle) +{ + SDL_handle = handle; +} +void *SDL_GetModuleHandle(void) +{ + void *handle; + + if ( SDL_handle ) { + handle = SDL_handle; + } else { + handle = GetModuleHandle(NULL); + } + return(handle); +} + +/* This allows the SDL_WINDOWID hack */ +BOOL SDL_windowid = FALSE; + +static int app_registered = 0; + +/* Register the class for this application -- exported for winmain.c */ +int SDL_RegisterApp(char *name, Uint32 style, void *hInst) +{ + WNDCLASS class; +#ifdef WM_MOUSELEAVE + HMODULE handle; +#endif + + /* Only do this once... */ + if ( app_registered ) { + ++app_registered; + return(0); + } + +#ifndef CS_BYTEALIGNCLIENT +#define CS_BYTEALIGNCLIENT 0 +#endif + if ( ! name && ! SDL_Appname ) { + name = "SDL_app"; + SDL_Appstyle = CS_BYTEALIGNCLIENT; + SDL_Instance = hInst ? hInst : SDL_GetModuleHandle(); + } + + if ( name ) { +#ifdef _WIN32_WCE + /* WinCE uses the UNICODE version */ + SDL_Appname = SDL_iconv_utf8_ucs2(name); +#else + SDL_Appname = SDL_iconv_utf8_locale(name); +#endif /* _WIN32_WCE */ + SDL_Appstyle = style; + SDL_Instance = hInst ? hInst : SDL_GetModuleHandle(); + } + + /* Register the application class */ + class.hCursor = NULL; + class.hIcon = LoadImage(SDL_Instance, SDL_Appname, + IMAGE_ICON, + 0, 0, LR_DEFAULTCOLOR); + class.lpszMenuName = NULL; + class.lpszClassName = SDL_Appname; + class.hbrBackground = NULL; + class.hInstance = SDL_Instance; + class.style = SDL_Appstyle; +#if SDL_VIDEO_OPENGL + class.style |= CS_OWNDC; +#endif + class.lpfnWndProc = WinMessage; + class.cbWndExtra = 0; + class.cbClsExtra = 0; + if ( ! RegisterClass(&class) ) { + SDL_SetError("Couldn't register application class"); + return(-1); + } + +#ifdef WM_MOUSELEAVE + /* Get the version of TrackMouseEvent() we use */ + _TrackMouseEvent = NULL; + handle = GetModuleHandle("USER32.DLL"); + if ( handle ) { + _TrackMouseEvent = (BOOL (WINAPI *)(TRACKMOUSEEVENT *))GetProcAddress(handle, "TrackMouseEvent"); + } + if ( _TrackMouseEvent == NULL ) { + _TrackMouseEvent = WIN_TrackMouseEvent; + } +#endif /* WM_MOUSELEAVE */ + +#ifndef NO_GETKEYBOARDSTATE +#ifndef _WIN64 + /* Initialise variables for SDL_ToUnicode() */ + codepage = GetCodePage(); + + /* Cygwin headers don't match windows.h, so we have to cast around a + const issue here... */ + SDL_ToUnicode = Is9xME() ? ToUnicode9xME : (ToUnicodeFN) ToUnicode; +#endif +#endif /* NO_GETKEYBOARDSTATE */ + + app_registered = 1; + return(0); +} + +/* Unregisters the windowclass registered in SDL_RegisterApp above. */ +void SDL_UnregisterApp() +{ + WNDCLASS class; + + /* SDL_RegisterApp might not have been called before */ + if ( !app_registered ) { + return; + } + --app_registered; + if ( app_registered == 0 ) { + /* Check for any registered window classes. */ + if ( GetClassInfo(SDL_Instance, SDL_Appname, &class) ) { + UnregisterClass(SDL_Appname, SDL_Instance); + } + SDL_free(SDL_Appname); + SDL_Appname = NULL; + } +} + +#ifndef NO_GETKEYBOARDSTATE +#ifndef _WIN64 +/* JFP: Implementation of ToUnicode() that works on 9x/ME/2K/XP */ + +static int Is9xME() +{ + OSVERSIONINFO info; + + SDL_memset(&info, 0, sizeof(info)); + info.dwOSVersionInfoSize = sizeof(info); + if (!GetVersionEx(&info)) { + return 0; + } + return (info.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS); +} + +static int GetCodePage() +{ + char buff[8]; + int lcid = MAKELCID(LOWORD(GetKeyboardLayout(0)), SORT_DEFAULT); + int cp = GetACP(); + + if (GetLocaleInfo(lcid, LOCALE_IDEFAULTANSICODEPAGE, buff, sizeof(buff))) { + cp = SDL_atoi(buff); + } + return cp; +} + +static int WINAPI ToUnicode9xME(UINT vkey, UINT scancode, const BYTE *keystate, LPWSTR wchars, int wsize, UINT flags) +{ + BYTE chars[2]; + + /* arg #3 should be const BYTE *, but cygwin lists it as PBYTE. */ + if (ToAsciiEx(vkey, scancode, (PBYTE) keystate, (WORD*)chars, 0, GetKeyboardLayout(0)) == 1) { + return MultiByteToWideChar(codepage, 0, (LPCSTR) chars, 1, wchars, wsize); + } + return 0; +} +#endif +#endif /* !NO_GETKEYBOARDSTATE */ diff --git a/3rdparty/SDL/src/video/wincommon/SDL_sysmouse.c b/3rdparty/SDL/src/video/wincommon/SDL_sysmouse.c new file mode 100644 index 0000000..12d17e0 --- /dev/null +++ b/3rdparty/SDL/src/video/wincommon/SDL_sysmouse.c @@ -0,0 +1,259 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#define WIN32_LEAN_AND_MEAN +#include <windows.h> + +#include "SDL_mouse.h" +#include "../../events/SDL_events_c.h" +#include "../SDL_cursor_c.h" +#include "SDL_sysmouse_c.h" +#include "SDL_lowvideo.h" + +#ifdef _WIN32_WCE +#define USE_STATIC_CURSOR +#endif + +HCURSOR SDL_hcursor = NULL; /* Exported for SDL_eventloop.c */ + +/* The implementation dependent data for the window manager cursor */ +/* For some reason when creating a windows cursor, the ands and xors memory + is not copied, so we need to keep track of it and free it when we are done + with the cursor. If we free the memory prematurely, the app crashes. :-} +*/ +struct WMcursor { + HCURSOR curs; +#ifndef USE_STATIC_CURSOR + Uint8 *ands; + Uint8 *xors; +#endif +}; + +/* Convert bits to padded bytes */ +#define PAD_BITS(bits) ((bits+7)/8) + +#ifdef CURSOR_DEBUG +static void PrintBITMAP(FILE *out, char *bits, int w, int h) +{ + int i; + unsigned char ch; + + while ( h-- > 0 ) { + for ( i=0; i<w; ++i ) { + if ( (i%8) == 0 ) + ch = *bits++; + if ( ch&0x80 ) + fprintf(out, "X"); + else + fprintf(out, " "); + ch <<= 1; + } + fprintf(out, "\n"); + } +} +#endif + +#ifndef USE_STATIC_CURSOR +/* Local functions to convert the SDL cursor mask into Windows format */ +static void memnot(Uint8 *dst, Uint8 *src, int len) +{ + while ( len-- > 0 ) + *dst++ = ~*src++; +} +static void memxor(Uint8 *dst, Uint8 *src1, Uint8 *src2, int len) +{ + while ( len-- > 0 ) + *dst++ = (*src1++)^(*src2++); +} +#endif /* !USE_STATIC_CURSOR */ + +void WIN_FreeWMCursor(_THIS, WMcursor *cursor) +{ +#ifndef USE_STATIC_CURSOR + if ( cursor->curs == GetCursor() ) + SetCursor(NULL); + if ( cursor->curs != NULL ) + DestroyCursor(cursor->curs); + if ( cursor->ands != NULL ) + SDL_free(cursor->ands); + if ( cursor->xors != NULL ) + SDL_free(cursor->xors); +#endif /* !USE_STATIC_CURSOR */ + SDL_free(cursor); +} + +WMcursor *WIN_CreateWMCursor(_THIS, + Uint8 *data, Uint8 *mask, int w, int h, int hot_x, int hot_y) +{ +#ifdef USE_STATIC_CURSOR + WMcursor *cursor; + + /* Allocate the cursor */ + cursor = (WMcursor *)SDL_malloc(sizeof(*cursor)); + if ( cursor ) { + cursor->curs = LoadCursor(NULL, IDC_ARROW); + } + return(cursor); +#else + WMcursor *cursor; + int allowed_x; + int allowed_y; + int run, pad, i; + Uint8 *aptr, *xptr; + + /* Check to make sure the cursor size is okay */ + allowed_x = GetSystemMetrics(SM_CXCURSOR); + allowed_y = GetSystemMetrics(SM_CYCURSOR); + if ( (w > allowed_x) || (h > allowed_y) ) { + SDL_SetError("Only cursors of dimension (%dx%d) are allowed", + allowed_x, allowed_y); + return(NULL); + } + + /* Allocate the cursor */ + cursor = (WMcursor *)SDL_malloc(sizeof(*cursor)); + if ( cursor == NULL ) { + SDL_SetError("Out of memory"); + return(NULL); + } + cursor->curs = NULL; + cursor->ands = NULL; + cursor->xors = NULL; + + /* Pad out to the normal cursor size */ + run = PAD_BITS(w); + pad = PAD_BITS(allowed_x)-run; + aptr = cursor->ands = (Uint8 *)SDL_malloc((run+pad)*allowed_y); + xptr = cursor->xors = (Uint8 *)SDL_malloc((run+pad)*allowed_y); + if ( (aptr == NULL) || (xptr == NULL) ) { + WIN_FreeWMCursor(NULL, cursor); + SDL_OutOfMemory(); + return(NULL); + } + for ( i=0; i<h; ++i ) { + memxor(xptr, data, mask, run); + xptr += run; + data += run; + memnot(aptr, mask, run); + mask += run; + aptr += run; + SDL_memset(xptr, 0, pad); + xptr += pad; + SDL_memset(aptr, ~0, pad); + aptr += pad; + } + pad += run; + for ( ; i<allowed_y; ++i ) { + SDL_memset(xptr, 0, pad); + xptr += pad; + SDL_memset(aptr, ~0, pad); + aptr += pad; + } + + /* Create the cursor */ + cursor->curs = CreateCursor( + (HINSTANCE)GetWindowLongPtr(SDL_Window, GWLP_HINSTANCE), + hot_x, hot_y, allowed_x, allowed_y, + cursor->ands, cursor->xors); + if ( cursor->curs == NULL ) { + WIN_FreeWMCursor(NULL, cursor); + SDL_SetError("Windows couldn't create the requested cursor"); + return(NULL); + } + return(cursor); +#endif /* USE_STATIC_CURSOR */ +} + +int WIN_ShowWMCursor(_THIS, WMcursor *cursor) +{ + POINT mouse_pos; + + if ( !this->screen ) { + return(0); + } + + /* Set the window cursor to our cursor, if applicable */ + if ( cursor != NULL ) { + SDL_hcursor = cursor->curs; + } else { + SDL_hcursor = NULL; + } + GetCursorPos(&mouse_pos); + if ( PtInRect(&SDL_bounds, mouse_pos) ) { + SetCursor(SDL_hcursor); + } + return(1); +} + +void WIN_WarpWMCursor(_THIS, Uint16 x, Uint16 y) +{ + if ( mouse_relative) { + /* RJR: March 28, 2000 + leave physical cursor at center of screen if + mouse hidden and grabbed */ + SDL_PrivateMouseMotion(0, 0, x, y); + } else { + POINT pt; + + /* With DirectInput the position doesn't follow + * the cursor, so it is set manually */ + if ( DINPUT() ) { + SDL_PrivateMouseMotion(0, 0, x, y); + } + + pt.x = x; + pt.y = y; + ClientToScreen(SDL_Window, &pt); + SetCursorPos(pt.x, pt.y); + } +} + +/* Update the current mouse state and position */ +void WIN_UpdateMouse(_THIS) +{ + POINT pt; + + /* Always unset SDL_APPMOUSEFOCUS to give the WM_MOUSEMOVE event + * handler a chance to install a TRACKMOUSEEVENT */ + SDL_PrivateAppActive(0, SDL_APPMOUSEFOCUS); + + GetCursorPos(&pt); + ScreenToClient(SDL_Window, &pt); + SDL_PrivateMouseMotion(0,0, (Sint16)pt.x, (Sint16)pt.y); +} + +/* Check to see if we need to enter or leave mouse relative mode */ +void WIN_CheckMouseMode(_THIS) +{ +#ifndef _WIN32_WCE + /* If the mouse is hidden and input is grabbed, we use relative mode */ + if ( !(SDL_cursorstate & CURSOR_VISIBLE) && + (this->input_grab != SDL_GRAB_OFF) ) { + mouse_relative = 1; + } else { + mouse_relative = 0; + } +#else + mouse_relative = 0; +#endif +} diff --git a/3rdparty/SDL/src/video/wincommon/SDL_sysmouse_c.h b/3rdparty/SDL/src/video/wincommon/SDL_sysmouse_c.h new file mode 100644 index 0000000..5d5fe8d --- /dev/null +++ b/3rdparty/SDL/src/video/wincommon/SDL_sysmouse_c.h @@ -0,0 +1,33 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#include "SDL_lowvideo.h" + +/* Functions to be exported */ +extern void WIN_FreeWMCursor(_THIS, WMcursor *cursor); +extern WMcursor *WIN_CreateWMCursor(_THIS, + Uint8 *data, Uint8 *mask, int w, int h, int hot_x, int hot_y); +extern int WIN_ShowWMCursor(_THIS, WMcursor *cursor); +extern void WIN_WarpWMCursor(_THIS, Uint16 x, Uint16 y); +extern void WIN_UpdateMouse(_THIS); +extern void WIN_CheckMouseMode(_THIS); diff --git a/3rdparty/SDL/src/video/wincommon/SDL_syswm.c b/3rdparty/SDL/src/video/wincommon/SDL_syswm.c new file mode 100644 index 0000000..504d95d --- /dev/null +++ b/3rdparty/SDL/src/video/wincommon/SDL_syswm.c @@ -0,0 +1,297 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#define WIN32_LEAN_AND_MEAN +#include <windows.h> + +#include "SDL_version.h" +#include "SDL_video.h" +#include "SDL_loadso.h" +#include "SDL_syswm.h" +#include "../SDL_pixels_c.h" +#include "../SDL_cursor_c.h" +#include "SDL_syswm_c.h" +#include "SDL_wingl_c.h" + + +#ifdef _WIN32_WCE +#define DISABLE_ICON_SUPPORT +#endif + +/* The screen icon -- needs to be freed on SDL_VideoQuit() */ +HICON screen_icn = NULL; + +/* Win32 icon mask semantics are different from those of SDL: + SDL applies the mask to the icon and copies result to desktop. + Win32 applies the mask to the desktop and XORs the icon on. + This means that the SDL mask needs to be applied to the icon and + then inverted and passed to Win32. +*/ +void WIN_SetWMIcon(_THIS, SDL_Surface *icon, Uint8 *mask) +{ +#ifdef DISABLE_ICON_SUPPORT + return; +#else + SDL_Palette *pal_256; + SDL_Surface *icon_256; + Uint8 *pdata, *pwin32; + Uint8 *mdata, *mwin32, m = 0; + int icon_len; + int icon_plen; + int icon_mlen; + int icon_pitch; + int mask_pitch; + SDL_Rect bounds; + int i, skip; + int row, col; + struct /* quasi-BMP format */ Win32Icon { + Uint32 biSize; + Sint32 biWidth; + Sint32 biHeight; + Uint16 biPlanes; + Uint16 biBitCount; + Uint32 biCompression; + Uint32 biSizeImage; + Sint32 biXPelsPerMeter; + Sint32 biYPelsPerMeter; + Uint32 biClrUsed; + Uint32 biClrImportant; + struct /* RGBQUAD -- note it's BGR ordered */ { + Uint8 rgbBlue; + Uint8 rgbGreen; + Uint8 rgbRed; + Uint8 rgbReserved; + } biColors[256]; + /* Pixels: + Uint8 pixels[] + */ + /* Mask: + Uint8 mask[] + */ + } *icon_win32; + + /* Allocate the win32 bmp icon and set everything to zero */ + icon_pitch = ((icon->w+3)&~3); + mask_pitch = ((icon->w+7)/8); + icon_plen = icon->h*icon_pitch; + icon_mlen = icon->h*mask_pitch; + icon_len = sizeof(*icon_win32)+icon_plen+icon_mlen; + icon_win32 = (struct Win32Icon *)SDL_stack_alloc(Uint8, icon_len); + if ( icon_win32 == NULL ) { + return; + } + SDL_memset(icon_win32, 0, icon_len); + + /* Set the basic BMP parameters */ + icon_win32->biSize = sizeof(*icon_win32)-sizeof(icon_win32->biColors); + icon_win32->biWidth = icon->w; + icon_win32->biHeight = icon->h*2; + icon_win32->biPlanes = 1; + icon_win32->biBitCount = 8; + icon_win32->biSizeImage = icon_plen+icon_mlen; + + /* Allocate a standard 256 color icon surface */ + icon_256 = SDL_CreateRGBSurface(SDL_SWSURFACE, icon->w, icon->h, + icon_win32->biBitCount, 0, 0, 0, 0); + if ( icon_256 == NULL ) { + SDL_stack_free(icon_win32); + return; + } + pal_256 = icon_256->format->palette; + if (icon->format->palette && + (icon->format->BitsPerPixel == icon_256->format->BitsPerPixel)){ + Uint8 black; + SDL_memcpy(pal_256->colors, icon->format->palette->colors, + pal_256->ncolors*sizeof(SDL_Color)); + /* Make sure that 0 is black! */ + black = SDL_FindColor(pal_256, 0x00, 0x00, 0x00); + pal_256->colors[black] = pal_256->colors[0]; + pal_256->colors[0].r = 0x00; + pal_256->colors[0].g = 0x00; + pal_256->colors[0].b = 0x00; + } else { + SDL_DitherColors(pal_256->colors, + icon_256->format->BitsPerPixel); + } + + /* Now copy color data to the icon BMP */ + for ( i=0; i<(1<<icon_win32->biBitCount); ++i ) { + icon_win32->biColors[i].rgbRed = pal_256->colors[i].r; + icon_win32->biColors[i].rgbGreen = pal_256->colors[i].g; + icon_win32->biColors[i].rgbBlue = pal_256->colors[i].b; + } + + /* Convert icon to a standard surface format. This may not always + be necessary, as Windows supports a variety of BMP formats, but + it greatly simplifies our code. + */ + bounds.x = 0; + bounds.y = 0; + bounds.w = icon->w; + bounds.h = icon->h; + if ( SDL_LowerBlit(icon, &bounds, icon_256, &bounds) < 0 ) { + SDL_stack_free(icon_win32); + SDL_FreeSurface(icon_256); + return; + } + + /* Copy pixels upside-down to icon BMP, masked with the icon mask */ + if ( SDL_MUSTLOCK(icon_256) || (icon_256->pitch != icon_pitch) ) { + SDL_stack_free(icon_win32); + SDL_FreeSurface(icon_256); + SDL_SetError("Warning: Unexpected icon_256 characteristics"); + return; + } + pdata = (Uint8 *)icon_256->pixels; + mdata = mask; + pwin32 = (Uint8 *)icon_win32+sizeof(*icon_win32)+icon_plen-icon_pitch; + skip = icon_pitch - icon->w; + for ( row=0; row<icon->h; ++row ) { + for ( col=0; col<icon->w; ++col ) { + if ( (col%8) == 0 ) { + m = *mdata++; + } + if ( (m&0x80) != 0x00 ) { + *pwin32 = *pdata; + } + m <<= 1; + ++pdata; + ++pwin32; + } + pdata += skip; + pwin32 += skip; + pwin32 -= 2*icon_pitch; + } + SDL_FreeSurface(icon_256); + + /* Copy mask inverted and upside-down to icon BMP */ + mdata = mask; + mwin32 = (Uint8 *)icon_win32 + +sizeof(*icon_win32)+icon_plen+icon_mlen-mask_pitch; + for ( row=0; row<icon->h; ++row ) { + for ( col=0; col<mask_pitch; ++col ) { + *mwin32++ = ~*mdata++; + } + mwin32 -= 2*mask_pitch; + } + + /* Finally, create the icon handle and set the window icon */ + screen_icn = CreateIconFromResourceEx((Uint8 *)icon_win32, icon_len, + TRUE, 0x00030000, icon->w, icon->h, LR_DEFAULTCOLOR); + if ( screen_icn == NULL ) { + SDL_SetError("Couldn't create Win32 icon handle"); + } else { + SetClassLongPtr(SDL_Window, GCLP_HICON, (LONG_PTR)screen_icn); + } + SDL_stack_free(icon_win32); +#endif /* DISABLE_ICON_SUPPORT */ +} + +typedef BOOL (WINAPI *PtrSetWindowTextW)(HWND hWnd, LPCWSTR lpString); + +void WIN_SetWMCaption(_THIS, const char *title, const char *icon) +{ +#ifdef _WIN32_WCE + /* WinCE uses the UNICODE version */ + LPWSTR lpszW = SDL_iconv_utf8_ucs2((char *)title); + SetWindowText(SDL_Window, lpszW); + SDL_free(lpszW); +#else + Uint16 *lpsz = SDL_iconv_utf8_ucs2(title); + size_t len = WideCharToMultiByte(CP_ACP, 0, lpsz, -1, NULL, 0, NULL, NULL); + char *cvt = SDL_stack_alloc(char, len + 1); + WideCharToMultiByte(CP_ACP, 0, lpsz, -1, cvt, len, NULL, NULL); + SetWindowText(SDL_Window, cvt); + SDL_stack_free(cvt); + SDL_free(lpsz); +#endif +} + +int WIN_IconifyWindow(_THIS) +{ + ShowWindow(SDL_Window, SW_MINIMIZE); + return(1); +} + +SDL_GrabMode WIN_GrabInput(_THIS, SDL_GrabMode mode) +{ + if ( mode == SDL_GRAB_OFF ) { + ClipCursor(NULL); + if ( !(SDL_cursorstate & CURSOR_VISIBLE) ) { + /* RJR: March 28, 2000 + must be leaving relative mode, move mouse from + center of window to where it belongs ... */ + POINT pt; + int x, y; + SDL_GetMouseState(&x,&y); + pt.x = x; + pt.y = y; + ClientToScreen(SDL_Window, &pt); + SetCursorPos(pt.x,pt.y); + } +#ifdef _WIN32_WCE + AllKeys(0); +#endif + } else { + ClipCursor(&SDL_bounds); + if ( !(SDL_cursorstate & CURSOR_VISIBLE) ) { + /* RJR: March 28, 2000 + must be entering relative mode, get ready by + moving mouse to center of window ... */ + POINT pt; + pt.x = (SDL_VideoSurface->w/2); + pt.y = (SDL_VideoSurface->h/2); + ClientToScreen(SDL_Window, &pt); + SetCursorPos(pt.x, pt.y); + } +#ifdef _WIN32_WCE + AllKeys(1); +#endif + } + return(mode); +} + +/* If 'info' is the right version, this function fills it and returns 1. + Otherwise, in case of a version mismatch, it returns -1. +*/ +int WIN_GetWMInfo(_THIS, SDL_SysWMinfo *info) +{ + if ( info->version.major <= SDL_MAJOR_VERSION ) { + info->window = SDL_Window; + if ( SDL_VERSIONNUM(info->version.major, + info->version.minor, + info->version.patch) >= + SDL_VERSIONNUM(1, 2, 5) ) { +#if SDL_VIDEO_OPENGL + info->hglrc = GL_hrc; +#else + info->hglrc = NULL; +#endif + } + return(1); + } else { + SDL_SetError("Application not compiled with SDL %d.%d\n", + SDL_MAJOR_VERSION, SDL_MINOR_VERSION); + return(-1); + } +} diff --git a/3rdparty/SDL/src/video/wincommon/SDL_syswm_c.h b/3rdparty/SDL/src/video/wincommon/SDL_syswm_c.h new file mode 100644 index 0000000..a103b43 --- /dev/null +++ b/3rdparty/SDL/src/video/wincommon/SDL_syswm_c.h @@ -0,0 +1,35 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#include "SDL_lowvideo.h" + +/* Data that needs to be freed at SDL_SYS_VideoQuit() */ +extern HICON screen_icn; + +/* Functions to be exported */ +extern void WIN_SetWMIcon(_THIS, SDL_Surface *icon, Uint8 *mask); +extern void WIN_SetWMCaption(_THIS, const char *title, const char *icon); +extern int WIN_IconifyWindow(_THIS); +extern SDL_GrabMode WIN_GrabInput(_THIS, SDL_GrabMode mode); +extern int WIN_GetWMInfo(_THIS, SDL_SysWMinfo *info); + diff --git a/3rdparty/SDL/src/video/wincommon/SDL_wingl.c b/3rdparty/SDL/src/video/wincommon/SDL_wingl.c new file mode 100644 index 0000000..fc4e984 --- /dev/null +++ b/3rdparty/SDL/src/video/wincommon/SDL_wingl.c @@ -0,0 +1,659 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* WGL implementation of SDL OpenGL support */ + +#if SDL_VIDEO_OPENGL +#include "SDL_opengl.h" +#endif +#include "SDL_lowvideo.h" +#include "SDL_wingl_c.h" + +#if SDL_VIDEO_OPENGL +#define DEFAULT_GL_DRIVER_PATH "OPENGL32.DLL" +#endif + +/* If setting the HDC fails, we may need to recreate the window (MSDN) */ +static int WIN_GL_ResetWindow(_THIS) +{ + int status = 0; + +#ifndef _WIN32_WCE /* FIXME WinCE needs the UNICODE version of CreateWindow() */ + /* This doesn't work with DirectX code (see CVS comments) */ + /* If we were passed a window, then we can't create a new one */ + if ( !SDL_windowid && SDL_strcmp(this->name, "windib") == 0 ) { + /* Save the existing window attributes */ + LONG style; + RECT rect = { 0, 0, 0, 0 }; + style = GetWindowLong(SDL_Window, GWL_STYLE); + GetWindowRect(SDL_Window, &rect); + DestroyWindow(SDL_Window); + WIN_FlushMessageQueue(); + + SDL_resizing = 1; + SDL_Window = CreateWindow(SDL_Appname, SDL_Appname, + style, + rect.left, rect.top, + (rect.right-rect.left)+1, + (rect.bottom-rect.top)+1, + NULL, NULL, SDL_Instance, NULL); + WIN_FlushMessageQueue(); + SDL_resizing = 0; + + if ( SDL_Window ) { + this->SetCaption(this, this->wm_title, this->wm_icon); + } else { + SDL_SetError("Couldn't create window"); + status = -1; + } + } else +#endif /* !_WIN32_WCE */ + { + SDL_SetError("Unable to reset window for OpenGL context"); + status = -1; + } + return(status); +} + +#if SDL_VIDEO_OPENGL + +static int ExtensionSupported(const char *extension, const char *extensions) +{ + const char *start; + const char *where, *terminator; + + /* Extension names should not have spaces. */ + where = SDL_strchr(extension, ' '); + if ( where || *extension == '\0' ) + return 0; + + if ( ! extensions ) + return 0; + + /* It takes a bit of care to be fool-proof about parsing the + * OpenGL extensions string. Don't be fooled by sub-strings, + * etc. */ + + start = extensions; + + for (;;) + { + where = SDL_strstr(start, extension); + if (!where) break; + + terminator = where + SDL_strlen(extension); + if (where == start || *(where - 1) == ' ') + if (*terminator == ' ' || *terminator == '\0') return 1; + + start = terminator; + } + + return 0; +} + +static int ChoosePixelFormatARB(_THIS, const int *iAttribs, const FLOAT *fAttribs) +{ + HWND hwnd; + HDC hdc; + HGLRC hglrc; + const char * (WINAPI *wglGetExtensionsStringARB)(HDC) = 0; + const char *extensions; + int pformat = 0; + UINT matches = 0; + + hwnd = CreateWindow(SDL_Appname, SDL_Appname, WS_POPUP | WS_DISABLED, + 0, 0, 10, 10, + NULL, NULL, SDL_Instance, NULL); + WIN_FlushMessageQueue(); + + hdc = GetDC(hwnd); + + SetPixelFormat(hdc, ChoosePixelFormat(hdc, &GL_pfd), &GL_pfd); + + hglrc = this->gl_data->wglCreateContext(hdc); + if ( hglrc ) { + this->gl_data->wglMakeCurrent(hdc, hglrc); + } + + wglGetExtensionsStringARB = (const char * (WINAPI *)(HDC)) + this->gl_data->wglGetProcAddress("wglGetExtensionsStringARB"); + + if( wglGetExtensionsStringARB ) { + extensions = wglGetExtensionsStringARB(hdc); + } else { + extensions = NULL; + } + + this->gl_data->WGL_ARB_pixel_format = 0; + if( ExtensionSupported("WGL_ARB_pixel_format", extensions) ) { + BOOL (WINAPI *wglChoosePixelFormatARB)(HDC hdc, const int *piAttribIList, const FLOAT *pfAttribFList, UINT nMaxFormats, int *piFormats, UINT *nNumFormats); + wglChoosePixelFormatARB = + (BOOL (WINAPI *)(HDC, const int *, const FLOAT *, UINT, int *, UINT *)) + this->gl_data->wglGetProcAddress("wglChoosePixelFormatARB"); + if( wglChoosePixelFormatARB && + wglChoosePixelFormatARB(hdc, iAttribs, fAttribs, 1, &pformat, &matches) && pformat ) { + this->gl_data->WGL_ARB_pixel_format = 1; + } + } + + if ( hglrc ) { + this->gl_data->wglMakeCurrent(NULL, NULL); + this->gl_data->wglDeleteContext(hglrc); + } + ReleaseDC(hwnd, hdc); + DestroyWindow(hwnd); + WIN_FlushMessageQueue(); + + return pformat; +} + +#endif /* SDL_VIDEO_OPENGL */ + +int WIN_GL_SetupWindow(_THIS) +{ + int retval; +#if SDL_VIDEO_OPENGL + int i; + int iAttribs[64]; + int *iAttr; + int *iAccelAttr = NULL; + float fAttribs[1] = { 0 }; + const GLubyte *(WINAPI *glGetStringFunc)(GLenum); + const char *wglext; + + /* load the gl driver from a default path */ + if ( ! this->gl_config.driver_loaded ) { + /* no driver has been loaded, use default (ourselves) */ + if ( WIN_GL_LoadLibrary(this, NULL) < 0 ) { + return(-1); + } + } + + /* Set up the pixel format descriptor with our needed format */ + SDL_memset(&GL_pfd, 0, sizeof(GL_pfd)); + GL_pfd.nSize = sizeof(GL_pfd); + GL_pfd.nVersion = 1; + GL_pfd.dwFlags = (PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL); + if ( this->gl_config.double_buffer ) { + GL_pfd.dwFlags |= PFD_DOUBLEBUFFER; + } + if ( this->gl_config.stereo ) { + GL_pfd.dwFlags |= PFD_STEREO; + } + GL_pfd.iPixelType = PFD_TYPE_RGBA; + GL_pfd.cColorBits = this->gl_config.buffer_size; + GL_pfd.cRedBits = this->gl_config.red_size; + GL_pfd.cGreenBits = this->gl_config.green_size; + GL_pfd.cBlueBits = this->gl_config.blue_size; + GL_pfd.cAlphaBits = this->gl_config.alpha_size; + GL_pfd.cAccumRedBits = this->gl_config.accum_red_size; + GL_pfd.cAccumGreenBits = this->gl_config.accum_green_size; + GL_pfd.cAccumBlueBits = this->gl_config.accum_blue_size; + GL_pfd.cAccumAlphaBits = this->gl_config.accum_alpha_size; + GL_pfd.cAccumBits = + (GL_pfd.cAccumRedBits + GL_pfd.cAccumGreenBits + + GL_pfd.cAccumBlueBits + GL_pfd.cAccumAlphaBits); + GL_pfd.cDepthBits = this->gl_config.depth_size; + GL_pfd.cStencilBits = this->gl_config.stencil_size; + + /* setup WGL_ARB_pixel_format attribs */ + iAttr = &iAttribs[0]; + + *iAttr++ = WGL_DRAW_TO_WINDOW_ARB; + *iAttr++ = GL_TRUE; + *iAttr++ = WGL_RED_BITS_ARB; + *iAttr++ = this->gl_config.red_size; + *iAttr++ = WGL_GREEN_BITS_ARB; + *iAttr++ = this->gl_config.green_size; + *iAttr++ = WGL_BLUE_BITS_ARB; + *iAttr++ = this->gl_config.blue_size; + + /* We always choose either FULL or NO accel on Windows, because of flaky + drivers. If the app didn't specify, we use FULL, because that's + probably what they wanted (and if you didn't care and got FULL, that's + a perfectly valid result in any case. */ + *iAttr++ = WGL_ACCELERATION_ARB; + iAccelAttr = iAttr; + if (this->gl_config.accelerated) { + *iAttr++ = WGL_FULL_ACCELERATION_ARB; + } else { + *iAttr++ = WGL_NO_ACCELERATION_ARB; + } + + if ( this->gl_config.alpha_size ) { + *iAttr++ = WGL_ALPHA_BITS_ARB; + *iAttr++ = this->gl_config.alpha_size; + } + + *iAttr++ = WGL_DOUBLE_BUFFER_ARB; + *iAttr++ = this->gl_config.double_buffer; + + *iAttr++ = WGL_DEPTH_BITS_ARB; + *iAttr++ = this->gl_config.depth_size; + + if ( this->gl_config.stencil_size ) { + *iAttr++ = WGL_STENCIL_BITS_ARB; + *iAttr++ = this->gl_config.stencil_size; + } + + if ( this->gl_config.accum_red_size ) { + *iAttr++ = WGL_ACCUM_RED_BITS_ARB; + *iAttr++ = this->gl_config.accum_red_size; + } + + if ( this->gl_config.accum_green_size ) { + *iAttr++ = WGL_ACCUM_GREEN_BITS_ARB; + *iAttr++ = this->gl_config.accum_green_size; + } + + if ( this->gl_config.accum_blue_size ) { + *iAttr++ = WGL_ACCUM_BLUE_BITS_ARB; + *iAttr++ = this->gl_config.accum_blue_size; + } + + if ( this->gl_config.accum_alpha_size ) { + *iAttr++ = WGL_ACCUM_ALPHA_BITS_ARB; + *iAttr++ = this->gl_config.accum_alpha_size; + } + + if ( this->gl_config.stereo ) { + *iAttr++ = WGL_STEREO_ARB; + *iAttr++ = GL_TRUE; + } + + if ( this->gl_config.multisamplebuffers ) { + *iAttr++ = WGL_SAMPLE_BUFFERS_ARB; + *iAttr++ = this->gl_config.multisamplebuffers; + } + + if ( this->gl_config.multisamplesamples ) { + *iAttr++ = WGL_SAMPLES_ARB; + *iAttr++ = this->gl_config.multisamplesamples; + } + + *iAttr = 0; + + for ( i=0; ; ++i ) { + /* Get the window device context for our OpenGL drawing */ + GL_hdc = GetDC(SDL_Window); + if ( GL_hdc == NULL ) { + SDL_SetError("Unable to get DC for SDL_Window"); + return(-1); + } + + /* Choose and set the closest available pixel format */ + pixel_format = ChoosePixelFormatARB(this, iAttribs, fAttribs); + /* App said "don't care about accel" and FULL accel failed. Try NO. */ + if ( ( !pixel_format ) && ( this->gl_config.accelerated < 0 ) ) { + *iAccelAttr = WGL_NO_ACCELERATION_ARB; + pixel_format = ChoosePixelFormatARB(this, iAttribs, fAttribs); + *iAccelAttr = WGL_FULL_ACCELERATION_ARB; /* if we try again. */ + } + if ( !pixel_format ) { + pixel_format = ChoosePixelFormat(GL_hdc, &GL_pfd); + } + if ( !pixel_format ) { + SDL_SetError("No matching GL pixel format available"); + return(-1); + } + if ( !SetPixelFormat(GL_hdc, pixel_format, &GL_pfd) ) { + if ( i == 0 ) { + /* First time through, try resetting the window */ + if ( WIN_GL_ResetWindow(this) < 0 ) { + return(-1); + } + continue; + } + SDL_SetError("Unable to set HDC pixel format"); + return(-1); + } + /* We either succeeded or failed by this point */ + break; + } + DescribePixelFormat(GL_hdc, pixel_format, sizeof(GL_pfd), &GL_pfd); + + GL_hrc = this->gl_data->wglCreateContext(GL_hdc); + if ( GL_hrc == NULL ) { + SDL_SetError("Unable to create GL context"); + return(-1); + } + if ( WIN_GL_MakeCurrent(this) < 0 ) { + return(-1); + } + gl_active = 1; + + /* Get the wglGetPixelFormatAttribivARB pointer for the context */ + if ( this->gl_data->WGL_ARB_pixel_format ) { + this->gl_data->wglGetPixelFormatAttribivARB = + (BOOL (WINAPI *)(HDC, int, int, UINT, const int *, int *)) + this->gl_data->wglGetProcAddress("wglGetPixelFormatAttribivARB"); + } else { + this->gl_data->wglGetPixelFormatAttribivARB = NULL; + } + + /* Vsync control under Windows. Checking glGetString here is + * somewhat a documented and reliable hack - it was originally + * as a feature added by mistake, but since so many people rely + * on it, it will not be removed. strstr should be safe here.*/ + glGetStringFunc = WIN_GL_GetProcAddress(this, "glGetString"); + if ( glGetStringFunc ) { + wglext = (const char *)glGetStringFunc(GL_EXTENSIONS); + } else { + /* Uh oh, something is seriously wrong here... */ + wglext = NULL; + } + if ( wglext && SDL_strstr(wglext, "WGL_EXT_swap_control") ) { + this->gl_data->wglSwapIntervalEXT = WIN_GL_GetProcAddress(this, "wglSwapIntervalEXT"); + this->gl_data->wglGetSwapIntervalEXT = WIN_GL_GetProcAddress(this, "wglGetSwapIntervalEXT"); + } else { + this->gl_data->wglSwapIntervalEXT = NULL; + this->gl_data->wglGetSwapIntervalEXT = NULL; + } + if ( this->gl_config.swap_control >= 0 ) { + if ( this->gl_data->wglSwapIntervalEXT ) { + this->gl_data->wglSwapIntervalEXT(this->gl_config.swap_control); + } + } +#else + SDL_SetError("WIN driver not configured with OpenGL"); +#endif + if ( gl_active ) { + retval = 0; + } else { + retval = -1; + } + return(retval); +} + +void WIN_GL_ShutDown(_THIS) +{ +#if SDL_VIDEO_OPENGL + /* Clean up OpenGL */ + if ( GL_hrc ) { + this->gl_data->wglMakeCurrent(NULL, NULL); + this->gl_data->wglDeleteContext(GL_hrc); + GL_hrc = NULL; + } + if ( GL_hdc ) { + ReleaseDC(SDL_Window, GL_hdc); + GL_hdc = NULL; + } + gl_active = 0; + + WIN_GL_UnloadLibrary(this); +#endif /* SDL_VIDEO_OPENGL */ +} + +#if SDL_VIDEO_OPENGL + +/* Make the current context active */ +int WIN_GL_MakeCurrent(_THIS) +{ + int retval; + + retval = 0; + if ( ! this->gl_data->wglMakeCurrent(GL_hdc, GL_hrc) ) { + SDL_SetError("Unable to make GL context current"); + retval = -1; + } + return(retval); +} + +/* Get attribute data from wgl. */ +int WIN_GL_GetAttribute(_THIS, SDL_GLattr attrib, int* value) +{ + int retval; + + if (attrib == SDL_GL_SWAP_CONTROL) { + if ( this->gl_data->wglGetSwapIntervalEXT ) { + *value = this->gl_data->wglGetSwapIntervalEXT(); + return 0; + } + return -1; + } + + if ( this->gl_data->wglGetPixelFormatAttribivARB ) { + int wgl_attrib; + + switch(attrib) { + case SDL_GL_RED_SIZE: + wgl_attrib = WGL_RED_BITS_ARB; + break; + case SDL_GL_GREEN_SIZE: + wgl_attrib = WGL_GREEN_BITS_ARB; + break; + case SDL_GL_BLUE_SIZE: + wgl_attrib = WGL_BLUE_BITS_ARB; + break; + case SDL_GL_ALPHA_SIZE: + wgl_attrib = WGL_ALPHA_BITS_ARB; + break; + case SDL_GL_DOUBLEBUFFER: + wgl_attrib = WGL_DOUBLE_BUFFER_ARB; + break; + case SDL_GL_BUFFER_SIZE: + wgl_attrib = WGL_COLOR_BITS_ARB; + break; + case SDL_GL_DEPTH_SIZE: + wgl_attrib = WGL_DEPTH_BITS_ARB; + break; + case SDL_GL_STENCIL_SIZE: + wgl_attrib = WGL_STENCIL_BITS_ARB; + break; + case SDL_GL_ACCUM_RED_SIZE: + wgl_attrib = WGL_ACCUM_RED_BITS_ARB; + break; + case SDL_GL_ACCUM_GREEN_SIZE: + wgl_attrib = WGL_ACCUM_GREEN_BITS_ARB; + break; + case SDL_GL_ACCUM_BLUE_SIZE: + wgl_attrib = WGL_ACCUM_BLUE_BITS_ARB; + break; + case SDL_GL_ACCUM_ALPHA_SIZE: + wgl_attrib = WGL_ACCUM_ALPHA_BITS_ARB; + break; + case SDL_GL_STEREO: + wgl_attrib = WGL_STEREO_ARB; + break; + case SDL_GL_MULTISAMPLEBUFFERS: + wgl_attrib = WGL_SAMPLE_BUFFERS_ARB; + break; + case SDL_GL_MULTISAMPLESAMPLES: + wgl_attrib = WGL_SAMPLES_ARB; + break; + case SDL_GL_ACCELERATED_VISUAL: + wgl_attrib = WGL_ACCELERATION_ARB; + this->gl_data->wglGetPixelFormatAttribivARB(GL_hdc, pixel_format, 0, 1, &wgl_attrib, value); + if ( *value == WGL_NO_ACCELERATION_ARB ) { + *value = SDL_FALSE; + } else { + *value = SDL_TRUE; + } + return 0; + default: + return(-1); + } + this->gl_data->wglGetPixelFormatAttribivARB(GL_hdc, pixel_format, 0, 1, &wgl_attrib, value); + + return 0; + } + + retval = 0; + switch ( attrib ) { + case SDL_GL_RED_SIZE: + *value = GL_pfd.cRedBits; + break; + case SDL_GL_GREEN_SIZE: + *value = GL_pfd.cGreenBits; + break; + case SDL_GL_BLUE_SIZE: + *value = GL_pfd.cBlueBits; + break; + case SDL_GL_ALPHA_SIZE: + *value = GL_pfd.cAlphaBits; + break; + case SDL_GL_DOUBLEBUFFER: + if ( GL_pfd.dwFlags & PFD_DOUBLEBUFFER ) { + *value = 1; + } else { + *value = 0; + } + break; + case SDL_GL_BUFFER_SIZE: + *value = GL_pfd.cColorBits; + break; + case SDL_GL_DEPTH_SIZE: + *value = GL_pfd.cDepthBits; + break; + case SDL_GL_STENCIL_SIZE: + *value = GL_pfd.cStencilBits; + break; + case SDL_GL_ACCUM_RED_SIZE: + *value = GL_pfd.cAccumRedBits; + break; + case SDL_GL_ACCUM_GREEN_SIZE: + *value = GL_pfd.cAccumGreenBits; + break; + case SDL_GL_ACCUM_BLUE_SIZE: + *value = GL_pfd.cAccumBlueBits; + break; + case SDL_GL_ACCUM_ALPHA_SIZE: + *value = GL_pfd.cAccumAlphaBits; + break; + case SDL_GL_STEREO: + if ( GL_pfd.dwFlags & PFD_STEREO ) { + *value = 1; + } else { + *value = 0; + } + break; + case SDL_GL_MULTISAMPLEBUFFERS: + *value = 0; + break; + case SDL_GL_MULTISAMPLESAMPLES: + *value = 1; + break; + case SDL_GL_SWAP_CONTROL: + if ( this->gl_data->wglGetSwapIntervalEXT ) { + *value = this->gl_data->wglGetSwapIntervalEXT(); + return 0; + } else { + return -1; + } + break; + default: + retval = -1; + break; + } + return retval; +} + +void WIN_GL_SwapBuffers(_THIS) +{ + SwapBuffers(GL_hdc); +} + +void WIN_GL_UnloadLibrary(_THIS) +{ + if ( this->gl_config.driver_loaded ) { + FreeLibrary((HMODULE)this->gl_config.dll_handle); + + this->gl_data->wglGetProcAddress = NULL; + this->gl_data->wglCreateContext = NULL; + this->gl_data->wglDeleteContext = NULL; + this->gl_data->wglMakeCurrent = NULL; + this->gl_data->wglGetPixelFormatAttribivARB = NULL; + this->gl_data->wglSwapIntervalEXT = NULL; + this->gl_data->wglGetSwapIntervalEXT = NULL; + + this->gl_config.dll_handle = NULL; + this->gl_config.driver_loaded = 0; + } +} + +/* Passing a NULL path means load pointers from the application */ +int WIN_GL_LoadLibrary(_THIS, const char* path) +{ + HMODULE handle; + + if ( gl_active ) { + SDL_SetError("OpenGL context already created"); + return -1; + } + + if ( path == NULL ) { + path = DEFAULT_GL_DRIVER_PATH; + } + handle = LoadLibrary(path); + if ( handle == NULL ) { + SDL_SetError("Could not load OpenGL library"); + return -1; + } + + /* Unload the old driver and reset the pointers */ + WIN_GL_UnloadLibrary(this); + + /* Load new function pointers */ + SDL_memset(this->gl_data, 0, sizeof(*this->gl_data)); + this->gl_data->wglGetProcAddress = (void * (WINAPI *)(const char *)) + GetProcAddress(handle, "wglGetProcAddress"); + this->gl_data->wglCreateContext = (HGLRC (WINAPI *)(HDC)) + GetProcAddress(handle, "wglCreateContext"); + this->gl_data->wglDeleteContext = (BOOL (WINAPI *)(HGLRC)) + GetProcAddress(handle, "wglDeleteContext"); + this->gl_data->wglMakeCurrent = (BOOL (WINAPI *)(HDC, HGLRC)) + GetProcAddress(handle, "wglMakeCurrent"); + this->gl_data->wglSwapIntervalEXT = (void (WINAPI *)(int)) + GetProcAddress(handle, "wglSwapIntervalEXT"); + this->gl_data->wglGetSwapIntervalEXT = (int (WINAPI *)(void)) + GetProcAddress(handle, "wglGetSwapIntervalEXT"); + + if ( (this->gl_data->wglGetProcAddress == NULL) || + (this->gl_data->wglCreateContext == NULL) || + (this->gl_data->wglDeleteContext == NULL) || + (this->gl_data->wglMakeCurrent == NULL) ) { + SDL_SetError("Could not retrieve OpenGL functions"); + FreeLibrary(handle); + return -1; + } + + this->gl_config.dll_handle = handle; + SDL_strlcpy(this->gl_config.driver_path, path, SDL_arraysize(this->gl_config.driver_path)); + this->gl_config.driver_loaded = 1; + return 0; +} + +void *WIN_GL_GetProcAddress(_THIS, const char* proc) +{ + void *func; + + /* This is to pick up extensions */ + func = this->gl_data->wglGetProcAddress(proc); + if ( ! func ) { + /* This is probably a normal GL function */ + func = GetProcAddress(this->gl_config.dll_handle, proc); + } + return func; +} + +#endif /* SDL_VIDEO_OPENGL */ diff --git a/3rdparty/SDL/src/video/wincommon/SDL_wingl_c.h b/3rdparty/SDL/src/video/wincommon/SDL_wingl_c.h new file mode 100644 index 0000000..c3f2291 --- /dev/null +++ b/3rdparty/SDL/src/video/wincommon/SDL_wingl_c.h @@ -0,0 +1,135 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* WGL implementation of SDL OpenGL support */ + +#include "../SDL_sysvideo.h" + + +struct SDL_PrivateGLData { + int gl_active; /* to stop switching drivers while we have a valid context */ + +#if SDL_VIDEO_OPENGL + PIXELFORMATDESCRIPTOR GL_pfd; + HDC GL_hdc; + HGLRC GL_hrc; + int pixel_format; + int WGL_ARB_pixel_format; + + void * (WINAPI *wglGetProcAddress)(const char *proc); + + HGLRC (WINAPI *wglCreateContext)(HDC hdc); + + BOOL (WINAPI *wglDeleteContext)(HGLRC hglrc); + + BOOL (WINAPI *wglMakeCurrent)(HDC hdc, HGLRC hglrc); + + BOOL (WINAPI *wglGetPixelFormatAttribivARB)(HDC hdc, int iPixelFormat, + int iLayerPlane, + UINT nAttributes, + const int *piAttributes, + int *piValues); + void (WINAPI *wglSwapIntervalEXT)(int interval); + int (WINAPI *wglGetSwapIntervalEXT)(void); +#endif /* SDL_VIDEO_OPENGL */ +}; + +/* Old variable names */ +#define gl_active (this->gl_data->gl_active) +#define GL_pfd (this->gl_data->GL_pfd) +#define GL_hdc (this->gl_data->GL_hdc) +#define GL_hrc (this->gl_data->GL_hrc) +#define pixel_format (this->gl_data->pixel_format) + +/* OpenGL functions */ +extern int WIN_GL_SetupWindow(_THIS); +extern void WIN_GL_ShutDown(_THIS); +#if SDL_VIDEO_OPENGL +extern int WIN_GL_MakeCurrent(_THIS); +extern int WIN_GL_GetAttribute(_THIS, SDL_GLattr attrib, int* value); +extern void WIN_GL_SwapBuffers(_THIS); +extern void WIN_GL_UnloadLibrary(_THIS); +extern int WIN_GL_LoadLibrary(_THIS, const char* path); +extern void *WIN_GL_GetProcAddress(_THIS, const char* proc); +#endif + +#if SDL_VIDEO_OPENGL + +#ifndef WGL_ARB_pixel_format +#define WGL_NUMBER_PIXEL_FORMATS_ARB 0x2000 +#define WGL_DRAW_TO_WINDOW_ARB 0x2001 +#define WGL_DRAW_TO_BITMAP_ARB 0x2002 +#define WGL_ACCELERATION_ARB 0x2003 +#define WGL_NEED_PALETTE_ARB 0x2004 +#define WGL_NEED_SYSTEM_PALETTE_ARB 0x2005 +#define WGL_SWAP_LAYER_BUFFERS_ARB 0x2006 +#define WGL_SWAP_METHOD_ARB 0x2007 +#define WGL_NUMBER_OVERLAYS_ARB 0x2008 +#define WGL_NUMBER_UNDERLAYS_ARB 0x2009 +#define WGL_TRANSPARENT_ARB 0x200A +#define WGL_TRANSPARENT_RED_VALUE_ARB 0x2037 +#define WGL_TRANSPARENT_GREEN_VALUE_ARB 0x2038 +#define WGL_TRANSPARENT_BLUE_VALUE_ARB 0x2039 +#define WGL_TRANSPARENT_ALPHA_VALUE_ARB 0x203A +#define WGL_TRANSPARENT_INDEX_VALUE_ARB 0x203B +#define WGL_SHARE_DEPTH_ARB 0x200C +#define WGL_SHARE_STENCIL_ARB 0x200D +#define WGL_SHARE_ACCUM_ARB 0x200E +#define WGL_SUPPORT_GDI_ARB 0x200F +#define WGL_SUPPORT_OPENGL_ARB 0x2010 +#define WGL_DOUBLE_BUFFER_ARB 0x2011 +#define WGL_STEREO_ARB 0x2012 +#define WGL_PIXEL_TYPE_ARB 0x2013 +#define WGL_COLOR_BITS_ARB 0x2014 +#define WGL_RED_BITS_ARB 0x2015 +#define WGL_RED_SHIFT_ARB 0x2016 +#define WGL_GREEN_BITS_ARB 0x2017 +#define WGL_GREEN_SHIFT_ARB 0x2018 +#define WGL_BLUE_BITS_ARB 0x2019 +#define WGL_BLUE_SHIFT_ARB 0x201A +#define WGL_ALPHA_BITS_ARB 0x201B +#define WGL_ALPHA_SHIFT_ARB 0x201C +#define WGL_ACCUM_BITS_ARB 0x201D +#define WGL_ACCUM_RED_BITS_ARB 0x201E +#define WGL_ACCUM_GREEN_BITS_ARB 0x201F +#define WGL_ACCUM_BLUE_BITS_ARB 0x2020 +#define WGL_ACCUM_ALPHA_BITS_ARB 0x2021 +#define WGL_DEPTH_BITS_ARB 0x2022 +#define WGL_STENCIL_BITS_ARB 0x2023 +#define WGL_AUX_BUFFERS_ARB 0x2024 +#define WGL_NO_ACCELERATION_ARB 0x2025 +#define WGL_GENERIC_ACCELERATION_ARB 0x2026 +#define WGL_FULL_ACCELERATION_ARB 0x2027 +#define WGL_SWAP_EXCHANGE_ARB 0x2028 +#define WGL_SWAP_COPY_ARB 0x2029 +#define WGL_SWAP_UNDEFINED_ARB 0x202A +#define WGL_TYPE_RGBA_ARB 0x202B +#define WGL_TYPE_COLORINDEX_ARB 0x202C +#endif + +#ifndef WGL_ARB_multisample +#define WGL_SAMPLE_BUFFERS_ARB 0x2041 +#define WGL_SAMPLES_ARB 0x2042 +#endif + +#endif diff --git a/3rdparty/SDL/src/video/wincommon/wmmsg.h b/3rdparty/SDL/src/video/wincommon/wmmsg.h new file mode 100644 index 0000000..175a8ce --- /dev/null +++ b/3rdparty/SDL/src/video/wincommon/wmmsg.h @@ -0,0 +1,1030 @@ + +#define MAX_WMMSG (sizeof(wmtab)/sizeof(wmtab[0])) + +char *wmtab[] = { + "WM_NULL", + "WM_CREATE", + "WM_DESTROY", + "WM_MOVE", + "UNKNOWN (4)", + "WM_SIZE", + "WM_ACTIVATE", + "WM_SETFOCUS", + "WM_KILLFOCUS", + "UNKNOWN (9)", + "WM_ENABLE", + "WM_SETREDRAW", + "WM_SETTEXT", + "WM_GETTEXT", + "WM_GETTEXTLENGTH", + "WM_PAINT", + "WM_CLOSE", + "WM_QUERYENDSESSION", + "WM_QUIT", + "WM_QUERYOPEN", + "WM_ERASEBKGND", + "WM_SYSCOLORCHANGE", + "WM_ENDSESSION", + "UNKNOWN (23)", + "WM_SHOWWINDOW", + "UNKNOWN (25)", + "WM_SETTINGCHANGE", + "WM_DEVMODECHANGE", + "WM_ACTIVATEAPP", + "WM_FONTCHANGE", + "WM_TIMECHANGE", + "WM_CANCELMODE", + "WM_SETCURSOR", + "WM_MOUSEACTIVATE", + "WM_CHILDACTIVATE", + "WM_QUEUESYNC", + "WM_GETMINMAXINFO", + "UNKNOWN (37)", + "WM_PAINTICON", + "WM_ICONERASEBKGND", + "WM_NEXTDLGCTL", + "UNKNOWN (41)", + "WM_SPOOLERSTATUS", + "WM_DRAWITEM", + "WM_MEASUREITEM", + "WM_DELETEITEM", + "WM_VKEYTOITEM", + "WM_CHARTOITEM", + "WM_SETFONT", + "WM_GETFONT", + "WM_SETHOTKEY", + "WM_GETHOTKEY", + "UNKNOWN (52)", + "UNKNOWN (53)", + "UNKNOWN (54)", + "WM_QUERYDRAGICON", + "UNKNOWN (56)", + "WM_COMPAREITEM", + "UNKNOWN (58)", + "UNKNOWN (59)", + "UNKNOWN (60)", + "WM_GETOBJECT", + "UNKNOWN (62)", + "UNKNOWN (63)", + "UNKNOWN (64)", + "WM_COMPACTING", + "UNKNOWN (66)", + "UNKNOWN (67)", + "WM_COMMNOTIFY", + "UNKNOWN (69)", + "WM_WINDOWPOSCHANGING", + "WM_WINDOWPOSCHANGED", + "WM_POWER", + "UNKNOWN (73)", + "WM_COPYDATA", + "WM_CANCELJOURNAL", + "UNKNOWN (76)", + "UNKNOWN (77)", + "WM_NOTIFY", + "UNKNOWN (79)", + "WM_INPUTLANGCHANGEREQUEST", + "WM_INPUTLANGCHANGE", + "WM_TCARD", + "WM_HELP", + "WM_USERCHANGED", + "WM_NOTIFYFORMAT", + "UNKNOWN (86)", + "UNKNOWN (87)", + "UNKNOWN (88)", + "UNKNOWN (89)", + "UNKNOWN (90)", + "UNKNOWN (91)", + "UNKNOWN (92)", + "UNKNOWN (93)", + "UNKNOWN (94)", + "UNKNOWN (95)", + "UNKNOWN (96)", + "UNKNOWN (97)", + "UNKNOWN (98)", + "UNKNOWN (99)", + "UNKNOWN (100)", + "UNKNOWN (101)", + "UNKNOWN (102)", + "UNKNOWN (103)", + "UNKNOWN (104)", + "UNKNOWN (105)", + "UNKNOWN (106)", + "UNKNOWN (107)", + "UNKNOWN (108)", + "UNKNOWN (109)", + "UNKNOWN (110)", + "UNKNOWN (111)", + "UNKNOWN (112)", + "UNKNOWN (113)", + "UNKNOWN (114)", + "UNKNOWN (115)", + "UNKNOWN (116)", + "UNKNOWN (117)", + "UNKNOWN (118)", + "UNKNOWN (119)", + "UNKNOWN (120)", + "UNKNOWN (121)", + "UNKNOWN (122)", + "WM_CONTEXTMENU", + "WM_STYLECHANGING", + "WM_STYLECHANGED", + "WM_DISPLAYCHANGE", + "WM_GETICON", + "WM_SETICON", + "WM_NCCREATE", + "WM_NCDESTROY", + "WM_NCCALCSIZE", + "WM_NCHITTEST", + "WM_NCPAINT", + "WM_NCACTIVATE", + "WM_GETDLGCODE", + "WM_SYNCPAINT", + "UNKNOWN (137)", + "UNKNOWN (138)", + "UNKNOWN (139)", + "UNKNOWN (140)", + "UNKNOWN (141)", + "UNKNOWN (142)", + "UNKNOWN (143)", + "UNKNOWN (144)", + "UNKNOWN (145)", + "UNKNOWN (146)", + "UNKNOWN (147)", + "UNKNOWN (148)", + "UNKNOWN (149)", + "UNKNOWN (150)", + "UNKNOWN (151)", + "UNKNOWN (152)", + "UNKNOWN (153)", + "UNKNOWN (154)", + "UNKNOWN (155)", + "UNKNOWN (156)", + "UNKNOWN (157)", + "UNKNOWN (158)", + "UNKNOWN (159)", + "WM_NCMOUSEMOVE", + "WM_NCLBUTTONDOWN", + "WM_NCLBUTTONUP", + "WM_NCLBUTTONDBLCLK", + "WM_NCRBUTTONDOWN", + "WM_NCRBUTTONUP", + "WM_NCRBUTTONDBLCLK", + "WM_NCMBUTTONDOWN", + "WM_NCMBUTTONUP", + "WM_NCMBUTTONDBLCLK", + "UNKNOWN (170)", + "UNKNOWN (171)", + "UNKNOWN (172)", + "UNKNOWN (173)", + "UNKNOWN (174)", + "UNKNOWN (175)", + "UNKNOWN (176)", + "UNKNOWN (177)", + "UNKNOWN (178)", + "UNKNOWN (179)", + "UNKNOWN (180)", + "UNKNOWN (181)", + "UNKNOWN (182)", + "UNKNOWN (183)", + "UNKNOWN (184)", + "UNKNOWN (185)", + "UNKNOWN (186)", + "UNKNOWN (187)", + "UNKNOWN (188)", + "UNKNOWN (189)", + "UNKNOWN (190)", + "UNKNOWN (191)", + "UNKNOWN (192)", + "UNKNOWN (193)", + "UNKNOWN (194)", + "UNKNOWN (195)", + "UNKNOWN (196)", + "UNKNOWN (197)", + "UNKNOWN (198)", + "UNKNOWN (199)", + "UNKNOWN (200)", + "UNKNOWN (201)", + "UNKNOWN (202)", + "UNKNOWN (203)", + "UNKNOWN (204)", + "UNKNOWN (205)", + "UNKNOWN (206)", + "UNKNOWN (207)", + "UNKNOWN (208)", + "UNKNOWN (209)", + "UNKNOWN (210)", + "UNKNOWN (211)", + "UNKNOWN (212)", + "UNKNOWN (213)", + "UNKNOWN (214)", + "UNKNOWN (215)", + "UNKNOWN (216)", + "UNKNOWN (217)", + "UNKNOWN (218)", + "UNKNOWN (219)", + "UNKNOWN (220)", + "UNKNOWN (221)", + "UNKNOWN (222)", + "UNKNOWN (223)", + "UNKNOWN (224)", + "UNKNOWN (225)", + "UNKNOWN (226)", + "UNKNOWN (227)", + "UNKNOWN (228)", + "UNKNOWN (229)", + "UNKNOWN (230)", + "UNKNOWN (231)", + "UNKNOWN (232)", + "UNKNOWN (233)", + "UNKNOWN (234)", + "UNKNOWN (235)", + "UNKNOWN (236)", + "UNKNOWN (237)", + "UNKNOWN (238)", + "UNKNOWN (239)", + "UNKNOWN (240)", + "UNKNOWN (241)", + "UNKNOWN (242)", + "UNKNOWN (243)", + "UNKNOWN (244)", + "UNKNOWN (245)", + "UNKNOWN (246)", + "UNKNOWN (247)", + "UNKNOWN (248)", + "UNKNOWN (249)", + "UNKNOWN (250)", + "UNKNOWN (251)", + "UNKNOWN (252)", + "UNKNOWN (253)", + "UNKNOWN (254)", + "UNKNOWN (255)", + "WM_KEYDOWN", + "WM_KEYUP", + "WM_CHAR", + "WM_DEADCHAR", + "WM_SYSKEYDOWN", + "WM_SYSKEYUP", + "WM_SYSCHAR", + "WM_SYSDEADCHAR", + "WM_KEYLAST", + "UNKNOWN (265)", + "UNKNOWN (266)", + "UNKNOWN (267)", + "UNKNOWN (268)", + "UNKNOWN (269)", + "UNKNOWN (270)", + "UNKNOWN (271)", + "WM_INITDIALOG", + "WM_COMMAND", + "WM_SYSCOMMAND", + "WM_TIMER", + "WM_HSCROLL", + "WM_VSCROLL", + "WM_INITMENU", + "WM_INITMENUPOPUP", + "UNKNOWN (280)", + "UNKNOWN (281)", + "UNKNOWN (282)", + "UNKNOWN (283)", + "UNKNOWN (284)", + "UNKNOWN (285)", + "UNKNOWN (286)", + "WM_MENUSELECT", + "WM_MENUCHAR", + "WM_ENTERIDLE", + "WM_MENURBUTTONUP", + "WM_MENUDRAG", + "WM_MENUGETOBJECT", + "WM_UNINITMENUPOPUP", + "WM_MENUCOMMAND", + "UNKNOWN (295)", + "UNKNOWN (296)", + "UNKNOWN (297)", + "UNKNOWN (298)", + "UNKNOWN (299)", + "UNKNOWN (300)", + "UNKNOWN (301)", + "UNKNOWN (302)", + "UNKNOWN (303)", + "UNKNOWN (304)", + "UNKNOWN (305)", + "WM_CTLCOLORMSGBOX", + "WM_CTLCOLOREDIT", + "WM_CTLCOLORLISTBOX", + "WM_CTLCOLORBTN", + "WM_CTLCOLORDLG", + "WM_CTLCOLORSCROLLBAR", + "WM_CTLCOLORSTATIC", + "UNKNOWN (313)", + "UNKNOWN (314)", + "UNKNOWN (315)", + "UNKNOWN (316)", + "UNKNOWN (317)", + "UNKNOWN (318)", + "UNKNOWN (319)", + "UNKNOWN (320)", + "UNKNOWN (321)", + "UNKNOWN (322)", + "UNKNOWN (323)", + "UNKNOWN (324)", + "UNKNOWN (325)", + "UNKNOWN (326)", + "UNKNOWN (327)", + "UNKNOWN (328)", + "UNKNOWN (329)", + "UNKNOWN (330)", + "UNKNOWN (331)", + "UNKNOWN (332)", + "UNKNOWN (333)", + "UNKNOWN (334)", + "UNKNOWN (335)", + "UNKNOWN (336)", + "UNKNOWN (337)", + "UNKNOWN (338)", + "UNKNOWN (339)", + "UNKNOWN (340)", + "UNKNOWN (341)", + "UNKNOWN (342)", + "UNKNOWN (343)", + "UNKNOWN (344)", + "UNKNOWN (345)", + "UNKNOWN (346)", + "UNKNOWN (347)", + "UNKNOWN (348)", + "UNKNOWN (349)", + "UNKNOWN (350)", + "UNKNOWN (351)", + "UNKNOWN (352)", + "UNKNOWN (353)", + "UNKNOWN (354)", + "UNKNOWN (355)", + "UNKNOWN (356)", + "UNKNOWN (357)", + "UNKNOWN (358)", + "UNKNOWN (359)", + "UNKNOWN (360)", + "UNKNOWN (361)", + "UNKNOWN (362)", + "UNKNOWN (363)", + "UNKNOWN (364)", + "UNKNOWN (365)", + "UNKNOWN (366)", + "UNKNOWN (367)", + "UNKNOWN (368)", + "UNKNOWN (369)", + "UNKNOWN (370)", + "UNKNOWN (371)", + "UNKNOWN (372)", + "UNKNOWN (373)", + "UNKNOWN (374)", + "UNKNOWN (375)", + "UNKNOWN (376)", + "UNKNOWN (377)", + "UNKNOWN (378)", + "UNKNOWN (379)", + "UNKNOWN (380)", + "UNKNOWN (381)", + "UNKNOWN (382)", + "UNKNOWN (383)", + "UNKNOWN (384)", + "UNKNOWN (385)", + "UNKNOWN (386)", + "UNKNOWN (387)", + "UNKNOWN (388)", + "UNKNOWN (389)", + "UNKNOWN (390)", + "UNKNOWN (391)", + "UNKNOWN (392)", + "UNKNOWN (393)", + "UNKNOWN (394)", + "UNKNOWN (395)", + "UNKNOWN (396)", + "UNKNOWN (397)", + "UNKNOWN (398)", + "UNKNOWN (399)", + "UNKNOWN (400)", + "UNKNOWN (401)", + "UNKNOWN (402)", + "UNKNOWN (403)", + "UNKNOWN (404)", + "UNKNOWN (405)", + "UNKNOWN (406)", + "UNKNOWN (407)", + "UNKNOWN (408)", + "UNKNOWN (409)", + "UNKNOWN (410)", + "UNKNOWN (411)", + "UNKNOWN (412)", + "UNKNOWN (413)", + "UNKNOWN (414)", + "UNKNOWN (415)", + "UNKNOWN (416)", + "UNKNOWN (417)", + "UNKNOWN (418)", + "UNKNOWN (419)", + "UNKNOWN (420)", + "UNKNOWN (421)", + "UNKNOWN (422)", + "UNKNOWN (423)", + "UNKNOWN (424)", + "UNKNOWN (425)", + "UNKNOWN (426)", + "UNKNOWN (427)", + "UNKNOWN (428)", + "UNKNOWN (429)", + "UNKNOWN (430)", + "UNKNOWN (431)", + "UNKNOWN (432)", + "UNKNOWN (433)", + "UNKNOWN (434)", + "UNKNOWN (435)", + "UNKNOWN (436)", + "UNKNOWN (437)", + "UNKNOWN (438)", + "UNKNOWN (439)", + "UNKNOWN (440)", + "UNKNOWN (441)", + "UNKNOWN (442)", + "UNKNOWN (443)", + "UNKNOWN (444)", + "UNKNOWN (445)", + "UNKNOWN (446)", + "UNKNOWN (447)", + "UNKNOWN (448)", + "UNKNOWN (449)", + "UNKNOWN (450)", + "UNKNOWN (451)", + "UNKNOWN (452)", + "UNKNOWN (453)", + "UNKNOWN (454)", + "UNKNOWN (455)", + "UNKNOWN (456)", + "UNKNOWN (457)", + "UNKNOWN (458)", + "UNKNOWN (459)", + "UNKNOWN (460)", + "UNKNOWN (461)", + "UNKNOWN (462)", + "UNKNOWN (463)", + "UNKNOWN (464)", + "UNKNOWN (465)", + "UNKNOWN (466)", + "UNKNOWN (467)", + "UNKNOWN (468)", + "UNKNOWN (469)", + "UNKNOWN (470)", + "UNKNOWN (471)", + "UNKNOWN (472)", + "UNKNOWN (473)", + "UNKNOWN (474)", + "UNKNOWN (475)", + "UNKNOWN (476)", + "UNKNOWN (477)", + "UNKNOWN (478)", + "UNKNOWN (479)", + "UNKNOWN (480)", + "UNKNOWN (481)", + "UNKNOWN (482)", + "UNKNOWN (483)", + "UNKNOWN (484)", + "UNKNOWN (485)", + "UNKNOWN (486)", + "UNKNOWN (487)", + "UNKNOWN (488)", + "UNKNOWN (489)", + "UNKNOWN (490)", + "UNKNOWN (491)", + "UNKNOWN (492)", + "UNKNOWN (493)", + "UNKNOWN (494)", + "UNKNOWN (495)", + "UNKNOWN (496)", + "UNKNOWN (497)", + "UNKNOWN (498)", + "UNKNOWN (499)", + "UNKNOWN (500)", + "UNKNOWN (501)", + "UNKNOWN (502)", + "UNKNOWN (503)", + "UNKNOWN (504)", + "UNKNOWN (505)", + "UNKNOWN (506)", + "UNKNOWN (507)", + "UNKNOWN (508)", + "UNKNOWN (509)", + "UNKNOWN (510)", + "UNKNOWN (511)", + "WM_MOUSEMOVE", + "WM_LBUTTONDOWN", + "WM_LBUTTONUP", + "WM_LBUTTONDBLCLK", + "WM_RBUTTONDOWN", + "WM_RBUTTONUP", + "WM_RBUTTONDBLCLK", + "WM_MBUTTONDOWN", + "WM_MBUTTONUP", + "WM_MOUSELAST", + "WM_MOUSEWHEEL", + "WM_XBUTTONDOWN", + "WM_XBUTTONUP", + "UNKNOWN (525)", + "UNKNOWN (526)", + "UNKNOWN (527)", + "WM_PARENTNOTIFY", + "WM_ENTERMENULOOP", + "WM_EXITMENULOOP", + "WM_NEXTMENU", + "WM_SIZING", + "WM_CAPTURECHANGED", + "WM_MOVING", + "UNKNOWN (535)", + "WM_POWERBROADCAST", + "WM_DEVICECHANGE", + "UNKNOWN (538)", + "UNKNOWN (539)", + "UNKNOWN (540)", + "UNKNOWN (541)", + "UNKNOWN (542)", + "UNKNOWN (543)", + "WM_MDICREATE", + "WM_MDIDESTROY", + "WM_MDIACTIVATE", + "WM_MDIRESTORE", + "WM_MDINEXT", + "WM_MDIMAXIMIZE", + "WM_MDITILE", + "WM_MDICASCADE", + "WM_MDIICONARRANGE", + "WM_MDIGETACTIVE", + "UNKNOWN (554)", + "UNKNOWN (555)", + "UNKNOWN (556)", + "UNKNOWN (557)", + "UNKNOWN (558)", + "UNKNOWN (559)", + "WM_MDISETMENU", + "WM_ENTERSIZEMOVE", + "WM_EXITSIZEMOVE", + "WM_DROPFILES", + "WM_MDIREFRESHMENU", + "UNKNOWN (565)", + "UNKNOWN (566)", + "UNKNOWN (567)", + "UNKNOWN (568)", + "UNKNOWN (569)", + "UNKNOWN (570)", + "UNKNOWN (571)", + "UNKNOWN (572)", + "UNKNOWN (573)", + "UNKNOWN (574)", + "UNKNOWN (575)", + "UNKNOWN (576)", + "UNKNOWN (577)", + "UNKNOWN (578)", + "UNKNOWN (579)", + "UNKNOWN (580)", + "UNKNOWN (581)", + "UNKNOWN (582)", + "UNKNOWN (583)", + "UNKNOWN (584)", + "UNKNOWN (585)", + "UNKNOWN (586)", + "UNKNOWN (587)", + "UNKNOWN (588)", + "UNKNOWN (589)", + "UNKNOWN (590)", + "UNKNOWN (591)", + "UNKNOWN (592)", + "UNKNOWN (593)", + "UNKNOWN (594)", + "UNKNOWN (595)", + "UNKNOWN (596)", + "UNKNOWN (597)", + "UNKNOWN (598)", + "UNKNOWN (599)", + "UNKNOWN (600)", + "UNKNOWN (601)", + "UNKNOWN (602)", + "UNKNOWN (603)", + "UNKNOWN (604)", + "UNKNOWN (605)", + "UNKNOWN (606)", + "UNKNOWN (607)", + "UNKNOWN (608)", + "UNKNOWN (609)", + "UNKNOWN (610)", + "UNKNOWN (611)", + "UNKNOWN (612)", + "UNKNOWN (613)", + "UNKNOWN (614)", + "UNKNOWN (615)", + "UNKNOWN (616)", + "UNKNOWN (617)", + "UNKNOWN (618)", + "UNKNOWN (619)", + "UNKNOWN (620)", + "UNKNOWN (621)", + "UNKNOWN (622)", + "UNKNOWN (623)", + "UNKNOWN (624)", + "UNKNOWN (625)", + "UNKNOWN (626)", + "UNKNOWN (627)", + "UNKNOWN (628)", + "UNKNOWN (629)", + "UNKNOWN (630)", + "UNKNOWN (631)", + "UNKNOWN (632)", + "UNKNOWN (633)", + "UNKNOWN (634)", + "UNKNOWN (635)", + "UNKNOWN (636)", + "UNKNOWN (637)", + "UNKNOWN (638)", + "UNKNOWN (639)", + "UNKNOWN (640)", + "UNKNOWN (641)", + "UNKNOWN (642)", + "UNKNOWN (643)", + "UNKNOWN (644)", + "UNKNOWN (645)", + "UNKNOWN (646)", + "UNKNOWN (647)", + "UNKNOWN (648)", + "UNKNOWN (649)", + "UNKNOWN (650)", + "UNKNOWN (651)", + "UNKNOWN (652)", + "UNKNOWN (653)", + "UNKNOWN (654)", + "UNKNOWN (655)", + "UNKNOWN (656)", + "UNKNOWN (657)", + "UNKNOWN (658)", + "UNKNOWN (659)", + "UNKNOWN (660)", + "UNKNOWN (661)", + "UNKNOWN (662)", + "UNKNOWN (663)", + "UNKNOWN (664)", + "UNKNOWN (665)", + "UNKNOWN (666)", + "UNKNOWN (667)", + "UNKNOWN (668)", + "UNKNOWN (669)", + "UNKNOWN (670)", + "UNKNOWN (671)", + "UNKNOWN (672)", + "WM_MOUSEHOVER", + "UNKNOWN (674)", + "WM_MOUSELEAVE", + "UNKNOWN (676)", + "UNKNOWN (677)", + "UNKNOWN (678)", + "UNKNOWN (679)", + "UNKNOWN (680)", + "UNKNOWN (681)", + "UNKNOWN (682)", + "UNKNOWN (683)", + "UNKNOWN (684)", + "UNKNOWN (685)", + "UNKNOWN (686)", + "UNKNOWN (687)", + "UNKNOWN (688)", + "UNKNOWN (689)", + "UNKNOWN (690)", + "UNKNOWN (691)", + "UNKNOWN (692)", + "UNKNOWN (693)", + "UNKNOWN (694)", + "UNKNOWN (695)", + "UNKNOWN (696)", + "UNKNOWN (697)", + "UNKNOWN (698)", + "UNKNOWN (699)", + "UNKNOWN (700)", + "UNKNOWN (701)", + "UNKNOWN (702)", + "UNKNOWN (703)", + "UNKNOWN (704)", + "UNKNOWN (705)", + "UNKNOWN (706)", + "UNKNOWN (707)", + "UNKNOWN (708)", + "UNKNOWN (709)", + "UNKNOWN (710)", + "UNKNOWN (711)", + "UNKNOWN (712)", + "UNKNOWN (713)", + "UNKNOWN (714)", + "UNKNOWN (715)", + "UNKNOWN (716)", + "UNKNOWN (717)", + "UNKNOWN (718)", + "UNKNOWN (719)", + "UNKNOWN (720)", + "UNKNOWN (721)", + "UNKNOWN (722)", + "UNKNOWN (723)", + "UNKNOWN (724)", + "UNKNOWN (725)", + "UNKNOWN (726)", + "UNKNOWN (727)", + "UNKNOWN (728)", + "UNKNOWN (729)", + "UNKNOWN (730)", + "UNKNOWN (731)", + "UNKNOWN (732)", + "UNKNOWN (733)", + "UNKNOWN (734)", + "UNKNOWN (735)", + "UNKNOWN (736)", + "UNKNOWN (737)", + "UNKNOWN (738)", + "UNKNOWN (739)", + "UNKNOWN (740)", + "UNKNOWN (741)", + "UNKNOWN (742)", + "UNKNOWN (743)", + "UNKNOWN (744)", + "UNKNOWN (745)", + "UNKNOWN (746)", + "UNKNOWN (747)", + "UNKNOWN (748)", + "UNKNOWN (749)", + "UNKNOWN (750)", + "UNKNOWN (751)", + "UNKNOWN (752)", + "UNKNOWN (753)", + "UNKNOWN (754)", + "UNKNOWN (755)", + "UNKNOWN (756)", + "UNKNOWN (757)", + "UNKNOWN (758)", + "UNKNOWN (759)", + "UNKNOWN (760)", + "UNKNOWN (761)", + "UNKNOWN (762)", + "UNKNOWN (763)", + "UNKNOWN (764)", + "UNKNOWN (765)", + "UNKNOWN (766)", + "UNKNOWN (767)", + "WM_CUT", + "WM_COPY", + "WM_PASTE", + "WM_CLEAR", + "WM_UNDO", + "WM_RENDERFORMAT", + "WM_RENDERALLFORMATS", + "WM_DESTROYCLIPBOARD", + "WM_DRAWCLIPBOARD", + "WM_PAINTCLIPBOARD", + "WM_VSCROLLCLIPBOARD", + "WM_SIZECLIPBOARD", + "WM_ASKCBFORMATNAME", + "WM_CHANGECBCHAIN", + "WM_HSCROLLCLIPBOARD", + "WM_QUERYNEWPALETTE", + "WM_PALETTEISCHANGING", + "WM_PALETTECHANGED", + "WM_HOTKEY", + "UNKNOWN (787)", + "UNKNOWN (788)", + "UNKNOWN (789)", + "UNKNOWN (790)", + "WM_PRINT", + "WM_PRINTCLIENT", + "UNKNOWN (793)", + "UNKNOWN (794)", + "UNKNOWN (795)", + "UNKNOWN (796)", + "UNKNOWN (797)", + "UNKNOWN (798)", + "UNKNOWN (799)", + "UNKNOWN (800)", + "UNKNOWN (801)", + "UNKNOWN (802)", + "UNKNOWN (803)", + "UNKNOWN (804)", + "UNKNOWN (805)", + "UNKNOWN (806)", + "UNKNOWN (807)", + "UNKNOWN (808)", + "UNKNOWN (809)", + "UNKNOWN (810)", + "UNKNOWN (811)", + "UNKNOWN (812)", + "UNKNOWN (813)", + "UNKNOWN (814)", + "UNKNOWN (815)", + "UNKNOWN (816)", + "UNKNOWN (817)", + "UNKNOWN (818)", + "UNKNOWN (819)", + "UNKNOWN (820)", + "UNKNOWN (821)", + "UNKNOWN (822)", + "UNKNOWN (823)", + "UNKNOWN (824)", + "UNKNOWN (825)", + "UNKNOWN (826)", + "UNKNOWN (827)", + "UNKNOWN (828)", + "UNKNOWN (829)", + "UNKNOWN (830)", + "UNKNOWN (831)", + "UNKNOWN (832)", + "UNKNOWN (833)", + "UNKNOWN (834)", + "UNKNOWN (835)", + "UNKNOWN (836)", + "UNKNOWN (837)", + "UNKNOWN (838)", + "UNKNOWN (839)", + "UNKNOWN (840)", + "UNKNOWN (841)", + "UNKNOWN (842)", + "UNKNOWN (843)", + "UNKNOWN (844)", + "UNKNOWN (845)", + "UNKNOWN (846)", + "UNKNOWN (847)", + "UNKNOWN (848)", + "UNKNOWN (849)", + "UNKNOWN (850)", + "UNKNOWN (851)", + "UNKNOWN (852)", + "UNKNOWN (853)", + "UNKNOWN (854)", + "UNKNOWN (855)", + "WM_HANDHELDFIRST", + "UNKNOWN (857)", + "UNKNOWN (858)", + "UNKNOWN (859)", + "UNKNOWN (860)", + "UNKNOWN (861)", + "UNKNOWN (862)", + "WM_HANDHELDLAST", + "WM_AFXFIRST", + "UNKNOWN (865)", + "UNKNOWN (866)", + "UNKNOWN (867)", + "UNKNOWN (868)", + "UNKNOWN (869)", + "UNKNOWN (870)", + "UNKNOWN (871)", + "UNKNOWN (872)", + "UNKNOWN (873)", + "UNKNOWN (874)", + "UNKNOWN (875)", + "UNKNOWN (876)", + "UNKNOWN (877)", + "UNKNOWN (878)", + "UNKNOWN (879)", + "UNKNOWN (880)", + "UNKNOWN (881)", + "UNKNOWN (882)", + "UNKNOWN (883)", + "UNKNOWN (884)", + "UNKNOWN (885)", + "UNKNOWN (886)", + "UNKNOWN (887)", + "UNKNOWN (888)", + "UNKNOWN (889)", + "UNKNOWN (890)", + "UNKNOWN (891)", + "UNKNOWN (892)", + "UNKNOWN (893)", + "UNKNOWN (894)", + "WM_AFXLAST", + "WM_PENWINFIRST", + "UNKNOWN (897)", + "UNKNOWN (898)", + "UNKNOWN (899)", + "UNKNOWN (900)", + "UNKNOWN (901)", + "UNKNOWN (902)", + "UNKNOWN (903)", + "UNKNOWN (904)", + "UNKNOWN (905)", + "UNKNOWN (906)", + "UNKNOWN (907)", + "UNKNOWN (908)", + "UNKNOWN (909)", + "UNKNOWN (910)", + "WM_PENWINLAST", + "UNKNOWN (912)", + "UNKNOWN (913)", + "UNKNOWN (914)", + "UNKNOWN (915)", + "UNKNOWN (916)", + "UNKNOWN (917)", + "UNKNOWN (918)", + "UNKNOWN (919)", + "UNKNOWN (920)", + "UNKNOWN (921)", + "UNKNOWN (922)", + "UNKNOWN (923)", + "UNKNOWN (924)", + "UNKNOWN (925)", + "UNKNOWN (926)", + "UNKNOWN (927)", + "UNKNOWN (928)", + "UNKNOWN (929)", + "UNKNOWN (930)", + "UNKNOWN (931)", + "UNKNOWN (932)", + "UNKNOWN (933)", + "UNKNOWN (934)", + "UNKNOWN (935)", + "UNKNOWN (936)", + "UNKNOWN (937)", + "UNKNOWN (938)", + "UNKNOWN (939)", + "UNKNOWN (940)", + "UNKNOWN (941)", + "UNKNOWN (942)", + "UNKNOWN (943)", + "UNKNOWN (944)", + "UNKNOWN (945)", + "UNKNOWN (946)", + "UNKNOWN (947)", + "UNKNOWN (948)", + "UNKNOWN (949)", + "UNKNOWN (950)", + "UNKNOWN (951)", + "UNKNOWN (952)", + "UNKNOWN (953)", + "UNKNOWN (954)", + "UNKNOWN (955)", + "UNKNOWN (956)", + "UNKNOWN (957)", + "UNKNOWN (958)", + "UNKNOWN (959)", + "UNKNOWN (960)", + "UNKNOWN (961)", + "UNKNOWN (962)", + "UNKNOWN (963)", + "UNKNOWN (964)", + "UNKNOWN (965)", + "UNKNOWN (966)", + "UNKNOWN (967)", + "UNKNOWN (968)", + "UNKNOWN (969)", + "UNKNOWN (970)", + "UNKNOWN (971)", + "UNKNOWN (972)", + "UNKNOWN (973)", + "UNKNOWN (974)", + "UNKNOWN (975)", + "UNKNOWN (976)", + "UNKNOWN (977)", + "UNKNOWN (978)", + "UNKNOWN (979)", + "UNKNOWN (980)", + "UNKNOWN (981)", + "UNKNOWN (982)", + "UNKNOWN (983)", + "UNKNOWN (984)", + "UNKNOWN (985)", + "UNKNOWN (986)", + "UNKNOWN (987)", + "UNKNOWN (988)", + "UNKNOWN (989)", + "UNKNOWN (990)", + "UNKNOWN (991)", + "UNKNOWN (992)", + "UNKNOWN (993)", + "UNKNOWN (994)", + "UNKNOWN (995)", + "UNKNOWN (996)", + "UNKNOWN (997)", + "UNKNOWN (998)", + "UNKNOWN (999)", + "UNKNOWN (1000)", + "UNKNOWN (1001)", + "UNKNOWN (1002)", + "UNKNOWN (1003)", + "UNKNOWN (1004)", + "UNKNOWN (1005)", + "UNKNOWN (1006)", + "UNKNOWN (1007)", + "UNKNOWN (1008)", + "UNKNOWN (1009)", + "UNKNOWN (1010)", + "UNKNOWN (1011)", + "UNKNOWN (1012)", + "UNKNOWN (1013)", + "UNKNOWN (1014)", + "UNKNOWN (1015)", + "UNKNOWN (1016)", + "UNKNOWN (1017)", + "UNKNOWN (1018)", + "UNKNOWN (1019)", + "UNKNOWN (1020)", + "UNKNOWN (1021)", + "UNKNOWN (1022)", + "UNKNOWN (1023)", + "WM_USER" +}; diff --git a/3rdparty/SDL/src/video/windib/SDL_dibevents.c b/3rdparty/SDL/src/video/windib/SDL_dibevents.c new file mode 100644 index 0000000..6cee54a --- /dev/null +++ b/3rdparty/SDL/src/video/windib/SDL_dibevents.c @@ -0,0 +1,704 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#define WIN32_LEAN_AND_MEAN +#include <windows.h> + +#include "SDL_main.h" +#include "SDL_events.h" +#include "SDL_syswm.h" +#include "../../events/SDL_sysevents.h" +#include "../../events/SDL_events_c.h" +#include "../wincommon/SDL_lowvideo.h" +#include "SDL_gapidibvideo.h" +#include "SDL_vkeys.h" + +#ifdef SDL_VIDEO_DRIVER_GAPI +#include "../gapi/SDL_gapivideo.h" +#endif + +#ifdef SDL_VIDEO_DRIVER_WINDIB +#include "SDL_dibvideo.h" +#endif + +#ifndef WM_APP +#define WM_APP 0x8000 +#endif + +#ifdef _WIN32_WCE +#define NO_GETKEYBOARDSTATE +#endif + +/* The translation table from a Microsoft VK keysym to a SDL keysym */ +static SDLKey VK_keymap[SDLK_LAST]; +static SDL_keysym *TranslateKey(WPARAM vkey, UINT scancode, SDL_keysym *keysym, int pressed); +static SDLKey Arrows_keymap[4]; + +/* Masks for processing the windows KEYDOWN and KEYUP messages */ +#define REPEATED_KEYMASK (1<<30) +#define EXTENDED_KEYMASK (1<<24) + +/* DJM: If the user setup the window for us, we want to save his window proc, + and give him a chance to handle some messages. */ +#ifdef STRICT +#define WNDPROCTYPE WNDPROC +#else +#define WNDPROCTYPE FARPROC +#endif +static WNDPROCTYPE userWindowProc = NULL; + + +#ifdef SDL_VIDEO_DRIVER_GAPI + +WPARAM rotateKey(WPARAM key,int direction) +{ + if(direction ==0 ) return key; + + switch (key) { + case 0x26: /* up */ + return Arrows_keymap[(2 + direction) % 4]; + case 0x27: /* right */ + return Arrows_keymap[(1 + direction) % 4]; + case 0x28: /* down */ + return Arrows_keymap[direction % 4]; + case 0x25: /* left */ + return Arrows_keymap[(3 + direction) % 4]; + } + + return key; +} + +static void GapiTransform(GapiInfo *gapiInfo, LONG *x, LONG *y) +{ + if(gapiInfo->hiresFix) + { + *x *= 2; + *y *= 2; + } + + // 0 3 0 + if((!gapiInfo->userOrientation && gapiInfo->systemOrientation && !gapiInfo->gapiOrientation) || + // 3 0 3 + (gapiInfo->userOrientation && !gapiInfo->systemOrientation && gapiInfo->gapiOrientation) || + // 3 0 0 + (gapiInfo->userOrientation && !gapiInfo->systemOrientation && !gapiInfo->gapiOrientation)) + { + Sint16 temp = *x; + *x = SDL_VideoSurface->w - *y; + *y = temp; + } + else + // 0 0 0 + if((!gapiInfo->userOrientation && !gapiInfo->systemOrientation && !gapiInfo->gapiOrientation) || + // 0 0 3 + (!gapiInfo->userOrientation && !gapiInfo->systemOrientation && gapiInfo->gapiOrientation)) + { + // without changes + // *x = *x; + // *y = *y; + } + // default + else + { + // without changes + // *x = *x; + // *y = *y; + } +} +#endif + + +/* The main Win32 event handler */ +LRESULT DIB_HandleMessage(_THIS, HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) +{ + extern int posted; + + switch (msg) { + case WM_SYSKEYDOWN: + case WM_KEYDOWN: { + SDL_keysym keysym; + +#ifdef SDL_VIDEO_DRIVER_GAPI + if(this->hidden->gapiInfo) + { + // Drop GAPI artefacts + if (wParam == 0x84 || wParam == 0x5B) + return 0; + + wParam = rotateKey(wParam, this->hidden->gapiInfo->coordinateTransform); + } +#endif + /* Ignore repeated keys */ + if ( lParam&REPEATED_KEYMASK ) { + return(0); + } + switch (wParam) { + case VK_CONTROL: + if ( lParam&EXTENDED_KEYMASK ) + wParam = VK_RCONTROL; + else + wParam = VK_LCONTROL; + break; + case VK_SHIFT: + /* EXTENDED trick doesn't work here */ + { + Uint8 *state = SDL_GetKeyState(NULL); + if (state[SDLK_LSHIFT] == SDL_RELEASED && (GetKeyState(VK_LSHIFT) & 0x8000)) { + wParam = VK_LSHIFT; + } else if (state[SDLK_RSHIFT] == SDL_RELEASED && (GetKeyState(VK_RSHIFT) & 0x8000)) { + wParam = VK_RSHIFT; + } else { + /* Win9x */ + int sc = HIWORD(lParam) & 0xFF; + + if (sc == 0x2A) + wParam = VK_LSHIFT; + else + if (sc == 0x36) + wParam = VK_RSHIFT; + else + wParam = VK_LSHIFT; + } + } + break; + case VK_MENU: + if ( lParam&EXTENDED_KEYMASK ) + wParam = VK_RMENU; + else + wParam = VK_LMENU; + break; + } +#ifdef NO_GETKEYBOARDSTATE + /* this is the workaround for the missing ToAscii() and ToUnicode() in CE (not necessary at KEYUP!) */ + if ( SDL_TranslateUNICODE ) { + MSG m; + + m.hwnd = hwnd; + m.message = msg; + m.wParam = wParam; + m.lParam = lParam; + m.time = 0; + if ( TranslateMessage(&m) && PeekMessage(&m, hwnd, 0, WM_USER, PM_NOREMOVE) && (m.message == WM_CHAR) ) { + GetMessage(&m, hwnd, 0, WM_USER); + wParam = m.wParam; + } + } +#endif /* NO_GETKEYBOARDSTATE */ + posted = SDL_PrivateKeyboard(SDL_PRESSED, + TranslateKey(wParam,HIWORD(lParam),&keysym,1)); + } + return(0); + + case WM_SYSKEYUP: + case WM_KEYUP: { + SDL_keysym keysym; + +#ifdef SDL_VIDEO_DRIVER_GAPI + if(this->hidden->gapiInfo) + { + // Drop GAPI artifacts + if (wParam == 0x84 || wParam == 0x5B) + return 0; + + wParam = rotateKey(wParam, this->hidden->gapiInfo->coordinateTransform); + } +#endif + + switch (wParam) { + case VK_CONTROL: + if ( lParam&EXTENDED_KEYMASK ) + wParam = VK_RCONTROL; + else + wParam = VK_LCONTROL; + break; + case VK_SHIFT: + /* EXTENDED trick doesn't work here */ + { + Uint8 *state = SDL_GetKeyState(NULL); + if (state[SDLK_LSHIFT] == SDL_PRESSED && !(GetKeyState(VK_LSHIFT) & 0x8000)) { + wParam = VK_LSHIFT; + } else if (state[SDLK_RSHIFT] == SDL_PRESSED && !(GetKeyState(VK_RSHIFT) & 0x8000)) { + wParam = VK_RSHIFT; + } else { + /* Win9x */ + int sc = HIWORD(lParam) & 0xFF; + + if (sc == 0x2A) + wParam = VK_LSHIFT; + else + if (sc == 0x36) + wParam = VK_RSHIFT; + else + wParam = VK_LSHIFT; + } + } + break; + case VK_MENU: + if ( lParam&EXTENDED_KEYMASK ) + wParam = VK_RMENU; + else + wParam = VK_LMENU; + break; + } + /* Windows only reports keyup for print screen */ + if ( wParam == VK_SNAPSHOT && SDL_GetKeyState(NULL)[SDLK_PRINT] == SDL_RELEASED ) { + posted = SDL_PrivateKeyboard(SDL_PRESSED, + TranslateKey(wParam,HIWORD(lParam),&keysym,1)); + } + posted = SDL_PrivateKeyboard(SDL_RELEASED, + TranslateKey(wParam,HIWORD(lParam),&keysym,0)); + } + return(0); +#if defined(SC_SCREENSAVE) && defined(SC_MONITORPOWER) + case WM_SYSCOMMAND: { + const DWORD val = (DWORD) (wParam & 0xFFF0); + if ((val == SC_SCREENSAVE) || (val == SC_MONITORPOWER)) { + if (this->hidden->dibInfo && !allow_screensaver) { + /* Note that this doesn't stop anything on Vista + if the screensaver has a password. */ + return(0); + } + } + } + /* Fall through to default processing */ +#endif /* SC_SCREENSAVE && SC_MONITORPOWER */ + + default: { + /* Only post the event if we're watching for it */ + if ( SDL_ProcessEvents[SDL_SYSWMEVENT] == SDL_ENABLE ) { + SDL_SysWMmsg wmmsg; + + SDL_VERSION(&wmmsg.version); + wmmsg.hwnd = hwnd; + wmmsg.msg = msg; + wmmsg.wParam = wParam; + wmmsg.lParam = lParam; + posted = SDL_PrivateSysWMEvent(&wmmsg); + + /* DJM: If the user isn't watching for private + messages in her SDL event loop, then pass it + along to any win32 specific window proc. + */ + } else if (userWindowProc) { + return CallWindowProc(userWindowProc, hwnd, msg, wParam, lParam); + } + } + break; + } + return(DefWindowProc(hwnd, msg, wParam, lParam)); +} + +#ifdef _WIN32_WCE +static BOOL GetLastStylusPos(POINT* ptLast) +{ + BOOL bResult = FALSE; + UINT nRet; + GetMouseMovePoints(ptLast, 1, &nRet); + if ( nRet == 1 ) { + ptLast->x /= 4; + ptLast->y /= 4; + bResult = TRUE; + } + return bResult; +} +#endif + +static void DIB_GenerateMouseMotionEvent(_THIS) +{ + extern int mouse_relative; + extern int posted; + + POINT mouse; +#ifdef _WIN32_WCE + if ( !GetCursorPos(&mouse) && !GetLastStylusPos(&mouse) ) return; +#else + if ( !GetCursorPos(&mouse) ) return; +#endif + + if ( mouse_relative ) { + POINT center; + center.x = (SDL_VideoSurface->w/2); + center.y = (SDL_VideoSurface->h/2); + ClientToScreen(SDL_Window, ¢er); + + mouse.x -= center.x; + mouse.y -= center.y; + if ( mouse.x || mouse.y ) { + SetCursorPos(center.x, center.y); + posted = SDL_PrivateMouseMotion(0, 1, (Sint16)mouse.x, (Sint16)mouse.y); + } + } else { + ScreenToClient(SDL_Window, &mouse); +#ifdef SDL_VIDEO_DRIVER_GAPI + if (SDL_VideoSurface && this->hidden->gapiInfo) + GapiTransform(this->hidden->gapiInfo, &mouse.x, &mouse.y); +#endif + posted = SDL_PrivateMouseMotion(0, 0, (Sint16)mouse.x, (Sint16)mouse.y); + } +} + +void DIB_PumpEvents(_THIS) +{ + MSG msg; + + while ( PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE) ) { + if ( GetMessage(&msg, NULL, 0, 0) > 0 ) { + DispatchMessage(&msg); + } + } + + if ( SDL_GetAppState() & SDL_APPMOUSEFOCUS ) { + DIB_GenerateMouseMotionEvent( this ); + } +} + +static HKL hLayoutUS = NULL; + +void DIB_InitOSKeymap(_THIS) +{ + int i; +#ifndef _WIN32_WCE + char current_layout[KL_NAMELENGTH]; + + GetKeyboardLayoutName(current_layout); + //printf("Initial Keyboard Layout Name: '%s'\n", current_layout); + + hLayoutUS = LoadKeyboardLayout("00000409", KLF_NOTELLSHELL); + + if (!hLayoutUS) { + //printf("Failed to load US keyboard layout. Using current.\n"); + hLayoutUS = GetKeyboardLayout(0); + } + LoadKeyboardLayout(current_layout, KLF_ACTIVATE); +#else +#if _WIN32_WCE >=420 + TCHAR current_layout[KL_NAMELENGTH]; + + GetKeyboardLayoutName(current_layout); + //printf("Initial Keyboard Layout Name: '%s'\n", current_layout); + + hLayoutUS = LoadKeyboardLayout(L"00000409", 0); + + if (!hLayoutUS) { + //printf("Failed to load US keyboard layout. Using current.\n"); + hLayoutUS = GetKeyboardLayout(0); + } + LoadKeyboardLayout(current_layout, 0); +#endif // _WIN32_WCE >=420 +#endif + /* Map the VK keysyms */ + for ( i=0; i<SDL_arraysize(VK_keymap); ++i ) + VK_keymap[i] = SDLK_UNKNOWN; + + VK_keymap[VK_BACK] = SDLK_BACKSPACE; + VK_keymap[VK_TAB] = SDLK_TAB; + VK_keymap[VK_CLEAR] = SDLK_CLEAR; + VK_keymap[VK_RETURN] = SDLK_RETURN; + VK_keymap[VK_PAUSE] = SDLK_PAUSE; + VK_keymap[VK_ESCAPE] = SDLK_ESCAPE; + VK_keymap[VK_SPACE] = SDLK_SPACE; + VK_keymap[VK_APOSTROPHE] = SDLK_QUOTE; + VK_keymap[VK_COMMA] = SDLK_COMMA; + VK_keymap[VK_MINUS] = SDLK_MINUS; + VK_keymap[VK_PERIOD] = SDLK_PERIOD; + VK_keymap[VK_SLASH] = SDLK_SLASH; + VK_keymap[VK_0] = SDLK_0; + VK_keymap[VK_1] = SDLK_1; + VK_keymap[VK_2] = SDLK_2; + VK_keymap[VK_3] = SDLK_3; + VK_keymap[VK_4] = SDLK_4; + VK_keymap[VK_5] = SDLK_5; + VK_keymap[VK_6] = SDLK_6; + VK_keymap[VK_7] = SDLK_7; + VK_keymap[VK_8] = SDLK_8; + VK_keymap[VK_9] = SDLK_9; + VK_keymap[VK_SEMICOLON] = SDLK_SEMICOLON; + VK_keymap[VK_EQUALS] = SDLK_EQUALS; + VK_keymap[VK_LBRACKET] = SDLK_LEFTBRACKET; + VK_keymap[VK_BACKSLASH] = SDLK_BACKSLASH; + VK_keymap[VK_OEM_102] = SDLK_LESS; + VK_keymap[VK_RBRACKET] = SDLK_RIGHTBRACKET; + VK_keymap[VK_GRAVE] = SDLK_BACKQUOTE; + VK_keymap[VK_BACKTICK] = SDLK_BACKQUOTE; + VK_keymap[VK_A] = SDLK_a; + VK_keymap[VK_B] = SDLK_b; + VK_keymap[VK_C] = SDLK_c; + VK_keymap[VK_D] = SDLK_d; + VK_keymap[VK_E] = SDLK_e; + VK_keymap[VK_F] = SDLK_f; + VK_keymap[VK_G] = SDLK_g; + VK_keymap[VK_H] = SDLK_h; + VK_keymap[VK_I] = SDLK_i; + VK_keymap[VK_J] = SDLK_j; + VK_keymap[VK_K] = SDLK_k; + VK_keymap[VK_L] = SDLK_l; + VK_keymap[VK_M] = SDLK_m; + VK_keymap[VK_N] = SDLK_n; + VK_keymap[VK_O] = SDLK_o; + VK_keymap[VK_P] = SDLK_p; + VK_keymap[VK_Q] = SDLK_q; + VK_keymap[VK_R] = SDLK_r; + VK_keymap[VK_S] = SDLK_s; + VK_keymap[VK_T] = SDLK_t; + VK_keymap[VK_U] = SDLK_u; + VK_keymap[VK_V] = SDLK_v; + VK_keymap[VK_W] = SDLK_w; + VK_keymap[VK_X] = SDLK_x; + VK_keymap[VK_Y] = SDLK_y; + VK_keymap[VK_Z] = SDLK_z; + VK_keymap[VK_DELETE] = SDLK_DELETE; + + VK_keymap[VK_NUMPAD0] = SDLK_KP0; + VK_keymap[VK_NUMPAD1] = SDLK_KP1; + VK_keymap[VK_NUMPAD2] = SDLK_KP2; + VK_keymap[VK_NUMPAD3] = SDLK_KP3; + VK_keymap[VK_NUMPAD4] = SDLK_KP4; + VK_keymap[VK_NUMPAD5] = SDLK_KP5; + VK_keymap[VK_NUMPAD6] = SDLK_KP6; + VK_keymap[VK_NUMPAD7] = SDLK_KP7; + VK_keymap[VK_NUMPAD8] = SDLK_KP8; + VK_keymap[VK_NUMPAD9] = SDLK_KP9; + VK_keymap[VK_DECIMAL] = SDLK_KP_PERIOD; + VK_keymap[VK_DIVIDE] = SDLK_KP_DIVIDE; + VK_keymap[VK_MULTIPLY] = SDLK_KP_MULTIPLY; + VK_keymap[VK_SUBTRACT] = SDLK_KP_MINUS; + VK_keymap[VK_ADD] = SDLK_KP_PLUS; + + VK_keymap[VK_UP] = SDLK_UP; + VK_keymap[VK_DOWN] = SDLK_DOWN; + VK_keymap[VK_RIGHT] = SDLK_RIGHT; + VK_keymap[VK_LEFT] = SDLK_LEFT; + VK_keymap[VK_INSERT] = SDLK_INSERT; + VK_keymap[VK_HOME] = SDLK_HOME; + VK_keymap[VK_END] = SDLK_END; + VK_keymap[VK_PRIOR] = SDLK_PAGEUP; + VK_keymap[VK_NEXT] = SDLK_PAGEDOWN; + + VK_keymap[VK_F1] = SDLK_F1; + VK_keymap[VK_F2] = SDLK_F2; + VK_keymap[VK_F3] = SDLK_F3; + VK_keymap[VK_F4] = SDLK_F4; + VK_keymap[VK_F5] = SDLK_F5; + VK_keymap[VK_F6] = SDLK_F6; + VK_keymap[VK_F7] = SDLK_F7; + VK_keymap[VK_F8] = SDLK_F8; + VK_keymap[VK_F9] = SDLK_F9; + VK_keymap[VK_F10] = SDLK_F10; + VK_keymap[VK_F11] = SDLK_F11; + VK_keymap[VK_F12] = SDLK_F12; + VK_keymap[VK_F13] = SDLK_F13; + VK_keymap[VK_F14] = SDLK_F14; + VK_keymap[VK_F15] = SDLK_F15; + + VK_keymap[VK_NUMLOCK] = SDLK_NUMLOCK; + VK_keymap[VK_CAPITAL] = SDLK_CAPSLOCK; + VK_keymap[VK_SCROLL] = SDLK_SCROLLOCK; + VK_keymap[VK_RSHIFT] = SDLK_RSHIFT; + VK_keymap[VK_LSHIFT] = SDLK_LSHIFT; + VK_keymap[VK_RCONTROL] = SDLK_RCTRL; + VK_keymap[VK_LCONTROL] = SDLK_LCTRL; + VK_keymap[VK_RMENU] = SDLK_RALT; + VK_keymap[VK_LMENU] = SDLK_LALT; + VK_keymap[VK_RWIN] = SDLK_RSUPER; + VK_keymap[VK_LWIN] = SDLK_LSUPER; + + VK_keymap[VK_HELP] = SDLK_HELP; +#ifdef VK_PRINT + VK_keymap[VK_PRINT] = SDLK_PRINT; +#endif + VK_keymap[VK_SNAPSHOT] = SDLK_PRINT; + VK_keymap[VK_CANCEL] = SDLK_BREAK; + VK_keymap[VK_APPS] = SDLK_MENU; + + Arrows_keymap[3] = 0x25; + Arrows_keymap[2] = 0x26; + Arrows_keymap[1] = 0x27; + Arrows_keymap[0] = 0x28; +} + +#define EXTKEYPAD(keypad) ((scancode & 0x100)?(mvke):(keypad)) + +static int SDL_MapVirtualKey(int scancode, int vkey) +{ +#ifndef _WIN32_WCE + int mvke = MapVirtualKeyEx(scancode & 0xFF, 1, hLayoutUS); +#else + int mvke = MapVirtualKey(scancode & 0xFF, 1); +#endif + + switch(vkey) { + /* These are always correct */ + case VK_DIVIDE: + case VK_MULTIPLY: + case VK_SUBTRACT: + case VK_ADD: + case VK_LWIN: + case VK_RWIN: + case VK_APPS: + /* These are already handled */ + case VK_LCONTROL: + case VK_RCONTROL: + case VK_LSHIFT: + case VK_RSHIFT: + case VK_LMENU: + case VK_RMENU: + case VK_SNAPSHOT: + case VK_PAUSE: + return vkey; + } + switch(mvke) { + /* Distinguish between keypad and extended keys */ + case VK_INSERT: return EXTKEYPAD(VK_NUMPAD0); + case VK_DELETE: return EXTKEYPAD(VK_DECIMAL); + case VK_END: return EXTKEYPAD(VK_NUMPAD1); + case VK_DOWN: return EXTKEYPAD(VK_NUMPAD2); + case VK_NEXT: return EXTKEYPAD(VK_NUMPAD3); + case VK_LEFT: return EXTKEYPAD(VK_NUMPAD4); + case VK_CLEAR: return EXTKEYPAD(VK_NUMPAD5); + case VK_RIGHT: return EXTKEYPAD(VK_NUMPAD6); + case VK_HOME: return EXTKEYPAD(VK_NUMPAD7); + case VK_UP: return EXTKEYPAD(VK_NUMPAD8); + case VK_PRIOR: return EXTKEYPAD(VK_NUMPAD9); + } + return mvke?mvke:vkey; +} + +static SDL_keysym *TranslateKey(WPARAM vkey, UINT scancode, SDL_keysym *keysym, int pressed) +{ + /* Set the keysym information */ + keysym->scancode = (unsigned char) scancode; + keysym->mod = KMOD_NONE; + keysym->unicode = 0; + + if ((vkey == VK_RETURN) && (scancode & 0x100)) { + /* No VK_ code for the keypad enter key */ + keysym->sym = SDLK_KP_ENTER; + } + else { + keysym->sym = VK_keymap[SDL_MapVirtualKey(scancode, vkey)]; + } + + if ( pressed && SDL_TranslateUNICODE ) { +#ifdef NO_GETKEYBOARDSTATE + /* Uh oh, better hope the vkey is close enough.. */ + if((keysym->sym == vkey) || (vkey > 0x7f)) + keysym->unicode = vkey; +#else + BYTE keystate[256]; + Uint16 wchars[2]; + + GetKeyboardState(keystate); + /* Numlock isn't taken into account in ToUnicode, + * so we handle it as a special case here */ + if ((keystate[VK_NUMLOCK] & 1) && vkey >= VK_NUMPAD0 && vkey <= VK_NUMPAD9) + { + keysym->unicode = vkey - VK_NUMPAD0 + '0'; + } + else if (SDL_ToUnicode((UINT)vkey, scancode, keystate, wchars, sizeof(wchars)/sizeof(wchars[0]), 0) > 0) + { + keysym->unicode = wchars[0]; + } +#endif /* NO_GETKEYBOARDSTATE */ + } + +#if 0 + { + HKL hLayoutCurrent = GetKeyboardLayout(0); + int sc = scancode & 0xFF; + + printf("SYM:%d, VK:0x%02X, SC:0x%04X, US:(1:0x%02X, 3:0x%02X), " + "Current:(1:0x%02X, 3:0x%02X)\n", + keysym->sym, vkey, scancode, + MapVirtualKeyEx(sc, 1, hLayoutUS), + MapVirtualKeyEx(sc, 3, hLayoutUS), + MapVirtualKeyEx(sc, 1, hLayoutCurrent), + MapVirtualKeyEx(sc, 3, hLayoutCurrent) + ); + } +#endif + return(keysym); +} + +int DIB_CreateWindow(_THIS) +{ + char *windowid; + + SDL_RegisterApp(NULL, 0, 0); + + windowid = SDL_getenv("SDL_WINDOWID"); + SDL_windowid = (windowid != NULL); + if ( SDL_windowid ) { +#if defined(_WIN32_WCE) && (_WIN32_WCE < 300) + /* wince 2.1 does not have strtol */ + wchar_t *windowid_t = SDL_malloc((SDL_strlen(windowid) + 1) * sizeof(wchar_t)); + MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, windowid, -1, windowid_t, SDL_strlen(windowid) + 1); + SDL_Window = (HWND)wcstol(windowid_t, NULL, 0); + SDL_free(windowid_t); +#else + SDL_Window = (HWND)((size_t)SDL_strtoull(windowid, NULL, 0)); +#endif + if ( SDL_Window == NULL ) { + SDL_SetError("Couldn't get user specified window"); + return(-1); + } + + /* DJM: we want all event's for the user specified + window to be handled by SDL. + */ + userWindowProc = (WNDPROCTYPE)GetWindowLongPtr(SDL_Window, GWLP_WNDPROC); + SetWindowLongPtr(SDL_Window, GWLP_WNDPROC, (LONG_PTR)WinMessage); + } else { + SDL_Window = CreateWindow(SDL_Appname, SDL_Appname, + (WS_OVERLAPPED|WS_CAPTION|WS_SYSMENU|WS_MINIMIZEBOX), + CW_USEDEFAULT, CW_USEDEFAULT, 0, 0, NULL, NULL, SDL_Instance, NULL); + if ( SDL_Window == NULL ) { + SDL_SetError("Couldn't create window"); + return(-1); + } + ShowWindow(SDL_Window, SW_HIDE); + } + + /* JC 14 Mar 2006 + Flush the message loop or this can cause big problems later + Especially if the user decides to use dialog boxes or assert()! + */ + WIN_FlushMessageQueue(); + + return(0); +} + +void DIB_DestroyWindow(_THIS) +{ + if ( SDL_windowid ) { + SetWindowLongPtr(SDL_Window, GWLP_WNDPROC, (LONG_PTR)userWindowProc); + } else { + DestroyWindow(SDL_Window); + } + SDL_UnregisterApp(); + + /* JC 14 Mar 2006 + Flush the message loop or this can cause big problems later + Especially if the user decides to use dialog boxes or assert()! + */ + WIN_FlushMessageQueue(); +} diff --git a/3rdparty/SDL/src/video/windib/SDL_dibevents_c.h b/3rdparty/SDL/src/video/windib/SDL_dibevents_c.h new file mode 100644 index 0000000..236aa68 --- /dev/null +++ b/3rdparty/SDL/src/video/windib/SDL_dibevents_c.h @@ -0,0 +1,35 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#include "../wincommon/SDL_lowvideo.h" + +/* Variables and functions exported by SDL_dibevents.c to other parts + of the native video subsystem (SDL_dibvideo.c) +*/ +extern LONG + DIB_HandleMessage(_THIS, HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam); +extern int DIB_CreateWindow(_THIS); +extern void DIB_DestroyWindow(_THIS); + +extern void DIB_PumpEvents(_THIS); +extern void DIB_InitOSKeymap(_THIS); diff --git a/3rdparty/SDL/src/video/windib/SDL_dibvideo.c b/3rdparty/SDL/src/video/windib/SDL_dibvideo.c new file mode 100644 index 0000000..6187bfc --- /dev/null +++ b/3rdparty/SDL/src/video/windib/SDL_dibvideo.c @@ -0,0 +1,1323 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#define WIN32_LEAN_AND_MEAN +#include <windows.h> + +/* Not yet in the mingw32 cross-compile headers */ +#ifndef CDS_FULLSCREEN +#define CDS_FULLSCREEN 4 +#endif + +#include "SDL_syswm.h" +#include "../SDL_sysvideo.h" +#include "../SDL_pixels_c.h" +#include "../../events/SDL_sysevents.h" +#include "../../events/SDL_events_c.h" +#include "SDL_gapidibvideo.h" +#include "SDL_dibvideo.h" +#include "../wincommon/SDL_syswm_c.h" +#include "../wincommon/SDL_sysmouse_c.h" +#include "SDL_dibevents_c.h" +#include "../wincommon/SDL_wingl_c.h" + +#ifdef _WIN32_WCE + +#ifndef DM_DISPLAYORIENTATION +#define DM_DISPLAYORIENTATION 0x00800000L +#endif +#ifndef DM_DISPLAYQUERYORIENTATION +#define DM_DISPLAYQUERYORIENTATION 0x01000000L +#endif +#ifndef DMDO_0 +#define DMDO_0 0 +#endif +#ifndef DMDO_90 +#define DMDO_90 1 +#endif +#ifndef DMDO_180 +#define DMDO_180 2 +#endif +#ifndef DMDO_270 +#define DMDO_270 4 +#endif + +#define NO_GETDIBITS +#define NO_GAMMA_SUPPORT + #if _WIN32_WCE < 420 + #define NO_CHANGEDISPLAYSETTINGS + #else + #define ChangeDisplaySettings(lpDevMode, dwFlags) ChangeDisplaySettingsEx(NULL, (lpDevMode), 0, (dwFlags), 0) + #endif +#endif +#ifndef WS_MAXIMIZE +#define WS_MAXIMIZE 0 +#endif +#ifndef WS_THICKFRAME +#define WS_THICKFRAME 0 +#endif +#ifndef SWP_NOCOPYBITS +#define SWP_NOCOPYBITS 0 +#endif +#ifndef PC_NOCOLLAPSE +#define PC_NOCOLLAPSE 0 +#endif + +#ifdef _WIN32_WCE +// defined and used in SDL_sysevents.c +extern HINSTANCE aygshell; +#endif + +/* Initialization/Query functions */ +static int DIB_VideoInit(_THIS, SDL_PixelFormat *vformat); +static SDL_Rect **DIB_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags); +SDL_Surface *DIB_SetVideoMode(_THIS, SDL_Surface *current, int width, int height, int bpp, Uint32 flags); +static int DIB_SetColors(_THIS, int firstcolor, int ncolors, + SDL_Color *colors); +static void DIB_CheckGamma(_THIS); +void DIB_SwapGamma(_THIS); +void DIB_QuitGamma(_THIS); +int DIB_SetGammaRamp(_THIS, Uint16 *ramp); +int DIB_GetGammaRamp(_THIS, Uint16 *ramp); +static void DIB_VideoQuit(_THIS); + +/* Hardware surface functions */ +static int DIB_AllocHWSurface(_THIS, SDL_Surface *surface); +static int DIB_LockHWSurface(_THIS, SDL_Surface *surface); +static void DIB_UnlockHWSurface(_THIS, SDL_Surface *surface); +static void DIB_FreeHWSurface(_THIS, SDL_Surface *surface); + +/* Windows message handling functions */ +static void DIB_GrabStaticColors(HWND window); +static void DIB_ReleaseStaticColors(HWND window); +static void DIB_Activate(_THIS, BOOL active, BOOL minimized); +static void DIB_RealizePalette(_THIS); +static void DIB_PaletteChanged(_THIS, HWND window); +static void DIB_WinPAINT(_THIS, HDC hdc); + +/* helper fn */ +static int DIB_SussScreenDepth(); + +/* DIB driver bootstrap functions */ + +static int DIB_Available(void) +{ + return(1); +} + +static void DIB_DeleteDevice(SDL_VideoDevice *device) +{ + if ( device ) { + if ( device->hidden ) { + if ( device->hidden->dibInfo ) { + SDL_free( device->hidden->dibInfo ); + } + SDL_free(device->hidden); + } + if ( device->gl_data ) { + SDL_free(device->gl_data); + } + SDL_free(device); + } +} + +static SDL_VideoDevice *DIB_CreateDevice(int devindex) +{ + SDL_VideoDevice *device; + + /* Initialize all variables that we clean on shutdown */ + device = (SDL_VideoDevice *)SDL_malloc(sizeof(SDL_VideoDevice)); + if ( device ) { + SDL_memset(device, 0, (sizeof *device)); + device->hidden = (struct SDL_PrivateVideoData *) + SDL_malloc((sizeof *device->hidden)); + if(device->hidden){ + SDL_memset(device->hidden, 0, (sizeof *device->hidden)); + device->hidden->dibInfo = (DibInfo *)SDL_malloc((sizeof(DibInfo))); + if(device->hidden->dibInfo == NULL) + { + SDL_free(device->hidden); + device->hidden = NULL; + } + } + + device->gl_data = (struct SDL_PrivateGLData *) + SDL_malloc((sizeof *device->gl_data)); + } + if ( (device == NULL) || (device->hidden == NULL) || + (device->gl_data == NULL) ) { + SDL_OutOfMemory(); + DIB_DeleteDevice(device); + return(NULL); + } + SDL_memset(device->hidden->dibInfo, 0, (sizeof *device->hidden->dibInfo)); + SDL_memset(device->gl_data, 0, (sizeof *device->gl_data)); + + /* Set the function pointers */ + device->VideoInit = DIB_VideoInit; + device->ListModes = DIB_ListModes; + device->SetVideoMode = DIB_SetVideoMode; + device->UpdateMouse = WIN_UpdateMouse; + device->SetColors = DIB_SetColors; + device->UpdateRects = NULL; + device->VideoQuit = DIB_VideoQuit; + device->AllocHWSurface = DIB_AllocHWSurface; + device->CheckHWBlit = NULL; + device->FillHWRect = NULL; + device->SetHWColorKey = NULL; + device->SetHWAlpha = NULL; + device->LockHWSurface = DIB_LockHWSurface; + device->UnlockHWSurface = DIB_UnlockHWSurface; + device->FlipHWSurface = NULL; + device->FreeHWSurface = DIB_FreeHWSurface; + device->SetGammaRamp = DIB_SetGammaRamp; + device->GetGammaRamp = DIB_GetGammaRamp; +#if SDL_VIDEO_OPENGL + device->GL_LoadLibrary = WIN_GL_LoadLibrary; + device->GL_GetProcAddress = WIN_GL_GetProcAddress; + device->GL_GetAttribute = WIN_GL_GetAttribute; + device->GL_MakeCurrent = WIN_GL_MakeCurrent; + device->GL_SwapBuffers = WIN_GL_SwapBuffers; +#endif + device->SetCaption = WIN_SetWMCaption; + device->SetIcon = WIN_SetWMIcon; + device->IconifyWindow = WIN_IconifyWindow; + device->GrabInput = WIN_GrabInput; + device->GetWMInfo = WIN_GetWMInfo; + device->FreeWMCursor = WIN_FreeWMCursor; + device->CreateWMCursor = WIN_CreateWMCursor; + device->ShowWMCursor = WIN_ShowWMCursor; + device->WarpWMCursor = WIN_WarpWMCursor; + device->CheckMouseMode = WIN_CheckMouseMode; + device->InitOSKeymap = DIB_InitOSKeymap; + device->PumpEvents = DIB_PumpEvents; + + /* Set up the windows message handling functions */ + WIN_Activate = DIB_Activate; + WIN_RealizePalette = DIB_RealizePalette; + WIN_PaletteChanged = DIB_PaletteChanged; + WIN_WinPAINT = DIB_WinPAINT; + HandleMessage = DIB_HandleMessage; + + device->free = DIB_DeleteDevice; + + /* We're finally ready */ + return device; +} + +VideoBootStrap WINDIB_bootstrap = { + "windib", "Win95/98/NT/2000/CE GDI", + DIB_Available, DIB_CreateDevice +}; + +static int cmpmodes(const void *va, const void *vb) +{ + SDL_Rect *a = *(SDL_Rect **)va; + SDL_Rect *b = *(SDL_Rect **)vb; + if ( a->w == b->w ) + return b->h - a->h; + else + return b->w - a->w; +} + +static int DIB_AddMode(_THIS, int bpp, int w, int h) +{ + SDL_Rect *mode; + int i, index; + int next_mode; + + /* Check to see if we already have this mode */ + if ( bpp < 8 || bpp > 32 ) { /* Not supported */ + return(0); + } + index = ((bpp+7)/8)-1; + for ( i=0; i<SDL_nummodes[index]; ++i ) { + mode = SDL_modelist[index][i]; + if ( (mode->w == w) && (mode->h == h) ) { + return(0); + } + } + + /* Set up the new video mode rectangle */ + mode = (SDL_Rect *)SDL_malloc(sizeof *mode); + if ( mode == NULL ) { + SDL_OutOfMemory(); + return(-1); + } + mode->x = 0; + mode->y = 0; + mode->w = w; + mode->h = h; + + /* Allocate the new list of modes, and fill in the new mode */ + next_mode = SDL_nummodes[index]; + SDL_modelist[index] = (SDL_Rect **) + SDL_realloc(SDL_modelist[index], (1+next_mode+1)*sizeof(SDL_Rect *)); + if ( SDL_modelist[index] == NULL ) { + SDL_OutOfMemory(); + SDL_nummodes[index] = 0; + SDL_free(mode); + return(-1); + } + SDL_modelist[index][next_mode] = mode; + SDL_modelist[index][next_mode+1] = NULL; + SDL_nummodes[index]++; + + return(0); +} + +static void DIB_CreatePalette(_THIS, int bpp) +{ +/* RJR: March 28, 2000 + moved palette creation here from "DIB_VideoInit" */ + + LOGPALETTE *palette; + HDC hdc; + int ncolors; + + ncolors = (1 << bpp); + palette = (LOGPALETTE *)SDL_malloc(sizeof(*palette)+ + ncolors*sizeof(PALETTEENTRY)); + palette->palVersion = 0x300; + palette->palNumEntries = ncolors; + hdc = GetDC(SDL_Window); + GetSystemPaletteEntries(hdc, 0, ncolors, palette->palPalEntry); + ReleaseDC(SDL_Window, hdc); + screen_pal = CreatePalette(palette); + screen_logpal = palette; +} + +int DIB_VideoInit(_THIS, SDL_PixelFormat *vformat) +{ + const char *env = NULL; +#ifndef NO_CHANGEDISPLAYSETTINGS + int i; + DEVMODE settings; +#endif + + /* Create the window */ + if ( DIB_CreateWindow(this) < 0 ) { + return(-1); + } + +#if !SDL_AUDIO_DISABLED + DX5_SoundFocus(SDL_Window); +#endif + + /* Determine the screen depth */ + vformat->BitsPerPixel = DIB_SussScreenDepth(); + switch (vformat->BitsPerPixel) { + case 15: + vformat->Rmask = 0x00007c00; + vformat->Gmask = 0x000003e0; + vformat->Bmask = 0x0000001f; + vformat->BitsPerPixel = 16; + break; + case 16: + vformat->Rmask = 0x0000f800; + vformat->Gmask = 0x000007e0; + vformat->Bmask = 0x0000001f; + break; + case 24: + case 32: + /* GDI defined as 8-8-8 */ + vformat->Rmask = 0x00ff0000; + vformat->Gmask = 0x0000ff00; + vformat->Bmask = 0x000000ff; + break; + default: + break; + } + + /* See if gamma is supported on this screen */ + DIB_CheckGamma(this); + +#ifndef NO_CHANGEDISPLAYSETTINGS + + settings.dmSize = sizeof(DEVMODE); + settings.dmDriverExtra = 0; +#ifdef _WIN32_WCE + settings.dmFields = DM_DISPLAYQUERYORIENTATION; + this->hidden->supportRotation = ChangeDisplaySettingsEx(NULL, &settings, NULL, CDS_TEST, NULL) == DISP_CHANGE_SUCCESSFUL; +#endif + /* Query for the desktop resolution */ + SDL_desktop_mode.dmSize = sizeof(SDL_desktop_mode); + SDL_desktop_mode.dmDriverExtra = 0; + EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &SDL_desktop_mode); + this->info.current_w = SDL_desktop_mode.dmPelsWidth; + this->info.current_h = SDL_desktop_mode.dmPelsHeight; + + /* Query for the list of available video modes */ + for ( i=0; EnumDisplaySettings(NULL, i, &settings); ++i ) { + DIB_AddMode(this, settings.dmBitsPerPel, + settings.dmPelsWidth, settings.dmPelsHeight); +#ifdef _WIN32_WCE + if( this->hidden->supportRotation ) + DIB_AddMode(this, settings.dmBitsPerPel, + settings.dmPelsHeight, settings.dmPelsWidth); +#endif + } + /* Sort the mode lists */ + for ( i=0; i<NUM_MODELISTS; ++i ) { + if ( SDL_nummodes[i] > 0 ) { + SDL_qsort(SDL_modelist[i], SDL_nummodes[i], sizeof *SDL_modelist[i], cmpmodes); + } + } +#else + // WinCE and fullscreen mode: + // We use only vformat->BitsPerPixel that allow SDL to + // emulate other bpp (8, 32) and use triple buffer, + // because SDL surface conversion is much faster than the WinCE one. + // Although it should be tested on devices with graphics accelerator. + + DIB_AddMode(this, vformat->BitsPerPixel, + GetDeviceCaps(GetDC(NULL), HORZRES), + GetDeviceCaps(GetDC(NULL), VERTRES)); + +#endif /* !NO_CHANGEDISPLAYSETTINGS */ + + /* Grab an identity palette if we are in a palettized mode */ + if ( vformat->BitsPerPixel <= 8 ) { + /* RJR: March 28, 2000 + moved palette creation to "DIB_CreatePalette" */ + DIB_CreatePalette(this, vformat->BitsPerPixel); + } + + /* Fill in some window manager capabilities */ + this->info.wm_available = 1; + +#ifdef _WIN32_WCE + this->hidden->origRotation = -1; +#endif + + /* Allow environment override of screensaver disable. */ + env = SDL_getenv("SDL_VIDEO_ALLOW_SCREENSAVER"); + if ( env ) { + allow_screensaver = SDL_atoi(env); + } else { +#ifdef SDL_VIDEO_DISABLE_SCREENSAVER + allow_screensaver = 0; +#else + allow_screensaver = 1; +#endif + } + + /* We're done! */ + return(0); +} + +/* We support any format at any dimension */ +SDL_Rect **DIB_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags) +{ + if ( (flags & SDL_FULLSCREEN) == SDL_FULLSCREEN ) { + return(SDL_modelist[((format->BitsPerPixel+7)/8)-1]); + } else { + return((SDL_Rect **)-1); + } +} + + +/* + Helper fn to work out which screen depth windows is currently using. + 15 bit mode is considered 555 format, 16 bit is 565. + returns 0 for unknown mode. + (Derived from code in sept 1999 Windows Developer Journal + http://www.wdj.com/code/archive.html) +*/ +static int DIB_SussScreenDepth() +{ +#ifdef NO_GETDIBITS + int depth; + HDC hdc; + + hdc = GetDC(SDL_Window); + depth = GetDeviceCaps(hdc, PLANES) * GetDeviceCaps(hdc, BITSPIXEL); + ReleaseDC(SDL_Window, hdc); + return(depth); +#else + int depth; + int dib_size; + LPBITMAPINFOHEADER dib_hdr; + HDC hdc; + HBITMAP hbm; + + /* Allocate enough space for a DIB header plus palette (for + * 8-bit modes) or bitfields (for 16- and 32-bit modes) + */ + dib_size = sizeof(BITMAPINFOHEADER) + 256 * sizeof (RGBQUAD); + dib_hdr = (LPBITMAPINFOHEADER) SDL_malloc(dib_size); + SDL_memset(dib_hdr, 0, dib_size); + dib_hdr->biSize = sizeof(BITMAPINFOHEADER); + + /* Get a device-dependent bitmap that's compatible with the + screen. + */ + hdc = GetDC(NULL); + hbm = CreateCompatibleBitmap( hdc, 1, 1 ); + + /* Convert the DDB to a DIB. We need to call GetDIBits twice: + * the first call just fills in the BITMAPINFOHEADER; the + * second fills in the bitfields or palette. + */ + GetDIBits(hdc, hbm, 0, 1, NULL, (LPBITMAPINFO) dib_hdr, DIB_RGB_COLORS); + GetDIBits(hdc, hbm, 0, 1, NULL, (LPBITMAPINFO) dib_hdr, DIB_RGB_COLORS); + DeleteObject(hbm); + ReleaseDC(NULL, hdc); + + depth = 0; + switch( dib_hdr->biBitCount ) + { + case 8: depth = 8; break; + case 24: depth = 24; break; + case 32: depth = 32; break; + case 16: + if( dib_hdr->biCompression == BI_BITFIELDS ) { + /* check the red mask */ + switch( ((DWORD*)((char*)dib_hdr + dib_hdr->biSize))[0] ) { + case 0xf800: depth = 16; break; /* 565 */ + case 0x7c00: depth = 15; break; /* 555 */ + } + } + } + SDL_free(dib_hdr); + return depth; +#endif /* NO_GETDIBITS */ +} + + +/* Various screen update functions available */ +static void DIB_NormalUpdate(_THIS, int numrects, SDL_Rect *rects); + +static void DIB_ResizeWindow(_THIS, int width, int height, int prev_width, int prev_height, Uint32 flags) +{ + RECT bounds; + int x, y; + +#ifndef _WIN32_WCE + /* Resize the window */ + if ( !SDL_windowid && !IsZoomed(SDL_Window) ) { +#else + if ( !SDL_windowid ) { +#endif + HWND top; + UINT swp_flags; + const char *window = NULL; + const char *center = NULL; + + if ( width != prev_width || height != prev_height ) { + window = SDL_getenv("SDL_VIDEO_WINDOW_POS"); + center = SDL_getenv("SDL_VIDEO_CENTERED"); + if ( window ) { + if ( SDL_sscanf(window, "%d,%d", &x, &y) == 2 ) { + SDL_windowX = x; + SDL_windowY = y; + } + if ( SDL_strcmp(window, "center") == 0 ) { + center = window; + } + } + } + swp_flags = (SWP_NOCOPYBITS | SWP_SHOWWINDOW); + + bounds.left = SDL_windowX; + bounds.top = SDL_windowY; + bounds.right = SDL_windowX+width; + bounds.bottom = SDL_windowY+height; +#ifndef _WIN32_WCE + AdjustWindowRectEx(&bounds, GetWindowLong(SDL_Window, GWL_STYLE), (GetMenu(SDL_Window) != NULL), 0); +#else + // The bMenu parameter must be FALSE; menu bars are not supported + AdjustWindowRectEx(&bounds, GetWindowLong(SDL_Window, GWL_STYLE), 0, 0); +#endif + width = bounds.right-bounds.left; + height = bounds.bottom-bounds.top; + if ( (flags & SDL_FULLSCREEN) ) { + x = (GetSystemMetrics(SM_CXSCREEN)-width)/2; + y = (GetSystemMetrics(SM_CYSCREEN)-height)/2; + } else if ( center ) { + x = (GetSystemMetrics(SM_CXSCREEN)-width)/2; + y = (GetSystemMetrics(SM_CYSCREEN)-height)/2; + } else if ( SDL_windowX || SDL_windowY || window ) { + x = bounds.left; + y = bounds.top; + } else { + x = y = -1; + swp_flags |= SWP_NOMOVE; + } + if ( flags & SDL_FULLSCREEN ) { + top = HWND_TOPMOST; + } else { + top = HWND_NOTOPMOST; + } + SetWindowPos(SDL_Window, top, x, y, width, height, swp_flags); + if ( !(flags & SDL_FULLSCREEN) ) { + SDL_windowX = SDL_bounds.left; + SDL_windowY = SDL_bounds.top; + } + if ( GetParent(SDL_Window) == NULL ) { + SetForegroundWindow(SDL_Window); + } + } +} + +SDL_Surface *DIB_SetVideoMode(_THIS, SDL_Surface *current, + int width, int height, int bpp, Uint32 flags) +{ + SDL_Surface *video; + int prev_w, prev_h; + Uint32 prev_flags; + DWORD style; + const DWORD directstyle = + (WS_POPUP); + const DWORD windowstyle = + (WS_OVERLAPPED|WS_CAPTION|WS_SYSMENU|WS_MINIMIZEBOX); + const DWORD resizestyle = + (WS_THICKFRAME|WS_MAXIMIZEBOX); + int binfo_size; + BITMAPINFO *binfo; + HDC hdc; + Uint32 Rmask, Gmask, Bmask; + + prev_w = current->w; + prev_h = current->h; + prev_flags = current->flags; + + /* + * Special case for OpenGL windows...since the app needs to call + * SDL_SetVideoMode() in response to resize events to continue to + * function, but WGL handles the GL context details behind the scenes, + * there's no sense in tearing the context down just to rebuild it + * to what it already was...tearing it down sacrifices your GL state + * and uploaded textures. So if we're requesting the same video mode + * attributes just resize the window and return immediately. + */ + if ( SDL_Window && + ((current->flags & ~SDL_ANYFORMAT) == (flags & ~SDL_ANYFORMAT)) && + (current->format->BitsPerPixel == bpp) && + (flags & SDL_OPENGL) && + !(flags & SDL_FULLSCREEN) ) { /* probably not safe for fs */ + current->w = width; + current->h = height; + SDL_resizing = 1; + DIB_ResizeWindow(this, width, height, prev_w, prev_h, flags); + SDL_resizing = 0; + return current; + } + + /* Clean up any GL context that may be hanging around */ + if ( current->flags & SDL_OPENGL ) { + WIN_GL_ShutDown(this); + } + SDL_resizing = 1; + + /* Recalculate the bitmasks if necessary */ + if ( bpp == current->format->BitsPerPixel ) { + video = current; + } else { + switch (bpp) { + case 15: + case 16: + if ( DIB_SussScreenDepth() == 15 ) { + /* 5-5-5 */ + Rmask = 0x00007c00; + Gmask = 0x000003e0; + Bmask = 0x0000001f; + } else { + /* 5-6-5 */ + Rmask = 0x0000f800; + Gmask = 0x000007e0; + Bmask = 0x0000001f; + } + break; + case 24: + case 32: + /* GDI defined as 8-8-8 */ + Rmask = 0x00ff0000; + Gmask = 0x0000ff00; + Bmask = 0x000000ff; + break; + default: + Rmask = 0x00000000; + Gmask = 0x00000000; + Bmask = 0x00000000; + break; + } + video = SDL_CreateRGBSurface(SDL_SWSURFACE, + 0, 0, bpp, Rmask, Gmask, Bmask, 0); + if ( video == NULL ) { + SDL_OutOfMemory(); + return(NULL); + } + } + + /* Fill in part of the video surface */ + video->flags = 0; /* Clear flags */ + video->w = width; + video->h = height; + video->pitch = SDL_CalculatePitch(video); + + /* Small fix for WinCE/Win32 - when activating window + SDL_VideoSurface is equal to zero, so activating code + is not called properly for fullscreen windows because + macros WINDIB_FULLSCREEN uses SDL_VideoSurface + */ + SDL_VideoSurface = video; + +#if defined(_WIN32_WCE) + if ( flags & SDL_FULLSCREEN ) + video->flags |= SDL_FULLSCREEN; +#endif + +#ifndef NO_CHANGEDISPLAYSETTINGS + /* Set fullscreen mode if appropriate */ + if ( (flags & SDL_FULLSCREEN) == SDL_FULLSCREEN ) { + DEVMODE settings; + BOOL changed; + + SDL_memset(&settings, 0, sizeof(DEVMODE)); + settings.dmSize = sizeof(DEVMODE); + +#ifdef _WIN32_WCE + // try to rotate screen to fit requested resolution + if( this->hidden->supportRotation ) + { + DWORD rotation; + + // ask current mode + settings.dmFields = DM_DISPLAYORIENTATION; + ChangeDisplaySettingsEx(NULL, &settings, NULL, CDS_TEST, NULL); + rotation = settings.dmDisplayOrientation; + + if( (width > GetDeviceCaps(GetDC(NULL), HORZRES)) + && (height < GetDeviceCaps(GetDC(NULL), VERTRES))) + { + switch( rotation ) + { + case DMDO_0: + settings.dmDisplayOrientation = DMDO_90; + break; + case DMDO_270: + settings.dmDisplayOrientation = DMDO_180; + break; + } + if( settings.dmDisplayOrientation != rotation ) + { + // go to landscape + this->hidden->origRotation = rotation; + ChangeDisplaySettingsEx(NULL,&settings,NULL,CDS_RESET,NULL); + } + } + if( (width < GetDeviceCaps(GetDC(NULL), HORZRES)) + && (height > GetDeviceCaps(GetDC(NULL), VERTRES))) + { + switch( rotation ) + { + case DMDO_90: + settings.dmDisplayOrientation = DMDO_0; + break; + case DMDO_180: + settings.dmDisplayOrientation = DMDO_270; + break; + } + if( settings.dmDisplayOrientation != rotation ) + { + // go to portrait + this->hidden->origRotation = rotation; + ChangeDisplaySettingsEx(NULL,&settings,NULL,CDS_RESET,NULL); + } + } + + } +#endif + +#ifndef _WIN32_WCE + settings.dmBitsPerPel = video->format->BitsPerPixel; + settings.dmPelsWidth = width; + settings.dmPelsHeight = height; + settings.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT | DM_BITSPERPEL; + if ( width <= (int)SDL_desktop_mode.dmPelsWidth && + height <= (int)SDL_desktop_mode.dmPelsHeight ) { + settings.dmDisplayFrequency = SDL_desktop_mode.dmDisplayFrequency; + settings.dmFields |= DM_DISPLAYFREQUENCY; + } + changed = (ChangeDisplaySettings(&settings, CDS_FULLSCREEN) == DISP_CHANGE_SUCCESSFUL); + if ( ! changed && (settings.dmFields & DM_DISPLAYFREQUENCY) ) { + settings.dmFields &= ~DM_DISPLAYFREQUENCY; + changed = (ChangeDisplaySettings(&settings, CDS_FULLSCREEN) == DISP_CHANGE_SUCCESSFUL); + } +#else + changed = 1; +#endif + if ( changed ) { + video->flags |= SDL_FULLSCREEN; + SDL_fullscreen_mode = settings; + } + + } +#endif /* !NO_CHANGEDISPLAYSETTINGS */ + + /* Reset the palette and create a new one if necessary */ + if ( grab_palette ) { + DIB_ReleaseStaticColors(SDL_Window); + grab_palette = FALSE; + } + if ( screen_pal != NULL ) { + /* RJR: March 28, 2000 + delete identity palette if switching from a palettized mode */ + DeleteObject(screen_pal); + screen_pal = NULL; + } + if ( screen_logpal != NULL ) { + SDL_free(screen_logpal); + screen_logpal = NULL; + } + + if ( bpp <= 8 ) + { + /* RJR: March 28, 2000 + create identity palette switching to a palettized mode */ + DIB_CreatePalette(this, bpp); + } + + style = GetWindowLong(SDL_Window, GWL_STYLE); + style &= ~(resizestyle|WS_MAXIMIZE); + if ( (video->flags & SDL_FULLSCREEN) == SDL_FULLSCREEN ) { + style &= ~windowstyle; + style |= directstyle; + } else { +#ifndef NO_CHANGEDISPLAYSETTINGS + if ( (prev_flags & SDL_FULLSCREEN) == SDL_FULLSCREEN ) { + ChangeDisplaySettings(NULL, 0); + } +#endif + if ( flags & SDL_NOFRAME ) { + style &= ~windowstyle; + style |= directstyle; + video->flags |= SDL_NOFRAME; + } else { + style &= ~directstyle; + style |= windowstyle; + if ( flags & SDL_RESIZABLE ) { + style |= resizestyle; + video->flags |= SDL_RESIZABLE; + } + } +#if WS_MAXIMIZE && !defined(_WIN32_WCE) + if (IsZoomed(SDL_Window)) style |= WS_MAXIMIZE; +#endif + } + + /* DJM: Don't piss of anyone who has setup his own window */ + if ( !SDL_windowid ) + SetWindowLong(SDL_Window, GWL_STYLE, style); + + /* Delete the old bitmap if necessary */ + if ( screen_bmp != NULL ) { + DeleteObject(screen_bmp); + } + if ( ! (flags & SDL_OPENGL) ) { + BOOL is16bitmode = (video->format->BytesPerPixel == 2); + + /* Suss out the bitmap info header */ + binfo_size = sizeof(*binfo); + if( is16bitmode ) { + /* 16bit modes, palette area used for rgb bitmasks */ + binfo_size += 3*sizeof(DWORD); + } else if ( video->format->palette ) { + binfo_size += video->format->palette->ncolors * + sizeof(RGBQUAD); + } + binfo = (BITMAPINFO *)SDL_malloc(binfo_size); + if ( ! binfo ) { + if ( video != current ) { + SDL_FreeSurface(video); + } + SDL_OutOfMemory(); + return(NULL); + } + + binfo->bmiHeader.biSize = sizeof(BITMAPINFOHEADER); + binfo->bmiHeader.biWidth = video->w; + binfo->bmiHeader.biHeight = -video->h; /* -ve for topdown bitmap */ + binfo->bmiHeader.biPlanes = 1; + binfo->bmiHeader.biSizeImage = video->h * video->pitch; + binfo->bmiHeader.biXPelsPerMeter = 0; + binfo->bmiHeader.biYPelsPerMeter = 0; + binfo->bmiHeader.biClrUsed = 0; + binfo->bmiHeader.biClrImportant = 0; + binfo->bmiHeader.biBitCount = video->format->BitsPerPixel; + + if ( is16bitmode ) { + /* BI_BITFIELDS tells CreateDIBSection about the rgb masks in the palette */ + binfo->bmiHeader.biCompression = BI_BITFIELDS; + ((Uint32*)binfo->bmiColors)[0] = video->format->Rmask; + ((Uint32*)binfo->bmiColors)[1] = video->format->Gmask; + ((Uint32*)binfo->bmiColors)[2] = video->format->Bmask; + } else { + binfo->bmiHeader.biCompression = BI_RGB; /* BI_BITFIELDS for 565 vs 555 */ + if ( video->format->palette ) { + SDL_memset(binfo->bmiColors, 0, + video->format->palette->ncolors*sizeof(RGBQUAD)); + } + } + + /* Create the offscreen bitmap buffer */ + hdc = GetDC(SDL_Window); + screen_bmp = CreateDIBSection(hdc, binfo, DIB_RGB_COLORS, + (void **)(&video->pixels), NULL, 0); + ReleaseDC(SDL_Window, hdc); + SDL_free(binfo); + if ( screen_bmp == NULL ) { + if ( video != current ) { + SDL_FreeSurface(video); + } + SDL_SetError("Couldn't create DIB section"); + return(NULL); + } + this->UpdateRects = DIB_NormalUpdate; + + /* Set video surface flags */ + if ( screen_pal && (flags & (SDL_FULLSCREEN|SDL_HWPALETTE)) ) { + grab_palette = TRUE; + } + if ( screen_pal ) { + /* BitBlt() maps colors for us */ + video->flags |= SDL_HWPALETTE; + } + } + DIB_ResizeWindow(this, width, height, prev_w, prev_h, flags); + SDL_resizing = 0; + + /* Set up for OpenGL */ + if ( flags & SDL_OPENGL ) { + if ( WIN_GL_SetupWindow(this) < 0 ) { + return(NULL); + } + video->flags |= SDL_OPENGL; + } + + /* JC 14 Mar 2006 + Flush the message loop or this can cause big problems later + Especially if the user decides to use dialog boxes or assert()! + */ + WIN_FlushMessageQueue(); + + /* We're live! */ + return(video); +} + +/* We don't actually allow hardware surfaces in the DIB driver */ +static int DIB_AllocHWSurface(_THIS, SDL_Surface *surface) +{ + return(-1); +} +static void DIB_FreeHWSurface(_THIS, SDL_Surface *surface) +{ + return; +} +static int DIB_LockHWSurface(_THIS, SDL_Surface *surface) +{ + return(0); +} +static void DIB_UnlockHWSurface(_THIS, SDL_Surface *surface) +{ + return; +} + +static void DIB_NormalUpdate(_THIS, int numrects, SDL_Rect *rects) +{ + HDC hdc, mdc; + int i; + + hdc = GetDC(SDL_Window); + if ( screen_pal ) { + SelectPalette(hdc, screen_pal, FALSE); + } + mdc = CreateCompatibleDC(hdc); + SelectObject(mdc, screen_bmp); + for ( i=0; i<numrects; ++i ) { + BitBlt(hdc, rects[i].x, rects[i].y, rects[i].w, rects[i].h, + mdc, rects[i].x, rects[i].y, SRCCOPY); + } + DeleteDC(mdc); + ReleaseDC(SDL_Window, hdc); +} + +static int FindPaletteIndex(LOGPALETTE *pal, BYTE r, BYTE g, BYTE b) +{ + PALETTEENTRY *entry; + int i; + int nentries = pal->palNumEntries; + + for ( i = 0; i < nentries; ++i ) { + entry = &pal->palPalEntry[i]; + if ( entry->peRed == r && entry->peGreen == g && entry->peBlue == b ) { + return i; + } + } + return -1; +} + +static BOOL CheckPaletteEntry(LOGPALETTE *pal, int index, BYTE r, BYTE g, BYTE b) +{ + PALETTEENTRY *entry; + BOOL moved = 0; + + entry = &pal->palPalEntry[index]; + if ( entry->peRed != r || entry->peGreen != g || entry->peBlue != b ) { + int found = FindPaletteIndex(pal, r, g, b); + if ( found >= 0 ) { + pal->palPalEntry[found] = *entry; + } + entry->peRed = r; + entry->peGreen = g; + entry->peBlue = b; + moved = 1; + } + entry->peFlags = 0; + + return moved; +} + +int DIB_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors) +{ +#if !defined(_WIN32_WCE) || (_WIN32_WCE >= 400) + HDC hdc, mdc; + RGBQUAD *pal; +#else + HDC hdc; +#endif + int i; + int moved_entries = 0; + + /* Update the display palette */ + hdc = GetDC(SDL_Window); + if ( screen_pal ) { + PALETTEENTRY *entry; + + for ( i=0; i<ncolors; ++i ) { + entry = &screen_logpal->palPalEntry[firstcolor+i]; + entry->peRed = colors[i].r; + entry->peGreen = colors[i].g; + entry->peBlue = colors[i].b; + entry->peFlags = PC_NOCOLLAPSE; + } +#if defined(SYSPAL_NOSTATIC) && !defined(_WIN32_WCE) + /* Check to make sure black and white are in position */ + if ( GetSystemPaletteUse(hdc) != SYSPAL_NOSTATIC256 ) { + moved_entries += CheckPaletteEntry(screen_logpal, 0, 0x00, 0x00, 0x00); + moved_entries += CheckPaletteEntry(screen_logpal, screen_logpal->palNumEntries-1, 0xff, 0xff, 0xff); + } + /* FIXME: + If we don't have full access to the palette, what we + really want to do is find the 236 most diverse colors + in the desired palette, set those entries (10-245) and + then map everything into the new system palette. + */ +#endif + +#ifndef _WIN32_WCE + /* Copy the entries into the system palette */ + UnrealizeObject(screen_pal); +#endif + SetPaletteEntries(screen_pal, 0, screen_logpal->palNumEntries, screen_logpal->palPalEntry); + SelectPalette(hdc, screen_pal, FALSE); + RealizePalette(hdc); + } + +#if !defined(_WIN32_WCE) || (_WIN32_WCE >= 400) + /* Copy palette colors into DIB palette */ + pal = SDL_stack_alloc(RGBQUAD, ncolors); + for ( i=0; i<ncolors; ++i ) { + pal[i].rgbRed = colors[i].r; + pal[i].rgbGreen = colors[i].g; + pal[i].rgbBlue = colors[i].b; + pal[i].rgbReserved = 0; + } + + /* Set the DIB palette and update the display */ + mdc = CreateCompatibleDC(hdc); + SelectObject(mdc, screen_bmp); + SetDIBColorTable(mdc, firstcolor, ncolors, pal); + if ( moved_entries || !grab_palette ) { + BitBlt(hdc, 0, 0, this->screen->w, this->screen->h, + mdc, 0, 0, SRCCOPY); + } + DeleteDC(mdc); + SDL_stack_free(pal); +#endif + ReleaseDC(SDL_Window, hdc); + return(1); +} + + +static void DIB_CheckGamma(_THIS) +{ +#ifndef NO_GAMMA_SUPPORT + HDC hdc; + WORD ramp[3*256]; + + /* If we fail to get gamma, disable gamma control */ + hdc = GetDC(SDL_Window); + if ( ! GetDeviceGammaRamp(hdc, ramp) ) { + this->GetGammaRamp = NULL; + this->SetGammaRamp = NULL; + } + ReleaseDC(SDL_Window, hdc); +#endif /* !NO_GAMMA_SUPPORT */ +} +void DIB_SwapGamma(_THIS) +{ +#ifndef NO_GAMMA_SUPPORT + HDC hdc; + + if ( gamma_saved ) { + hdc = GetDC(SDL_Window); + if ( SDL_GetAppState() & SDL_APPINPUTFOCUS ) { + /* About to leave active state, restore gamma */ + SetDeviceGammaRamp(hdc, gamma_saved); + } else { + /* About to enter active state, set game gamma */ + GetDeviceGammaRamp(hdc, gamma_saved); + SetDeviceGammaRamp(hdc, this->gamma); + } + ReleaseDC(SDL_Window, hdc); + } +#endif /* !NO_GAMMA_SUPPORT */ +} +void DIB_QuitGamma(_THIS) +{ +#ifndef NO_GAMMA_SUPPORT + if ( gamma_saved ) { + /* Restore the original gamma if necessary */ + if ( SDL_GetAppState() & SDL_APPINPUTFOCUS ) { + HDC hdc; + + hdc = GetDC(SDL_Window); + SetDeviceGammaRamp(hdc, gamma_saved); + ReleaseDC(SDL_Window, hdc); + } + + /* Free the saved gamma memory */ + SDL_free(gamma_saved); + gamma_saved = 0; + } +#endif /* !NO_GAMMA_SUPPORT */ +} + +int DIB_SetGammaRamp(_THIS, Uint16 *ramp) +{ +#ifdef NO_GAMMA_SUPPORT + SDL_SetError("SDL compiled without gamma ramp support"); + return -1; +#else + HDC hdc; + BOOL succeeded; + + /* Set the ramp for the display */ + if ( ! gamma_saved ) { + gamma_saved = (WORD *)SDL_malloc(3*256*sizeof(*gamma_saved)); + if ( ! gamma_saved ) { + SDL_OutOfMemory(); + return -1; + } + hdc = GetDC(SDL_Window); + GetDeviceGammaRamp(hdc, gamma_saved); + ReleaseDC(SDL_Window, hdc); + } + if ( SDL_GetAppState() & SDL_APPINPUTFOCUS ) { + hdc = GetDC(SDL_Window); + succeeded = SetDeviceGammaRamp(hdc, ramp); + ReleaseDC(SDL_Window, hdc); + } else { + succeeded = TRUE; + } + return succeeded ? 0 : -1; +#endif /* !NO_GAMMA_SUPPORT */ +} + +int DIB_GetGammaRamp(_THIS, Uint16 *ramp) +{ +#ifdef NO_GAMMA_SUPPORT + SDL_SetError("SDL compiled without gamma ramp support"); + return -1; +#else + HDC hdc; + BOOL succeeded; + + /* Get the ramp from the display */ + hdc = GetDC(SDL_Window); + succeeded = GetDeviceGammaRamp(hdc, ramp); + ReleaseDC(SDL_Window, hdc); + return succeeded ? 0 : -1; +#endif /* !NO_GAMMA_SUPPORT */ +} + +void DIB_VideoQuit(_THIS) +{ + int i, j; + + /* Destroy the window and everything associated with it */ + if ( SDL_Window ) { + /* Delete the screen bitmap (also frees screen->pixels) */ + if ( this->screen ) { + if ( grab_palette ) { + DIB_ReleaseStaticColors(SDL_Window); + } +#ifndef NO_CHANGEDISPLAYSETTINGS + if ( this->screen->flags & SDL_FULLSCREEN ) { + ChangeDisplaySettings(NULL, 0); + ShowWindow(SDL_Window, SW_HIDE); + } +#endif + if ( this->screen->flags & SDL_OPENGL ) { + WIN_GL_ShutDown(this); + } + this->screen->pixels = NULL; + } + if ( screen_pal != NULL ) { + DeleteObject(screen_pal); + screen_pal = NULL; + } + if ( screen_logpal != NULL ) { + SDL_free(screen_logpal); + screen_logpal = NULL; + } + if ( screen_bmp ) { + DeleteObject(screen_bmp); + screen_bmp = NULL; + } + if ( screen_icn ) { + DestroyIcon(screen_icn); + screen_icn = NULL; + } + DIB_QuitGamma(this); + DIB_DestroyWindow(this); + + SDL_Window = NULL; + +#if defined(_WIN32_WCE) + +// Unload wince aygshell library to prevent leak + if( aygshell ) + { + FreeLibrary(aygshell); + aygshell = NULL; + } +#endif + } + + for ( i=0; i < SDL_arraysize(SDL_modelist); ++i ) { + if ( !SDL_modelist[i] ) { + continue; + } + for ( j=0; SDL_modelist[i][j]; ++j ) { + SDL_free(SDL_modelist[i][j]); + } + SDL_free(SDL_modelist[i]); + SDL_modelist[i] = NULL; + SDL_nummodes[i] = 0; + } +} + +/* Exported for the windows message loop only */ +static void DIB_GrabStaticColors(HWND window) +{ +#if defined(SYSPAL_NOSTATIC) && !defined(_WIN32_WCE) + HDC hdc; + + hdc = GetDC(window); + SetSystemPaletteUse(hdc, SYSPAL_NOSTATIC256); + if ( GetSystemPaletteUse(hdc) != SYSPAL_NOSTATIC256 ) { + SetSystemPaletteUse(hdc, SYSPAL_NOSTATIC); + } + ReleaseDC(window, hdc); +#endif +} +static void DIB_ReleaseStaticColors(HWND window) +{ +#if defined(SYSPAL_NOSTATIC) && !defined(_WIN32_WCE) + HDC hdc; + + hdc = GetDC(window); + SetSystemPaletteUse(hdc, SYSPAL_STATIC); + ReleaseDC(window, hdc); +#endif +} +static void DIB_Activate(_THIS, BOOL active, BOOL minimized) +{ + if ( grab_palette ) { + if ( !active ) { + DIB_ReleaseStaticColors(SDL_Window); + DIB_RealizePalette(this); + } else if ( !minimized ) { + DIB_GrabStaticColors(SDL_Window); + DIB_RealizePalette(this); + } + } +} +static void DIB_RealizePalette(_THIS) +{ + if ( screen_pal != NULL ) { + HDC hdc; + + hdc = GetDC(SDL_Window); +#ifndef _WIN32_WCE + UnrealizeObject(screen_pal); +#endif + SelectPalette(hdc, screen_pal, FALSE); + if ( RealizePalette(hdc) ) { + InvalidateRect(SDL_Window, NULL, FALSE); + } + ReleaseDC(SDL_Window, hdc); + } +} +static void DIB_PaletteChanged(_THIS, HWND window) +{ + if ( window != SDL_Window ) { + DIB_RealizePalette(this); + } +} + +/* Exported for the windows message loop only */ +static void DIB_WinPAINT(_THIS, HDC hdc) +{ + HDC mdc; + + if ( screen_pal ) { + SelectPalette(hdc, screen_pal, FALSE); + } + mdc = CreateCompatibleDC(hdc); + SelectObject(mdc, screen_bmp); + BitBlt(hdc, 0, 0, SDL_VideoSurface->w, SDL_VideoSurface->h, + mdc, 0, 0, SRCCOPY); + DeleteDC(mdc); +} + +/* Stub in case DirectX isn't available */ +#if !SDL_AUDIO_DRIVER_DSOUND +void DX5_SoundFocus(HWND hwnd) +{ + return; +} +#endif diff --git a/3rdparty/SDL/src/video/windib/SDL_dibvideo.h b/3rdparty/SDL/src/video/windib/SDL_dibvideo.h new file mode 100644 index 0000000..48b1943 --- /dev/null +++ b/3rdparty/SDL/src/video/windib/SDL_dibvideo.h @@ -0,0 +1,59 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#ifndef _SDL_dibvideo_h +#define _SDL_dibvideo_h + +#define WIN32_LEAN_AND_MEAN +#include <windows.h> + + +/* Private display data */ +struct DibInfo { + HBITMAP screen_bmp; + HPALETTE screen_pal; + LOGPALETTE *screen_logpal; + BOOL grab_palette; + +#define NUM_MODELISTS 4 /* 8, 16, 24, and 32 bits-per-pixel */ + int SDL_nummodes[NUM_MODELISTS]; + SDL_Rect **SDL_modelist[NUM_MODELISTS]; + +#ifdef _WIN32_WCE + int supportRotation; /* for Pocket PC devices */ + DWORD origRotation; /* for Pocket PC devices */ +#endif + + /* Screensaver settings */ + int allow_screensaver; +}; +/* Old variable names */ +#define screen_bmp (this->hidden->dibInfo->screen_bmp) +#define screen_pal (this->hidden->dibInfo->screen_pal) +#define screen_logpal (this->hidden->dibInfo->screen_logpal) +#define grab_palette (this->hidden->dibInfo->grab_palette) +#define SDL_nummodes (this->hidden->dibInfo->SDL_nummodes) +#define SDL_modelist (this->hidden->dibInfo->SDL_modelist) +#define allow_screensaver (this->hidden->dibInfo->allow_screensaver) + +#endif /* _SDL_dibvideo_h */ diff --git a/3rdparty/SDL/src/video/windib/SDL_gapidibvideo.h b/3rdparty/SDL/src/video/windib/SDL_gapidibvideo.h new file mode 100644 index 0000000..64743d1 --- /dev/null +++ b/3rdparty/SDL/src/video/windib/SDL_gapidibvideo.h @@ -0,0 +1,56 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#ifndef _SDL_gapidibvideo_h +#define _SDL_gapidibvideo_h + +#define WIN32_LEAN_AND_MEAN +#include <windows.h> + +/* Hidden "this" pointer for the video functions */ +#define _THIS SDL_VideoDevice *this + +/* typedef these to be able to define pointers, but still force everybody who + * wants to access them to include the corresponding header */ +typedef struct GapiInfo GapiInfo; +typedef struct DibInfo DibInfo; + +/* for PDA */ +typedef enum +{ + SDL_ORIENTATION_UP, + SDL_ORIENTATION_DOWN, + SDL_ORIENTATION_LEFT, + SDL_ORIENTATION_RIGHT +} SDL_ScreenOrientation; + +/* Private display data shared by gapi and windib*/ +struct SDL_PrivateVideoData { + int supportRotation; /* for Pocket PC devices */ + DWORD origRotation; /* for Pocket PC devices */ + + GapiInfo* gapiInfo; + DibInfo* dibInfo; +}; + +#endif diff --git a/3rdparty/SDL/src/video/windib/SDL_vkeys.h b/3rdparty/SDL/src/video/windib/SDL_vkeys.h new file mode 100644 index 0000000..53d9246 --- /dev/null +++ b/3rdparty/SDL/src/video/windib/SDL_vkeys.h @@ -0,0 +1,75 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ + +#ifndef VK_0 +#define VK_0 '0' +#define VK_1 '1' +#define VK_2 '2' +#define VK_3 '3' +#define VK_4 '4' +#define VK_5 '5' +#define VK_6 '6' +#define VK_7 '7' +#define VK_8 '8' +#define VK_9 '9' +#define VK_A 'A' +#define VK_B 'B' +#define VK_C 'C' +#define VK_D 'D' +#define VK_E 'E' +#define VK_F 'F' +#define VK_G 'G' +#define VK_H 'H' +#define VK_I 'I' +#define VK_J 'J' +#define VK_K 'K' +#define VK_L 'L' +#define VK_M 'M' +#define VK_N 'N' +#define VK_O 'O' +#define VK_P 'P' +#define VK_Q 'Q' +#define VK_R 'R' +#define VK_S 'S' +#define VK_T 'T' +#define VK_U 'U' +#define VK_V 'V' +#define VK_W 'W' +#define VK_X 'X' +#define VK_Y 'Y' +#define VK_Z 'Z' +#endif /* VK_0 */ + +/* These keys haven't been defined, but were experimentally determined */ +#define VK_SEMICOLON 0xBA +#define VK_EQUALS 0xBB +#define VK_COMMA 0xBC +#define VK_MINUS 0xBD +#define VK_PERIOD 0xBE +#define VK_SLASH 0xBF +#define VK_GRAVE 0xC0 +#define VK_LBRACKET 0xDB +#define VK_BACKSLASH 0xDC +#define VK_RBRACKET 0xDD +#define VK_APOSTROPHE 0xDE +#define VK_BACKTICK 0xDF +#define VK_OEM_102 0xE2 diff --git a/3rdparty/SDL/src/video/windx5/SDL_dx5events.c b/3rdparty/SDL/src/video/windx5/SDL_dx5events.c new file mode 100644 index 0000000..e12092f --- /dev/null +++ b/3rdparty/SDL/src/video/windx5/SDL_dx5events.c @@ -0,0 +1,1005 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* CAUTION!!!! If you modify this file, check ../windib/SDL_sysevents.c */ + +#include "directx.h" + +#include "SDL_main.h" +#include "SDL_events.h" +#include "SDL_video.h" +#include "SDL_syswm.h" +#include "../../events/SDL_sysevents.h" +#include "../../events/SDL_events_c.h" +#include "../wincommon/SDL_lowvideo.h" +#include "SDL_dx5video.h" + +#ifndef WM_APP +#define WM_APP 0x8000 +#endif + +#ifdef _WIN32_WCE +#define NO_GETKEYBOARDSTATE +#endif + +/* The keyboard and mouse device input */ +#define MAX_INPUTS 2 +#define INPUT_QSIZE 512 /* Buffer up to 512 input messages */ + +static LPDIRECTINPUT dinput = NULL; +static LPDIRECTINPUTDEVICE2 SDL_DIdev[MAX_INPUTS]; +static HANDLE SDL_DIevt[MAX_INPUTS]; +static void (*SDL_DIfun[MAX_INPUTS])(const int, DIDEVICEOBJECTDATA *); +static int SDL_DIndev = 0; +static int mouse_lost; +static int mouse_pressed; +static int mouse_buttons_swapped = 0; + +/* The translation table from a DirectInput scancode to an SDL keysym */ +static SDLKey DIK_keymap[256]; +static SDL_keysym *TranslateKey(UINT scancode, SDL_keysym *keysym, int pressed); + +/* DJM: If the user setup the window for us, we want to save his window proc, + and give him a chance to handle some messages. */ +#ifdef STRICT +#define WNDPROCTYPE WNDPROC +#else +#define WNDPROCTYPE FARPROC +#endif +static WNDPROCTYPE userWindowProc = NULL; + +static HWND GetTopLevelParent(HWND hWnd) +{ + HWND hParentWnd; + while (1) + { + hParentWnd = GetParent(hWnd); + if (hParentWnd == NULL) + break; + hWnd = hParentWnd; + } + return hWnd; +} + +/* Convert a DirectInput return code to a text message */ +static void SetDIerror(char *function, int code) +{ + static char *error; + static char errbuf[1024]; + + errbuf[0] = 0; + switch (code) { + case DIERR_GENERIC: + error = "Undefined error!"; + break; + case DIERR_OLDDIRECTINPUTVERSION: + error = "Your version of DirectInput needs upgrading"; + break; + case DIERR_INVALIDPARAM: + error = "Invalid parameters"; + break; + case DIERR_OUTOFMEMORY: + error = "Out of memory"; + break; + case DIERR_DEVICENOTREG: + error = "Device not registered"; + break; + case DIERR_NOINTERFACE: + error = "Interface not supported"; + break; + case DIERR_NOTINITIALIZED: + error = "Device not initialized"; + break; + default: + SDL_snprintf(errbuf, SDL_arraysize(errbuf), + "%s: Unknown DirectInput error: 0x%x", + function, code); + break; + } + if ( ! errbuf[0] ) { + SDL_snprintf(errbuf, SDL_arraysize(errbuf), "%s: %s", function, error); + } + SDL_SetError("%s", errbuf); + return; +} + +/* Initialize DirectInput + Note: If NONEXCLUSIVE access is requested for the devices, normal + windows input messages will continue to be generated for that + input device, in addition to DirectInput messages. + */ +static void handle_keyboard(const int numevents, DIDEVICEOBJECTDATA *events); +static void handle_mouse(const int numevents, DIDEVICEOBJECTDATA *events); +struct { + char *name; + REFGUID guid; + LPCDIDATAFORMAT format; + DWORD win_level; + DWORD raw_level; + void (*fun)(const int numevents, DIDEVICEOBJECTDATA *events); +} inputs[] = { + { "keyboard", + &GUID_SysKeyboard, &c_dfDIKeyboard, + (DISCL_FOREGROUND|DISCL_NONEXCLUSIVE), + (DISCL_FOREGROUND|DISCL_NONEXCLUSIVE), handle_keyboard }, + { "mouse", + &GUID_SysMouse, +#if DIRECTINPUT_VERSION >= 0x700 + &c_dfDIMouse2, +#else + &c_dfDIMouse, +#endif + (DISCL_BACKGROUND|DISCL_NONEXCLUSIVE), + (DISCL_BACKGROUND|DISCL_NONEXCLUSIVE), handle_mouse }, + { NULL, NULL, NULL, 0, 0, NULL } +}; + +static int DX5_DInputInit(_THIS) +{ + int i; + LPDIRECTINPUTDEVICE device; + HRESULT result; + DIPROPDWORD dipdw; + HWND topwnd; + + /* Create the DirectInput object */ + result = DInputCreate(SDL_Instance, DIRECTINPUT_VERSION, + &dinput, NULL); + if ( result != DI_OK ) { + SetDIerror("DirectInputCreate", result); + return(-1); + } + + /* Create all of our registered input devices */ + SDL_DIndev = 0; + for ( i=0; inputs[i].name; ++i ) { + /* Create the DirectInput device */ + result = IDirectInput_CreateDevice(dinput, inputs[i].guid, + &device, NULL); + if ( result != DI_OK ) { + SetDIerror("DirectInput::CreateDevice", result); + return(-1); + } + result = IDirectInputDevice_QueryInterface(device, + &IID_IDirectInputDevice2, (LPVOID *)&SDL_DIdev[i]); + IDirectInputDevice_Release(device); + if ( result != DI_OK ) { + SetDIerror("DirectInputDevice::QueryInterface", result); + return(-1); + } + topwnd = GetTopLevelParent(SDL_Window); + result = IDirectInputDevice2_SetCooperativeLevel(SDL_DIdev[i], + topwnd, inputs[i].win_level); + if ( result != DI_OK ) { + SetDIerror("DirectInputDevice::SetCooperativeLevel", + result); + return(-1); + } + result = IDirectInputDevice2_SetDataFormat(SDL_DIdev[i], + inputs[i].format); + if ( result != DI_OK ) { + SetDIerror("DirectInputDevice::SetDataFormat", result); + return(-1); + } + + /* Set buffered input -- we aren't polling */ + SDL_memset(&dipdw, 0, sizeof(dipdw)); + dipdw.diph.dwSize = sizeof(dipdw); + dipdw.diph.dwHeaderSize = sizeof(dipdw.diph); + dipdw.diph.dwObj = 0; + dipdw.diph.dwHow = DIPH_DEVICE; + dipdw.dwData = INPUT_QSIZE; + result = IDirectInputDevice2_SetProperty(SDL_DIdev[i], + DIPROP_BUFFERSIZE, &dipdw.diph); + if ( result != DI_OK ) { + SetDIerror("DirectInputDevice::SetProperty", result); + return(-1); + } + + /* Create an event to be signaled when input is ready */ + SDL_DIevt[i] = CreateEvent(NULL, FALSE, FALSE, NULL); + if ( SDL_DIevt[i] == NULL ) { + SDL_SetError("Couldn't create DirectInput event"); + return(-1); + } + result = IDirectInputDevice2_SetEventNotification(SDL_DIdev[i], + SDL_DIevt[i]); + if ( result != DI_OK ) { + SetDIerror("DirectInputDevice::SetEventNotification", + result); + return(-1); + } + SDL_DIfun[i] = inputs[i].fun; + + /* Acquire the device for input */ + IDirectInputDevice2_Acquire(SDL_DIdev[i]); + + /* Increment the number of devices we have */ + ++SDL_DIndev; + } + mouse_pressed = 0; + mouse_buttons_swapped = GetSystemMetrics(SM_SWAPBUTTON); + + /* DirectInput is ready! */ + return(0); +} + +/* Clean up DirectInput */ +static void DX5_DInputQuit(_THIS) +{ + int i; + + if ( dinput != NULL ) { + /* Close and release all DirectInput devices */ + for ( i=0; i<MAX_INPUTS; ++i ) { + if ( SDL_DIdev[i] != NULL ) { + IDirectInputDevice2_Unacquire(SDL_DIdev[i]); + IDirectInputDevice2_SetEventNotification( + SDL_DIdev[i], NULL); + if ( SDL_DIevt[i] != NULL ) { + CloseHandle(SDL_DIevt[i]); + SDL_DIevt[i] = NULL; + } + IDirectInputDevice2_Release(SDL_DIdev[i]); + SDL_DIdev[i] = NULL; + } + } + SDL_DIndev = 0; + + /* Release DirectInput */ + IDirectInput_Release(dinput); + dinput = NULL; + } +} + +/* Flag to tell SDL whether or not we queued an event */ +static int posted = 0; + +/* Input event handler functions */ +static void handle_keyboard(const int numevents, DIDEVICEOBJECTDATA *keybuf) +{ + int i; + SDL_keysym keysym; + + /* Translate keyboard messages */ + for ( i=0; i<numevents; ++i ) { + if ( keybuf[i].dwData & 0x80 ) { + posted = SDL_PrivateKeyboard(SDL_PRESSED, + TranslateKey(keybuf[i].dwOfs, &keysym, 1)); + } else { + posted = SDL_PrivateKeyboard(SDL_RELEASED, + TranslateKey(keybuf[i].dwOfs, &keysym, 0)); + } + } +} + +static void post_mouse_motion(int relative, Sint16 x, Sint16 y) +{ + extern int mouse_relative; + + if ( SDL_GetAppState() & SDL_APPMOUSEFOCUS ) { + posted = SDL_PrivateMouseMotion( + 0, relative, x, y); + + if ( !mouse_relative ) { + /* As DirectInput reads raw device coordinates, it has no notion of + * cursors or absolute position. We must assume responsibility for + * keeping track of this. */ + int current_x, current_y; + POINT cursor; + RECT trap; + RECT window; + int at_edge; + + /* Get the current cursor position */ + SDL_GetMouseState(¤t_x, ¤t_y); + cursor.x = current_x; + cursor.y = current_y; + ClientToScreen(SDL_Window, &cursor); + + /* Construct a 1 pixel square RECT that is used to confine the cursor + * pointer to a specific pixel using ClipCursor. This is used in + * preference to SetCursorPos as it avoids the cursor jumping around as + * both the OS and SDL attempt to move it simultaneously. */ + trap.left = cursor.x; + trap.top = cursor.y; + trap.right = cursor.x + 1; + trap.bottom = cursor.y + 1; + + GetClientRect(SDL_Window, &window); + window.right -= window.left; window.left = 0; + window.bottom -= window.top; window.top = 0; + + /* As we're assuming control over the cursor, we need to know when to + * relinquish control of it back to the operating system. This is when + * the cursor reaches the edge of the window. */ + at_edge = (current_x == window.left) || + (current_x == (window.right - 1)) || + (current_y == window.top) || + (current_y == (window.bottom - 1)); + + if ( at_edge ) { + ClipCursor(NULL); + } else { + ClipCursor(&trap); + } + } else { + /* When in relative mode, warp the OS's idea of where the cursor is to + * the center of the screen. This isn't really necessary as DirectInput + * reads from the hardware itself, but in case things go wrong, the + * cursor will be left in a sensible place. */ + POINT center; + center.x = (SDL_VideoSurface->w/2); + center.y = (SDL_VideoSurface->h/2); + ClientToScreen(SDL_Window, ¢er); + SetCursorPos(center.x, center.y); + } + } +} + +static void handle_mouse(const int numevents, DIDEVICEOBJECTDATA *ptrbuf) +{ + int i; + Sint16 xrel, yrel; + Uint8 state; + Uint8 button; + DWORD timestamp = 0; + + /* Sanity check. Mailing list reports this being NULL unexpectedly. */ + if (SDL_PublicSurface == NULL) { + return; + } + + /* If mouse focus has been lost, make sure we release the cursor. */ + if ( !(SDL_GetAppState() & SDL_APPMOUSEFOCUS) ) { + mouse_lost = 1; + ClipCursor(NULL); + } else { + /* If the mouse was lost, regain some sense of mouse state */ + if ( mouse_lost ) { + POINT mouse_pos; + Uint8 old_state; + Uint8 new_state; + + /* Set ourselves up with the current cursor position */ + GetCursorPos(&mouse_pos); + ScreenToClient(SDL_Window, &mouse_pos); + post_mouse_motion( 0, (Sint16)mouse_pos.x, (Sint16)mouse_pos.y); + + /* Check for mouse button changes */ + old_state = SDL_GetMouseState(NULL, NULL); + new_state = 0; + { /* Get the new DirectInput button state for the mouse */ + #if DIRECTINPUT_VERSION >= 0x700 + DIMOUSESTATE2 distate; + #else + DIMOUSESTATE distate; + #endif + HRESULT result; + + result=IDirectInputDevice2_GetDeviceState(SDL_DIdev[1], + sizeof(distate), &distate); + if ( result != DI_OK ) { + /* Try again next time */ + SetDIerror( + "IDirectInputDevice2::GetDeviceState", result); + return; + } + for ( i=3; i>=0; --i ) { + if ( (distate.rgbButtons[i]&0x80) == 0x80 ) { + new_state |= 0x01; + } + new_state <<= 1; + } + } + for ( i=0; i<8; ++i ) { + if ( (old_state&0x01) != (new_state&0x01) ) { + button = (Uint8)(i+1); + /* Map DI button numbers to SDL */ + switch ( button ) { + case 2: button = SDL_BUTTON_RIGHT; break; + case 3: button = SDL_BUTTON_MIDDLE; break; + case 4: button = SDL_BUTTON_X1; break; + case 5: button = SDL_BUTTON_X2; break; + default: break; + } + if ( new_state & 0x01 ) { + /* Grab mouse so we get mouse-up */ + if ( ++mouse_pressed > 0 ) { + SetCapture(SDL_Window); + } + state = SDL_PRESSED; + } else { + /* Release mouse after all mouse-ups */ + if ( --mouse_pressed <= 0 ) { + ReleaseCapture(); + mouse_pressed = 0; + } + state = SDL_RELEASED; + } + if ( mouse_buttons_swapped ) { + if ( button == 1 ) button = 3; + else + if ( button == 3 ) button = 1; + } + posted = SDL_PrivateMouseButton(state, button, + 0, 0); + } + old_state >>= 1; + new_state >>= 1; + } + mouse_lost = 0; + return; + } + + /* Translate mouse messages */ + xrel = 0; + yrel = 0; + for ( i=0; i<(int)numevents; ++i ) { + switch (ptrbuf[i].dwOfs) { + case DIMOFS_X: + if ( timestamp != ptrbuf[i].dwTimeStamp ) { + if ( xrel || yrel ) { + post_mouse_motion(1, xrel, yrel); + xrel = 0; + yrel = 0; + } + timestamp = ptrbuf[i].dwTimeStamp; + } + xrel += (Sint16)ptrbuf[i].dwData; + break; + case DIMOFS_Y: + if ( timestamp != ptrbuf[i].dwTimeStamp ) { + if ( xrel || yrel ) { + post_mouse_motion(1, xrel, yrel); + xrel = 0; + yrel = 0; + } + timestamp = ptrbuf[i].dwTimeStamp; + } + yrel += (Sint16)ptrbuf[i].dwData; + break; + case DIMOFS_Z: + if ( xrel || yrel ) { + post_mouse_motion(1, xrel, yrel); + xrel = 0; + yrel = 0; + } + timestamp = 0; + if((int)ptrbuf[i].dwData > 0) + button = SDL_BUTTON_WHEELUP; + else + button = SDL_BUTTON_WHEELDOWN; + posted = SDL_PrivateMouseButton( + SDL_PRESSED, button, 0, 0); + posted |= SDL_PrivateMouseButton( + SDL_RELEASED, button, 0, 0); + break; + case DIMOFS_BUTTON0: + case DIMOFS_BUTTON1: + case DIMOFS_BUTTON2: + case DIMOFS_BUTTON3: + #if DIRECTINPUT_VERSION >= 0x700 + case DIMOFS_BUTTON4: + case DIMOFS_BUTTON5: + case DIMOFS_BUTTON6: + case DIMOFS_BUTTON7: + #endif + if ( xrel || yrel ) { + post_mouse_motion(1, xrel, yrel); + xrel = 0; + yrel = 0; + } + timestamp = 0; + button = (Uint8)(ptrbuf[i].dwOfs-DIMOFS_BUTTON0)+1; + /* Map DI button numbers to SDL */ + switch ( button ) { + case 2: button = SDL_BUTTON_RIGHT; break; + case 3: button = SDL_BUTTON_MIDDLE; break; + case 4: button = SDL_BUTTON_X1; break; + case 5: button = SDL_BUTTON_X2; break; + default: break; + } + if ( ptrbuf[i].dwData & 0x80 ) { + /* Grab mouse so we get mouse-up */ + if ( ++mouse_pressed > 0 ) { + SetCapture(SDL_Window); + } + state = SDL_PRESSED; + } else { + /* Release mouse after all mouse-ups */ + if ( --mouse_pressed <= 0 ) { + ReleaseCapture(); + mouse_pressed = 0; + } + state = SDL_RELEASED; + } + if ( mouse_buttons_swapped ) { + if ( button == 1 ) button = 3; + else + if ( button == 3 ) button = 1; + } + posted = SDL_PrivateMouseButton(state, button, + 0, 0); + break; + } + } + if ( xrel || yrel ) { + post_mouse_motion(1, xrel, yrel); + } + } +} + +/* The main Win32 event handler */ +LRESULT DX5_HandleMessage(_THIS, HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) +{ + switch (msg) { +#ifdef WM_ACTIVATEAPP + case WM_ACTIVATEAPP: { + int i, active; + + active = (wParam && (GetForegroundWindow() == hwnd)); + if ( active ) { + for ( i=0; i<MAX_INPUTS; ++i ) { + if (SDL_DIdev[i] != NULL) + IDirectInputDevice2_Acquire( + SDL_DIdev[i]); + } + } else { + for ( i=0; i<MAX_INPUTS; ++i ) { + if (SDL_DIdev[i] != NULL) + IDirectInputDevice2_Unacquire( + SDL_DIdev[i]); + } + mouse_lost = 1; + } + } + break; +#endif /* WM_ACTIVATEAPP */ + +#ifdef WM_DISPLAYCHANGE + case WM_DISPLAYCHANGE: { + WPARAM BitsPerPixel; + WORD SizeX, SizeY; + + /* Ack! The display changed size and/or depth! */ + SizeX = LOWORD(lParam); + SizeY = HIWORD(lParam); + BitsPerPixel = wParam; + /* We cause this message when we go fullscreen */ + } + break; +#endif /* WM_DISPLAYCHANGE */ + + /* The keyboard is handled via DirectInput */ + case WM_SYSKEYUP: + case WM_SYSKEYDOWN: + case WM_KEYUP: + case WM_KEYDOWN: { + /* Ignore windows keyboard messages */; + } + return(0); + +#if defined(SC_SCREENSAVE) || defined(SC_MONITORPOWER) + /* Don't allow screen savers or monitor power downs. + This is because they quietly clear DirectX surfaces. + It would be better to allow the application to + decide whether or not to blow these off, but the + semantics of SDL_PrivateSysWMEvent() don't allow + the application that choice. + */ + case WM_SYSCOMMAND: { + if ((wParam&0xFFF0)==SC_SCREENSAVE || + (wParam&0xFFF0)==SC_MONITORPOWER) + return(0); + } + /* Fall through to default processing */ + +#endif /* SC_SCREENSAVE || SC_MONITORPOWER */ + + default: { + /* Only post the event if we're watching for it */ + if ( SDL_ProcessEvents[SDL_SYSWMEVENT] == SDL_ENABLE ) { + SDL_SysWMmsg wmmsg; + + SDL_VERSION(&wmmsg.version); + wmmsg.hwnd = hwnd; + wmmsg.msg = msg; + wmmsg.wParam = wParam; + wmmsg.lParam = lParam; + posted = SDL_PrivateSysWMEvent(&wmmsg); + + /* DJM: If the user isn't watching for private + messages in her SDL event loop, then pass it + along to any win32 specific window proc. + */ + } else if (userWindowProc) { + return CallWindowProc(userWindowProc, hwnd, msg, wParam, lParam); + } + } + break; + } + return(DefWindowProc(hwnd, msg, wParam, lParam)); +} + +/* This function checks the windows message queue and DirectInput and returns + 1 if there was input, 0 if there was no input, or -1 if the application has + posted a quit message. +*/ +static int DX5_CheckInput(_THIS, int timeout, BOOL processInput) +{ + MSG msg; + int i; + HRESULT result; + DWORD event; + + /* Check the normal windows queue (highest preference) */ + posted = 0; + while ( ! posted && + PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE) ) { + if ( GetMessage(&msg, NULL, 0, 0) > 0 ) { + DispatchMessage(&msg); + } else { + return(-1); + } + } + if ( posted ) { + return(1); + } + + /* Pump the DirectInput flow */ + if ( SDL_GetAppState() & SDL_APPMOUSEFOCUS ) { + for ( i=0; i<MAX_INPUTS; ++i ) { + if ( SDL_DIdev[i] != NULL ) { + result = IDirectInputDevice2_Poll(SDL_DIdev[i]); + if ( (result == DIERR_INPUTLOST) || + (result == DIERR_NOTACQUIRED) ) { + if ( SDL_strcmp(inputs[i].name, "mouse") == 0 ) { + mouse_lost = 1; + } + IDirectInputDevice2_Acquire(SDL_DIdev[i]); + IDirectInputDevice2_Poll(SDL_DIdev[i]); + } + } + } + } + + /* Wait for messages and input events */ + event = MsgWaitForMultipleObjects(SDL_DIndev, SDL_DIevt, FALSE, + timeout, QS_ALLEVENTS); + if ((event >= WAIT_OBJECT_0) && (event < (WAIT_OBJECT_0+SDL_DIndev))) { + DWORD numevents; + static DIDEVICEOBJECTDATA evtbuf[INPUT_QSIZE]; + + event -= WAIT_OBJECT_0; + numevents = INPUT_QSIZE; + result = IDirectInputDevice2_GetDeviceData( + SDL_DIdev[event], sizeof(DIDEVICEOBJECTDATA), + evtbuf, &numevents, 0); + if ( (result == DIERR_INPUTLOST) || + (result == DIERR_NOTACQUIRED) ) { + if ( SDL_strcmp(inputs[event].name, "mouse") == 0 ) { + mouse_lost = 1; + } + IDirectInputDevice2_Acquire(SDL_DIdev[event]); + result = IDirectInputDevice2_GetDeviceData( + SDL_DIdev[event], sizeof(DIDEVICEOBJECTDATA), + evtbuf, &numevents, 0); + } + /* Handle the events */ + if ( result == DI_OK && processInput ) { + /* Note: This can post multiple events to event queue + */ + (*SDL_DIfun[event])((int)numevents, evtbuf); + return(1); + } + } + if ( event != WAIT_TIMEOUT ) { + /* Maybe there was a windows message? */ + if ( PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE) ) { + if ( GetMessage(&msg, NULL, 0, 0) > 0 ) { + DispatchMessage(&msg); + } else { + return(-1); + } + return(1); + } + } + return(0); +} + +/* Change cooperative level based on whether or not we are fullscreen */ +void DX5_DInputReset(_THIS, int fullscreen) +{ + DWORD level; + int i; + HRESULT result; + HWND topwnd; + + for ( i=0; i<MAX_INPUTS; ++i ) { + if ( SDL_DIdev[i] != NULL ) { + if ( fullscreen ) { + level = inputs[i].raw_level; + } else { + level = inputs[i].win_level; + } + IDirectInputDevice2_Unacquire(SDL_DIdev[i]); + topwnd = GetTopLevelParent(SDL_Window); + result = IDirectInputDevice2_SetCooperativeLevel( + SDL_DIdev[i], topwnd, level); + IDirectInputDevice2_Acquire(SDL_DIdev[i]); + if ( result != DI_OK ) { + SetDIerror( + "DirectInputDevice::SetCooperativeLevel", result); + } + } + } + mouse_lost = 1; + + /* Flush pending input */ + DX5_CheckInput(this, 0, FALSE); +} + +void DX5_PumpEvents(_THIS) +{ + /* Wait for messages and DirectInput */ + while ( DX5_CheckInput(this, 0, TRUE) > 0 ) { + /* Loop and check again */; + } +} + +void DX5_InitOSKeymap(_THIS) +{ +#ifndef DIK_PAUSE +#define DIK_PAUSE 0xC5 +#endif +#ifndef DIK_OEM_102 +#define DIK_OEM_102 0x56 /* < > | on UK/Germany keyboards */ +#endif + int i; + + /* Map the DIK scancodes to SDL keysyms */ + for ( i=0; i<SDL_arraysize(DIK_keymap); ++i ) + DIK_keymap[i] = 0; + + /* Defined DIK_* constants */ + DIK_keymap[DIK_ESCAPE] = SDLK_ESCAPE; + DIK_keymap[DIK_1] = SDLK_1; + DIK_keymap[DIK_2] = SDLK_2; + DIK_keymap[DIK_3] = SDLK_3; + DIK_keymap[DIK_4] = SDLK_4; + DIK_keymap[DIK_5] = SDLK_5; + DIK_keymap[DIK_6] = SDLK_6; + DIK_keymap[DIK_7] = SDLK_7; + DIK_keymap[DIK_8] = SDLK_8; + DIK_keymap[DIK_9] = SDLK_9; + DIK_keymap[DIK_0] = SDLK_0; + DIK_keymap[DIK_MINUS] = SDLK_MINUS; + DIK_keymap[DIK_EQUALS] = SDLK_EQUALS; + DIK_keymap[DIK_BACK] = SDLK_BACKSPACE; + DIK_keymap[DIK_TAB] = SDLK_TAB; + DIK_keymap[DIK_Q] = SDLK_q; + DIK_keymap[DIK_W] = SDLK_w; + DIK_keymap[DIK_E] = SDLK_e; + DIK_keymap[DIK_R] = SDLK_r; + DIK_keymap[DIK_T] = SDLK_t; + DIK_keymap[DIK_Y] = SDLK_y; + DIK_keymap[DIK_U] = SDLK_u; + DIK_keymap[DIK_I] = SDLK_i; + DIK_keymap[DIK_O] = SDLK_o; + DIK_keymap[DIK_P] = SDLK_p; + DIK_keymap[DIK_LBRACKET] = SDLK_LEFTBRACKET; + DIK_keymap[DIK_RBRACKET] = SDLK_RIGHTBRACKET; + DIK_keymap[DIK_RETURN] = SDLK_RETURN; + DIK_keymap[DIK_LCONTROL] = SDLK_LCTRL; + DIK_keymap[DIK_A] = SDLK_a; + DIK_keymap[DIK_S] = SDLK_s; + DIK_keymap[DIK_D] = SDLK_d; + DIK_keymap[DIK_F] = SDLK_f; + DIK_keymap[DIK_G] = SDLK_g; + DIK_keymap[DIK_H] = SDLK_h; + DIK_keymap[DIK_J] = SDLK_j; + DIK_keymap[DIK_K] = SDLK_k; + DIK_keymap[DIK_L] = SDLK_l; + DIK_keymap[DIK_SEMICOLON] = SDLK_SEMICOLON; + DIK_keymap[DIK_APOSTROPHE] = SDLK_QUOTE; + DIK_keymap[DIK_GRAVE] = SDLK_BACKQUOTE; + DIK_keymap[DIK_LSHIFT] = SDLK_LSHIFT; + DIK_keymap[DIK_BACKSLASH] = SDLK_BACKSLASH; + DIK_keymap[DIK_OEM_102] = SDLK_LESS; + DIK_keymap[DIK_Z] = SDLK_z; + DIK_keymap[DIK_X] = SDLK_x; + DIK_keymap[DIK_C] = SDLK_c; + DIK_keymap[DIK_V] = SDLK_v; + DIK_keymap[DIK_B] = SDLK_b; + DIK_keymap[DIK_N] = SDLK_n; + DIK_keymap[DIK_M] = SDLK_m; + DIK_keymap[DIK_COMMA] = SDLK_COMMA; + DIK_keymap[DIK_PERIOD] = SDLK_PERIOD; + DIK_keymap[DIK_SLASH] = SDLK_SLASH; + DIK_keymap[DIK_RSHIFT] = SDLK_RSHIFT; + DIK_keymap[DIK_MULTIPLY] = SDLK_KP_MULTIPLY; + DIK_keymap[DIK_LMENU] = SDLK_LALT; + DIK_keymap[DIK_SPACE] = SDLK_SPACE; + DIK_keymap[DIK_CAPITAL] = SDLK_CAPSLOCK; + DIK_keymap[DIK_F1] = SDLK_F1; + DIK_keymap[DIK_F2] = SDLK_F2; + DIK_keymap[DIK_F3] = SDLK_F3; + DIK_keymap[DIK_F4] = SDLK_F4; + DIK_keymap[DIK_F5] = SDLK_F5; + DIK_keymap[DIK_F6] = SDLK_F6; + DIK_keymap[DIK_F7] = SDLK_F7; + DIK_keymap[DIK_F8] = SDLK_F8; + DIK_keymap[DIK_F9] = SDLK_F9; + DIK_keymap[DIK_F10] = SDLK_F10; + DIK_keymap[DIK_NUMLOCK] = SDLK_NUMLOCK; + DIK_keymap[DIK_SCROLL] = SDLK_SCROLLOCK; + DIK_keymap[DIK_NUMPAD7] = SDLK_KP7; + DIK_keymap[DIK_NUMPAD8] = SDLK_KP8; + DIK_keymap[DIK_NUMPAD9] = SDLK_KP9; + DIK_keymap[DIK_SUBTRACT] = SDLK_KP_MINUS; + DIK_keymap[DIK_NUMPAD4] = SDLK_KP4; + DIK_keymap[DIK_NUMPAD5] = SDLK_KP5; + DIK_keymap[DIK_NUMPAD6] = SDLK_KP6; + DIK_keymap[DIK_ADD] = SDLK_KP_PLUS; + DIK_keymap[DIK_NUMPAD1] = SDLK_KP1; + DIK_keymap[DIK_NUMPAD2] = SDLK_KP2; + DIK_keymap[DIK_NUMPAD3] = SDLK_KP3; + DIK_keymap[DIK_NUMPAD0] = SDLK_KP0; + DIK_keymap[DIK_DECIMAL] = SDLK_KP_PERIOD; + DIK_keymap[DIK_F11] = SDLK_F11; + DIK_keymap[DIK_F12] = SDLK_F12; + + DIK_keymap[DIK_F13] = SDLK_F13; + DIK_keymap[DIK_F14] = SDLK_F14; + DIK_keymap[DIK_F15] = SDLK_F15; + + DIK_keymap[DIK_NUMPADEQUALS] = SDLK_KP_EQUALS; + DIK_keymap[DIK_NUMPADENTER] = SDLK_KP_ENTER; + DIK_keymap[DIK_RCONTROL] = SDLK_RCTRL; + DIK_keymap[DIK_DIVIDE] = SDLK_KP_DIVIDE; + DIK_keymap[DIK_SYSRQ] = SDLK_PRINT; + DIK_keymap[DIK_RMENU] = SDLK_RALT; + DIK_keymap[DIK_PAUSE] = SDLK_PAUSE; + DIK_keymap[DIK_HOME] = SDLK_HOME; + DIK_keymap[DIK_UP] = SDLK_UP; + DIK_keymap[DIK_PRIOR] = SDLK_PAGEUP; + DIK_keymap[DIK_LEFT] = SDLK_LEFT; + DIK_keymap[DIK_RIGHT] = SDLK_RIGHT; + DIK_keymap[DIK_END] = SDLK_END; + DIK_keymap[DIK_DOWN] = SDLK_DOWN; + DIK_keymap[DIK_NEXT] = SDLK_PAGEDOWN; + DIK_keymap[DIK_INSERT] = SDLK_INSERT; + DIK_keymap[DIK_DELETE] = SDLK_DELETE; + DIK_keymap[DIK_LWIN] = SDLK_LMETA; + DIK_keymap[DIK_RWIN] = SDLK_RMETA; + DIK_keymap[DIK_APPS] = SDLK_MENU; +} + +static SDL_keysym *TranslateKey(UINT scancode, SDL_keysym *keysym, int pressed) +{ + /* Set the keysym information */ + keysym->scancode = (unsigned char)scancode; + keysym->sym = DIK_keymap[scancode]; + keysym->mod = KMOD_NONE; + keysym->unicode = 0; + if ( pressed && SDL_TranslateUNICODE ) { + UINT vkey; +#ifndef NO_GETKEYBOARDSTATE + BYTE keystate[256]; + Uint16 wchars[2]; +#endif + + vkey = MapVirtualKey(scancode, 1); +#ifdef NO_GETKEYBOARDSTATE + /* Uh oh, better hope the vkey is close enough.. */ + keysym->unicode = vkey; +#else + GetKeyboardState(keystate); + /* Numlock isn't taken into account in ToUnicode, + * so we handle it as a special case here */ + if ((keystate[VK_NUMLOCK] & 1) && vkey >= VK_NUMPAD0 && vkey <= VK_NUMPAD9) + { + keysym->unicode = vkey - VK_NUMPAD0 + '0'; + } + else if (SDL_ToUnicode(vkey, scancode, keystate, wchars, sizeof(wchars)/sizeof(wchars[0]), 0) > 0) + { + keysym->unicode = wchars[0]; + } +#endif /* NO_GETKEYBOARDSTATE */ + } + return(keysym); +} + +int DX5_CreateWindow(_THIS) +{ + char *windowid = SDL_getenv("SDL_WINDOWID"); + int i; + + /* Clear out DirectInput variables in case we fail */ + for ( i=0; i<MAX_INPUTS; ++i ) { + SDL_DIdev[i] = NULL; + SDL_DIevt[i] = NULL; + SDL_DIfun[i] = NULL; + } + + SDL_RegisterApp(NULL, 0, 0); + + SDL_windowid = (windowid != NULL); + if ( SDL_windowid ) { + SDL_Window = (HWND)((size_t)SDL_strtoull(windowid, NULL, 0)); + if ( SDL_Window == NULL ) { + SDL_SetError("Couldn't get user specified window"); + return(-1); + } + + /* DJM: we want all event's for the user specified + window to be handled by SDL. + */ + userWindowProc = (WNDPROCTYPE)GetWindowLongPtr(SDL_Window, GWLP_WNDPROC); + SetWindowLongPtr(SDL_Window, GWLP_WNDPROC, (LONG_PTR)WinMessage); + } else { + SDL_Window = CreateWindow(SDL_Appname, SDL_Appname, + (WS_OVERLAPPED|WS_CAPTION|WS_SYSMENU|WS_MINIMIZEBOX), + CW_USEDEFAULT, CW_USEDEFAULT, 0, 0, NULL, NULL, SDL_Instance, NULL); + if ( SDL_Window == NULL ) { + SDL_SetError("Couldn't create window"); + return(-1); + } + ShowWindow(SDL_Window, SW_HIDE); + } + + /* Initialize DirectInput */ + if ( DX5_DInputInit(this) < 0 ) { + return(-1); + } + + /* JC 14 Mar 2006 + Flush the message loop or this can cause big problems later + Especially if the user decides to use dialog boxes or assert()! + */ + WIN_FlushMessageQueue(); + + /* Ready to roll */ + return(0); +} + +void DX5_DestroyWindow(_THIS) +{ + /* Close down DirectInput */ + DX5_DInputQuit(this); + + /* Destroy our window */ + if ( SDL_windowid ) { + SetWindowLongPtr(SDL_Window, GWLP_WNDPROC, (LONG_PTR)userWindowProc); + } else { + DestroyWindow(SDL_Window); + } + SDL_UnregisterApp(); + + /* JC 14 Mar 2006 + Flush the message loop or this can cause big problems later + Especially if the user decides to use dialog boxes or assert()! + */ + WIN_FlushMessageQueue(); +} diff --git a/3rdparty/SDL/src/video/windx5/SDL_dx5events_c.h b/3rdparty/SDL/src/video/windx5/SDL_dx5events_c.h new file mode 100644 index 0000000..28e1b6c --- /dev/null +++ b/3rdparty/SDL/src/video/windx5/SDL_dx5events_c.h @@ -0,0 +1,37 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#include "../wincommon/SDL_lowvideo.h" + +/* Variables and functions exported by SDL_dx5events.c to other parts + of the native video subsystem (SDL_dx5video.c) +*/ +extern LONG + DX5_HandleMessage(_THIS, HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam); +extern int DX5_CreateWindow(_THIS); +extern void DX5_DestroyWindow(_THIS); + +extern void DX5_PumpEvents(_THIS); +extern void DX5_InitOSKeymap(_THIS); +extern void DX5_DInputReset(_THIS, int fullscreen); + diff --git a/3rdparty/SDL/src/video/windx5/SDL_dx5video.c b/3rdparty/SDL/src/video/windx5/SDL_dx5video.c new file mode 100644 index 0000000..f80ca97 --- /dev/null +++ b/3rdparty/SDL/src/video/windx5/SDL_dx5video.c @@ -0,0 +1,2537 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#include "directx.h" + +/* Not yet in the mingw32 cross-compile headers */ +#ifndef CDS_FULLSCREEN +#define CDS_FULLSCREEN 4 +#endif + +#include "SDL_timer.h" +#include "SDL_events.h" +#include "SDL_syswm.h" +#include "../SDL_sysvideo.h" +#include "../SDL_blit.h" +#include "../SDL_pixels_c.h" +#include "SDL_dx5video.h" +#include "../wincommon/SDL_syswm_c.h" +#include "../wincommon/SDL_sysmouse_c.h" +#include "SDL_dx5events_c.h" +#include "SDL_dx5yuv_c.h" +#include "../wincommon/SDL_wingl_c.h" + +#ifdef _WIN32_WCE +#define NO_CHANGEDISPLAYSETTINGS +#endif +#ifndef WS_MAXIMIZE +#define WS_MAXIMIZE 0 +#endif +#ifndef SWP_NOCOPYBITS +#define SWP_NOCOPYBITS 0 +#endif +#ifndef PC_NOCOLLAPSE +#define PC_NOCOLLAPSE 0 +#endif + + +/* DirectX function pointers for video and events */ +HRESULT (WINAPI *DDrawCreate)( GUID FAR *lpGUID, LPDIRECTDRAW FAR *lplpDD, IUnknown FAR *pUnkOuter ); +HRESULT (WINAPI *DInputCreate)(HINSTANCE hinst, DWORD dwVersion, LPDIRECTINPUT *ppDI, LPUNKNOWN punkOuter); + +/* This is the rect EnumModes2 uses */ +struct DX5EnumRect { + SDL_Rect r; + int refreshRate; + struct DX5EnumRect* next; +}; +static struct DX5EnumRect *enumlists[NUM_MODELISTS]; + +/* + * Experimentally determined values for c_cfDI* constants used in DirectX 5.0 + */ + +/* Keyboard */ + +static DIOBJECTDATAFORMAT KBD_fmt[] = { + { &GUID_Key, 0, 0x8000000C, 0x00000000 }, + { &GUID_Key, 1, 0x8000010C, 0x00000000 }, + { &GUID_Key, 2, 0x8000020C, 0x00000000 }, + { &GUID_Key, 3, 0x8000030C, 0x00000000 }, + { &GUID_Key, 4, 0x8000040C, 0x00000000 }, + { &GUID_Key, 5, 0x8000050C, 0x00000000 }, + { &GUID_Key, 6, 0x8000060C, 0x00000000 }, + { &GUID_Key, 7, 0x8000070C, 0x00000000 }, + { &GUID_Key, 8, 0x8000080C, 0x00000000 }, + { &GUID_Key, 9, 0x8000090C, 0x00000000 }, + { &GUID_Key, 10, 0x80000A0C, 0x00000000 }, + { &GUID_Key, 11, 0x80000B0C, 0x00000000 }, + { &GUID_Key, 12, 0x80000C0C, 0x00000000 }, + { &GUID_Key, 13, 0x80000D0C, 0x00000000 }, + { &GUID_Key, 14, 0x80000E0C, 0x00000000 }, + { &GUID_Key, 15, 0x80000F0C, 0x00000000 }, + { &GUID_Key, 16, 0x8000100C, 0x00000000 }, + { &GUID_Key, 17, 0x8000110C, 0x00000000 }, + { &GUID_Key, 18, 0x8000120C, 0x00000000 }, + { &GUID_Key, 19, 0x8000130C, 0x00000000 }, + { &GUID_Key, 20, 0x8000140C, 0x00000000 }, + { &GUID_Key, 21, 0x8000150C, 0x00000000 }, + { &GUID_Key, 22, 0x8000160C, 0x00000000 }, + { &GUID_Key, 23, 0x8000170C, 0x00000000 }, + { &GUID_Key, 24, 0x8000180C, 0x00000000 }, + { &GUID_Key, 25, 0x8000190C, 0x00000000 }, + { &GUID_Key, 26, 0x80001A0C, 0x00000000 }, + { &GUID_Key, 27, 0x80001B0C, 0x00000000 }, + { &GUID_Key, 28, 0x80001C0C, 0x00000000 }, + { &GUID_Key, 29, 0x80001D0C, 0x00000000 }, + { &GUID_Key, 30, 0x80001E0C, 0x00000000 }, + { &GUID_Key, 31, 0x80001F0C, 0x00000000 }, + { &GUID_Key, 32, 0x8000200C, 0x00000000 }, + { &GUID_Key, 33, 0x8000210C, 0x00000000 }, + { &GUID_Key, 34, 0x8000220C, 0x00000000 }, + { &GUID_Key, 35, 0x8000230C, 0x00000000 }, + { &GUID_Key, 36, 0x8000240C, 0x00000000 }, + { &GUID_Key, 37, 0x8000250C, 0x00000000 }, + { &GUID_Key, 38, 0x8000260C, 0x00000000 }, + { &GUID_Key, 39, 0x8000270C, 0x00000000 }, + { &GUID_Key, 40, 0x8000280C, 0x00000000 }, + { &GUID_Key, 41, 0x8000290C, 0x00000000 }, + { &GUID_Key, 42, 0x80002A0C, 0x00000000 }, + { &GUID_Key, 43, 0x80002B0C, 0x00000000 }, + { &GUID_Key, 44, 0x80002C0C, 0x00000000 }, + { &GUID_Key, 45, 0x80002D0C, 0x00000000 }, + { &GUID_Key, 46, 0x80002E0C, 0x00000000 }, + { &GUID_Key, 47, 0x80002F0C, 0x00000000 }, + { &GUID_Key, 48, 0x8000300C, 0x00000000 }, + { &GUID_Key, 49, 0x8000310C, 0x00000000 }, + { &GUID_Key, 50, 0x8000320C, 0x00000000 }, + { &GUID_Key, 51, 0x8000330C, 0x00000000 }, + { &GUID_Key, 52, 0x8000340C, 0x00000000 }, + { &GUID_Key, 53, 0x8000350C, 0x00000000 }, + { &GUID_Key, 54, 0x8000360C, 0x00000000 }, + { &GUID_Key, 55, 0x8000370C, 0x00000000 }, + { &GUID_Key, 56, 0x8000380C, 0x00000000 }, + { &GUID_Key, 57, 0x8000390C, 0x00000000 }, + { &GUID_Key, 58, 0x80003A0C, 0x00000000 }, + { &GUID_Key, 59, 0x80003B0C, 0x00000000 }, + { &GUID_Key, 60, 0x80003C0C, 0x00000000 }, + { &GUID_Key, 61, 0x80003D0C, 0x00000000 }, + { &GUID_Key, 62, 0x80003E0C, 0x00000000 }, + { &GUID_Key, 63, 0x80003F0C, 0x00000000 }, + { &GUID_Key, 64, 0x8000400C, 0x00000000 }, + { &GUID_Key, 65, 0x8000410C, 0x00000000 }, + { &GUID_Key, 66, 0x8000420C, 0x00000000 }, + { &GUID_Key, 67, 0x8000430C, 0x00000000 }, + { &GUID_Key, 68, 0x8000440C, 0x00000000 }, + { &GUID_Key, 69, 0x8000450C, 0x00000000 }, + { &GUID_Key, 70, 0x8000460C, 0x00000000 }, + { &GUID_Key, 71, 0x8000470C, 0x00000000 }, + { &GUID_Key, 72, 0x8000480C, 0x00000000 }, + { &GUID_Key, 73, 0x8000490C, 0x00000000 }, + { &GUID_Key, 74, 0x80004A0C, 0x00000000 }, + { &GUID_Key, 75, 0x80004B0C, 0x00000000 }, + { &GUID_Key, 76, 0x80004C0C, 0x00000000 }, + { &GUID_Key, 77, 0x80004D0C, 0x00000000 }, + { &GUID_Key, 78, 0x80004E0C, 0x00000000 }, + { &GUID_Key, 79, 0x80004F0C, 0x00000000 }, + { &GUID_Key, 80, 0x8000500C, 0x00000000 }, + { &GUID_Key, 81, 0x8000510C, 0x00000000 }, + { &GUID_Key, 82, 0x8000520C, 0x00000000 }, + { &GUID_Key, 83, 0x8000530C, 0x00000000 }, + { &GUID_Key, 84, 0x8000540C, 0x00000000 }, + { &GUID_Key, 85, 0x8000550C, 0x00000000 }, + { &GUID_Key, 86, 0x8000560C, 0x00000000 }, + { &GUID_Key, 87, 0x8000570C, 0x00000000 }, + { &GUID_Key, 88, 0x8000580C, 0x00000000 }, + { &GUID_Key, 89, 0x8000590C, 0x00000000 }, + { &GUID_Key, 90, 0x80005A0C, 0x00000000 }, + { &GUID_Key, 91, 0x80005B0C, 0x00000000 }, + { &GUID_Key, 92, 0x80005C0C, 0x00000000 }, + { &GUID_Key, 93, 0x80005D0C, 0x00000000 }, + { &GUID_Key, 94, 0x80005E0C, 0x00000000 }, + { &GUID_Key, 95, 0x80005F0C, 0x00000000 }, + { &GUID_Key, 96, 0x8000600C, 0x00000000 }, + { &GUID_Key, 97, 0x8000610C, 0x00000000 }, + { &GUID_Key, 98, 0x8000620C, 0x00000000 }, + { &GUID_Key, 99, 0x8000630C, 0x00000000 }, + { &GUID_Key, 100, 0x8000640C, 0x00000000 }, + { &GUID_Key, 101, 0x8000650C, 0x00000000 }, + { &GUID_Key, 102, 0x8000660C, 0x00000000 }, + { &GUID_Key, 103, 0x8000670C, 0x00000000 }, + { &GUID_Key, 104, 0x8000680C, 0x00000000 }, + { &GUID_Key, 105, 0x8000690C, 0x00000000 }, + { &GUID_Key, 106, 0x80006A0C, 0x00000000 }, + { &GUID_Key, 107, 0x80006B0C, 0x00000000 }, + { &GUID_Key, 108, 0x80006C0C, 0x00000000 }, + { &GUID_Key, 109, 0x80006D0C, 0x00000000 }, + { &GUID_Key, 110, 0x80006E0C, 0x00000000 }, + { &GUID_Key, 111, 0x80006F0C, 0x00000000 }, + { &GUID_Key, 112, 0x8000700C, 0x00000000 }, + { &GUID_Key, 113, 0x8000710C, 0x00000000 }, + { &GUID_Key, 114, 0x8000720C, 0x00000000 }, + { &GUID_Key, 115, 0x8000730C, 0x00000000 }, + { &GUID_Key, 116, 0x8000740C, 0x00000000 }, + { &GUID_Key, 117, 0x8000750C, 0x00000000 }, + { &GUID_Key, 118, 0x8000760C, 0x00000000 }, + { &GUID_Key, 119, 0x8000770C, 0x00000000 }, + { &GUID_Key, 120, 0x8000780C, 0x00000000 }, + { &GUID_Key, 121, 0x8000790C, 0x00000000 }, + { &GUID_Key, 122, 0x80007A0C, 0x00000000 }, + { &GUID_Key, 123, 0x80007B0C, 0x00000000 }, + { &GUID_Key, 124, 0x80007C0C, 0x00000000 }, + { &GUID_Key, 125, 0x80007D0C, 0x00000000 }, + { &GUID_Key, 126, 0x80007E0C, 0x00000000 }, + { &GUID_Key, 127, 0x80007F0C, 0x00000000 }, + { &GUID_Key, 128, 0x8000800C, 0x00000000 }, + { &GUID_Key, 129, 0x8000810C, 0x00000000 }, + { &GUID_Key, 130, 0x8000820C, 0x00000000 }, + { &GUID_Key, 131, 0x8000830C, 0x00000000 }, + { &GUID_Key, 132, 0x8000840C, 0x00000000 }, + { &GUID_Key, 133, 0x8000850C, 0x00000000 }, + { &GUID_Key, 134, 0x8000860C, 0x00000000 }, + { &GUID_Key, 135, 0x8000870C, 0x00000000 }, + { &GUID_Key, 136, 0x8000880C, 0x00000000 }, + { &GUID_Key, 137, 0x8000890C, 0x00000000 }, + { &GUID_Key, 138, 0x80008A0C, 0x00000000 }, + { &GUID_Key, 139, 0x80008B0C, 0x00000000 }, + { &GUID_Key, 140, 0x80008C0C, 0x00000000 }, + { &GUID_Key, 141, 0x80008D0C, 0x00000000 }, + { &GUID_Key, 142, 0x80008E0C, 0x00000000 }, + { &GUID_Key, 143, 0x80008F0C, 0x00000000 }, + { &GUID_Key, 144, 0x8000900C, 0x00000000 }, + { &GUID_Key, 145, 0x8000910C, 0x00000000 }, + { &GUID_Key, 146, 0x8000920C, 0x00000000 }, + { &GUID_Key, 147, 0x8000930C, 0x00000000 }, + { &GUID_Key, 148, 0x8000940C, 0x00000000 }, + { &GUID_Key, 149, 0x8000950C, 0x00000000 }, + { &GUID_Key, 150, 0x8000960C, 0x00000000 }, + { &GUID_Key, 151, 0x8000970C, 0x00000000 }, + { &GUID_Key, 152, 0x8000980C, 0x00000000 }, + { &GUID_Key, 153, 0x8000990C, 0x00000000 }, + { &GUID_Key, 154, 0x80009A0C, 0x00000000 }, + { &GUID_Key, 155, 0x80009B0C, 0x00000000 }, + { &GUID_Key, 156, 0x80009C0C, 0x00000000 }, + { &GUID_Key, 157, 0x80009D0C, 0x00000000 }, + { &GUID_Key, 158, 0x80009E0C, 0x00000000 }, + { &GUID_Key, 159, 0x80009F0C, 0x00000000 }, + { &GUID_Key, 160, 0x8000A00C, 0x00000000 }, + { &GUID_Key, 161, 0x8000A10C, 0x00000000 }, + { &GUID_Key, 162, 0x8000A20C, 0x00000000 }, + { &GUID_Key, 163, 0x8000A30C, 0x00000000 }, + { &GUID_Key, 164, 0x8000A40C, 0x00000000 }, + { &GUID_Key, 165, 0x8000A50C, 0x00000000 }, + { &GUID_Key, 166, 0x8000A60C, 0x00000000 }, + { &GUID_Key, 167, 0x8000A70C, 0x00000000 }, + { &GUID_Key, 168, 0x8000A80C, 0x00000000 }, + { &GUID_Key, 169, 0x8000A90C, 0x00000000 }, + { &GUID_Key, 170, 0x8000AA0C, 0x00000000 }, + { &GUID_Key, 171, 0x8000AB0C, 0x00000000 }, + { &GUID_Key, 172, 0x8000AC0C, 0x00000000 }, + { &GUID_Key, 173, 0x8000AD0C, 0x00000000 }, + { &GUID_Key, 174, 0x8000AE0C, 0x00000000 }, + { &GUID_Key, 175, 0x8000AF0C, 0x00000000 }, + { &GUID_Key, 176, 0x8000B00C, 0x00000000 }, + { &GUID_Key, 177, 0x8000B10C, 0x00000000 }, + { &GUID_Key, 178, 0x8000B20C, 0x00000000 }, + { &GUID_Key, 179, 0x8000B30C, 0x00000000 }, + { &GUID_Key, 180, 0x8000B40C, 0x00000000 }, + { &GUID_Key, 181, 0x8000B50C, 0x00000000 }, + { &GUID_Key, 182, 0x8000B60C, 0x00000000 }, + { &GUID_Key, 183, 0x8000B70C, 0x00000000 }, + { &GUID_Key, 184, 0x8000B80C, 0x00000000 }, + { &GUID_Key, 185, 0x8000B90C, 0x00000000 }, + { &GUID_Key, 186, 0x8000BA0C, 0x00000000 }, + { &GUID_Key, 187, 0x8000BB0C, 0x00000000 }, + { &GUID_Key, 188, 0x8000BC0C, 0x00000000 }, + { &GUID_Key, 189, 0x8000BD0C, 0x00000000 }, + { &GUID_Key, 190, 0x8000BE0C, 0x00000000 }, + { &GUID_Key, 191, 0x8000BF0C, 0x00000000 }, + { &GUID_Key, 192, 0x8000C00C, 0x00000000 }, + { &GUID_Key, 193, 0x8000C10C, 0x00000000 }, + { &GUID_Key, 194, 0x8000C20C, 0x00000000 }, + { &GUID_Key, 195, 0x8000C30C, 0x00000000 }, + { &GUID_Key, 196, 0x8000C40C, 0x00000000 }, + { &GUID_Key, 197, 0x8000C50C, 0x00000000 }, + { &GUID_Key, 198, 0x8000C60C, 0x00000000 }, + { &GUID_Key, 199, 0x8000C70C, 0x00000000 }, + { &GUID_Key, 200, 0x8000C80C, 0x00000000 }, + { &GUID_Key, 201, 0x8000C90C, 0x00000000 }, + { &GUID_Key, 202, 0x8000CA0C, 0x00000000 }, + { &GUID_Key, 203, 0x8000CB0C, 0x00000000 }, + { &GUID_Key, 204, 0x8000CC0C, 0x00000000 }, + { &GUID_Key, 205, 0x8000CD0C, 0x00000000 }, + { &GUID_Key, 206, 0x8000CE0C, 0x00000000 }, + { &GUID_Key, 207, 0x8000CF0C, 0x00000000 }, + { &GUID_Key, 208, 0x8000D00C, 0x00000000 }, + { &GUID_Key, 209, 0x8000D10C, 0x00000000 }, + { &GUID_Key, 210, 0x8000D20C, 0x00000000 }, + { &GUID_Key, 211, 0x8000D30C, 0x00000000 }, + { &GUID_Key, 212, 0x8000D40C, 0x00000000 }, + { &GUID_Key, 213, 0x8000D50C, 0x00000000 }, + { &GUID_Key, 214, 0x8000D60C, 0x00000000 }, + { &GUID_Key, 215, 0x8000D70C, 0x00000000 }, + { &GUID_Key, 216, 0x8000D80C, 0x00000000 }, + { &GUID_Key, 217, 0x8000D90C, 0x00000000 }, + { &GUID_Key, 218, 0x8000DA0C, 0x00000000 }, + { &GUID_Key, 219, 0x8000DB0C, 0x00000000 }, + { &GUID_Key, 220, 0x8000DC0C, 0x00000000 }, + { &GUID_Key, 221, 0x8000DD0C, 0x00000000 }, + { &GUID_Key, 222, 0x8000DE0C, 0x00000000 }, + { &GUID_Key, 223, 0x8000DF0C, 0x00000000 }, + { &GUID_Key, 224, 0x8000E00C, 0x00000000 }, + { &GUID_Key, 225, 0x8000E10C, 0x00000000 }, + { &GUID_Key, 226, 0x8000E20C, 0x00000000 }, + { &GUID_Key, 227, 0x8000E30C, 0x00000000 }, + { &GUID_Key, 228, 0x8000E40C, 0x00000000 }, + { &GUID_Key, 229, 0x8000E50C, 0x00000000 }, + { &GUID_Key, 230, 0x8000E60C, 0x00000000 }, + { &GUID_Key, 231, 0x8000E70C, 0x00000000 }, + { &GUID_Key, 232, 0x8000E80C, 0x00000000 }, + { &GUID_Key, 233, 0x8000E90C, 0x00000000 }, + { &GUID_Key, 234, 0x8000EA0C, 0x00000000 }, + { &GUID_Key, 235, 0x8000EB0C, 0x00000000 }, + { &GUID_Key, 236, 0x8000EC0C, 0x00000000 }, + { &GUID_Key, 237, 0x8000ED0C, 0x00000000 }, + { &GUID_Key, 238, 0x8000EE0C, 0x00000000 }, + { &GUID_Key, 239, 0x8000EF0C, 0x00000000 }, + { &GUID_Key, 240, 0x8000F00C, 0x00000000 }, + { &GUID_Key, 241, 0x8000F10C, 0x00000000 }, + { &GUID_Key, 242, 0x8000F20C, 0x00000000 }, + { &GUID_Key, 243, 0x8000F30C, 0x00000000 }, + { &GUID_Key, 244, 0x8000F40C, 0x00000000 }, + { &GUID_Key, 245, 0x8000F50C, 0x00000000 }, + { &GUID_Key, 246, 0x8000F60C, 0x00000000 }, + { &GUID_Key, 247, 0x8000F70C, 0x00000000 }, + { &GUID_Key, 248, 0x8000F80C, 0x00000000 }, + { &GUID_Key, 249, 0x8000F90C, 0x00000000 }, + { &GUID_Key, 250, 0x8000FA0C, 0x00000000 }, + { &GUID_Key, 251, 0x8000FB0C, 0x00000000 }, + { &GUID_Key, 252, 0x8000FC0C, 0x00000000 }, + { &GUID_Key, 253, 0x8000FD0C, 0x00000000 }, + { &GUID_Key, 254, 0x8000FE0C, 0x00000000 }, + { &GUID_Key, 255, 0x8000FF0C, 0x00000000 }, +}; + +const DIDATAFORMAT c_dfDIKeyboard = { sizeof(DIDATAFORMAT), sizeof(DIOBJECTDATAFORMAT), 0x00000002, 256, 256, KBD_fmt }; + + +/* Mouse */ + +static DIOBJECTDATAFORMAT PTR_fmt[] = { + { &GUID_XAxis, 0, 0x00FFFF03, 0x00000000 }, + { &GUID_YAxis, 4, 0x00FFFF03, 0x00000000 }, + { &GUID_ZAxis, 8, 0x80FFFF03, 0x00000000 }, + { NULL, 12, 0x00FFFF0C, 0x00000000 }, + { NULL, 13, 0x00FFFF0C, 0x00000000 }, + { NULL, 14, 0x80FFFF0C, 0x00000000 }, + { NULL, 15, 0x80FFFF0C, 0x00000000 }, +}; + +const DIDATAFORMAT c_dfDIMouse = { sizeof(DIDATAFORMAT), sizeof(DIOBJECTDATAFORMAT), 0x00000002, 16, 7, PTR_fmt }; + +static DIOBJECTDATAFORMAT PTR2_fmt[] = { + { &GUID_XAxis, 0, 0x00FFFF03, 0x00000000 }, + { &GUID_YAxis, 4, 0x00FFFF03, 0x00000000 }, + { &GUID_ZAxis, 8, 0x80FFFF03, 0x00000000 }, + { NULL, 12, 0x00FFFF0C, 0x00000000 }, + { NULL, 13, 0x00FFFF0C, 0x00000000 }, + { NULL, 14, 0x80FFFF0C, 0x00000000 }, + { NULL, 15, 0x80FFFF0C, 0x00000000 }, + { NULL, 16, 0x80FFFF0C, 0x00000000 }, + { NULL, 17, 0x80FFFF0C, 0x00000000 }, + { NULL, 18, 0x80FFFF0C, 0x00000000 }, + { NULL, 19, 0x80FFFF0C, 0x00000000 } +}; + +const DIDATAFORMAT c_dfDIMouse2 = { sizeof(DIDATAFORMAT), sizeof(DIOBJECTDATAFORMAT), 0x00000002, 20, 11, PTR2_fmt }; + + +/* Joystick */ + +static DIOBJECTDATAFORMAT JOY_fmt[] = { + { &GUID_XAxis, 0, 0x80FFFF03, 0x00000100 }, + { &GUID_YAxis, 4, 0x80FFFF03, 0x00000100 }, + { &GUID_ZAxis, 8, 0x80FFFF03, 0x00000100 }, + { &GUID_RxAxis, 12, 0x80FFFF03, 0x00000100 }, + { &GUID_RyAxis, 16, 0x80FFFF03, 0x00000100 }, + { &GUID_RzAxis, 20, 0x80FFFF03, 0x00000100 }, + { &GUID_Slider, 24, 0x80FFFF03, 0x00000100 }, + { &GUID_Slider, 28, 0x80FFFF03, 0x00000100 }, + { &GUID_POV, 32, 0x80FFFF10, 0x00000000 }, + { &GUID_POV, 36, 0x80FFFF10, 0x00000000 }, + { &GUID_POV, 40, 0x80FFFF10, 0x00000000 }, + { &GUID_POV, 44, 0x80FFFF10, 0x00000000 }, + { NULL, 48, 0x80FFFF0C, 0x00000000 }, + { NULL, 49, 0x80FFFF0C, 0x00000000 }, + { NULL, 50, 0x80FFFF0C, 0x00000000 }, + { NULL, 51, 0x80FFFF0C, 0x00000000 }, + { NULL, 52, 0x80FFFF0C, 0x00000000 }, + { NULL, 53, 0x80FFFF0C, 0x00000000 }, + { NULL, 54, 0x80FFFF0C, 0x00000000 }, + { NULL, 55, 0x80FFFF0C, 0x00000000 }, + { NULL, 56, 0x80FFFF0C, 0x00000000 }, + { NULL, 57, 0x80FFFF0C, 0x00000000 }, + { NULL, 58, 0x80FFFF0C, 0x00000000 }, + { NULL, 59, 0x80FFFF0C, 0x00000000 }, + { NULL, 60, 0x80FFFF0C, 0x00000000 }, + { NULL, 61, 0x80FFFF0C, 0x00000000 }, + { NULL, 62, 0x80FFFF0C, 0x00000000 }, + { NULL, 63, 0x80FFFF0C, 0x00000000 }, + { NULL, 64, 0x80FFFF0C, 0x00000000 }, + { NULL, 65, 0x80FFFF0C, 0x00000000 }, + { NULL, 66, 0x80FFFF0C, 0x00000000 }, + { NULL, 67, 0x80FFFF0C, 0x00000000 }, + { NULL, 68, 0x80FFFF0C, 0x00000000 }, + { NULL, 69, 0x80FFFF0C, 0x00000000 }, + { NULL, 70, 0x80FFFF0C, 0x00000000 }, + { NULL, 71, 0x80FFFF0C, 0x00000000 }, + { NULL, 72, 0x80FFFF0C, 0x00000000 }, + { NULL, 73, 0x80FFFF0C, 0x00000000 }, + { NULL, 74, 0x80FFFF0C, 0x00000000 }, + { NULL, 75, 0x80FFFF0C, 0x00000000 }, + { NULL, 76, 0x80FFFF0C, 0x00000000 }, + { NULL, 77, 0x80FFFF0C, 0x00000000 }, + { NULL, 78, 0x80FFFF0C, 0x00000000 }, + { NULL, 79, 0x80FFFF0C, 0x00000000 }, +}; + +const DIDATAFORMAT c_dfDIJoystick = { sizeof(DIDATAFORMAT), sizeof(DIOBJECTDATAFORMAT), 0x00000001, 80, 44, JOY_fmt }; + + +/* Initialization/Query functions */ +static int DX5_VideoInit(_THIS, SDL_PixelFormat *vformat); +static SDL_Rect **DX5_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags); +static SDL_Surface *DX5_SetVideoMode(_THIS, SDL_Surface *current, int width, int height, int bpp, Uint32 flags); +static int DX5_SetColors(_THIS, int firstcolor, int ncolors, + SDL_Color *colors); +static int DX5_SetGammaRamp(_THIS, Uint16 *ramp); +static int DX5_GetGammaRamp(_THIS, Uint16 *ramp); +static void DX5_VideoQuit(_THIS); + +/* Hardware surface functions */ +static int DX5_AllocHWSurface(_THIS, SDL_Surface *surface); +static int DX5_CheckHWBlit(_THIS, SDL_Surface *src, SDL_Surface *dst); +static int DX5_FillHWRect(_THIS, SDL_Surface *dst, SDL_Rect *dstrect, Uint32 color); +static int DX5_SetHWColorKey(_THIS, SDL_Surface *surface, Uint32 key); +static int DX5_SetHWAlpha(_THIS, SDL_Surface *surface, Uint8 alpha); +static int DX5_LockHWSurface(_THIS, SDL_Surface *surface); +static void DX5_UnlockHWSurface(_THIS, SDL_Surface *surface); +static int DX5_FlipHWSurface(_THIS, SDL_Surface *surface); +static void DX5_FreeHWSurface(_THIS, SDL_Surface *surface); + +static int DX5_AllocDDSurface(_THIS, SDL_Surface *surface, + LPDIRECTDRAWSURFACE3 requested, Uint32 flag); + +/* Windows message handling functions */ +static void DX5_Activate(_THIS, BOOL active, BOOL minimized); +static void DX5_RealizePalette(_THIS); +static void DX5_PaletteChanged(_THIS, HWND window); +static void DX5_WinPAINT(_THIS, HDC hdc); + +/* WinDIB driver functions for manipulating gamma ramps */ +extern int DIB_SetGammaRamp(_THIS, Uint16 *ramp); +extern int DIB_GetGammaRamp(_THIS, Uint16 *ramp); +extern void DIB_QuitGamma(_THIS); + +/* DX5 driver bootstrap functions */ + +static int DX5_Available(void) +{ + HINSTANCE DInputDLL; + HINSTANCE DDrawDLL; + int dinput_ok; + int ddraw_ok; + + /* Version check DINPUT.DLL and DDRAW.DLL (Is DirectX okay?) */ + dinput_ok = 0; + DInputDLL = LoadLibrary(TEXT("DINPUT.DLL")); + if ( DInputDLL != NULL ) { + dinput_ok = 1; + FreeLibrary(DInputDLL); + } + ddraw_ok = 0; + DDrawDLL = LoadLibrary(TEXT("DDRAW.DLL")); + if ( DDrawDLL != NULL ) { + HRESULT (WINAPI *DDrawCreate)(GUID *,LPDIRECTDRAW *,IUnknown *); + LPDIRECTDRAW DDraw; + + /* Try to create a valid DirectDraw object */ + DDrawCreate = (void *)GetProcAddress(DDrawDLL, TEXT("DirectDrawCreate")); + if ( (DDrawCreate != NULL) + && !FAILED(DDrawCreate(NULL, &DDraw, NULL)) ) { + if ( !FAILED(IDirectDraw_SetCooperativeLevel(DDraw, + NULL, DDSCL_NORMAL)) ) { + DDSURFACEDESC desc; + LPDIRECTDRAWSURFACE DDrawSurf; + LPDIRECTDRAWSURFACE3 DDrawSurf3; + + /* Try to create a DirectDrawSurface3 object */ + SDL_memset(&desc, 0, sizeof(desc)); + desc.dwSize = sizeof(desc); + desc.dwFlags = DDSD_CAPS; + desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE|DDSCAPS_VIDEOMEMORY; + if ( !FAILED(IDirectDraw_CreateSurface(DDraw, &desc, + &DDrawSurf, NULL)) ) { + if ( !FAILED(IDirectDrawSurface_QueryInterface(DDrawSurf, + &IID_IDirectDrawSurface3, (LPVOID *)&DDrawSurf3)) ) { + /* Yay! */ + ddraw_ok = 1; + + /* Clean up.. */ + IDirectDrawSurface3_Release(DDrawSurf3); + } + IDirectDrawSurface_Release(DDrawSurf); + } + } + IDirectDraw_Release(DDraw); + } + FreeLibrary(DDrawDLL); + } + return(dinput_ok && ddraw_ok); +} + +/* Functions for loading the DirectX functions dynamically */ +static HINSTANCE DDrawDLL = NULL; +static HINSTANCE DInputDLL = NULL; + +static void DX5_Unload(void) +{ + if ( DDrawDLL != NULL ) { + FreeLibrary(DDrawDLL); + DDrawCreate = NULL; + DDrawDLL = NULL; + } + if ( DInputDLL != NULL ) { + FreeLibrary(DInputDLL); + DInputCreate = NULL; + DInputDLL = NULL; + } +} +static int DX5_Load(void) +{ + int status; + + DX5_Unload(); + DDrawDLL = LoadLibrary(TEXT("DDRAW.DLL")); + if ( DDrawDLL != NULL ) { + DDrawCreate = (void *)GetProcAddress(DDrawDLL, + TEXT("DirectDrawCreate")); + } + DInputDLL = LoadLibrary(TEXT("DINPUT.DLL")); + if ( DInputDLL != NULL ) { + DInputCreate = (void *)GetProcAddress(DInputDLL, + TEXT("DirectInputCreateA")); + } + if ( DDrawDLL && DDrawCreate && DInputDLL && DInputCreate ) { + status = 0; + } else { + DX5_Unload(); + status = -1; + } + return status; +} + +static void DX5_DeleteDevice(SDL_VideoDevice *this) +{ + /* Free DirectDraw object */ + if ( ddraw2 != NULL ) { + IDirectDraw2_Release(ddraw2); + } + DX5_Unload(); + if ( this ) { + if ( this->hidden ) { + SDL_free(this->hidden); + } + if ( this->gl_data ) { + SDL_free(this->gl_data); + } + SDL_free(this); + } +} + +static SDL_VideoDevice *DX5_CreateDevice(int devindex) +{ + SDL_VideoDevice *device; + + /* Load DirectX */ + if ( DX5_Load() < 0 ) { + return(NULL); + } + + /* Initialize all variables that we clean on shutdown */ + device = (SDL_VideoDevice *)SDL_malloc(sizeof(SDL_VideoDevice)); + if ( device ) { + SDL_memset(device, 0, (sizeof *device)); + device->hidden = (struct SDL_PrivateVideoData *) + SDL_malloc((sizeof *device->hidden)); + device->gl_data = (struct SDL_PrivateGLData *) + SDL_malloc((sizeof *device->gl_data)); + } + if ( (device == NULL) || (device->hidden == NULL) || + (device->gl_data == NULL) ) { + SDL_OutOfMemory(); + DX5_DeleteDevice(device); + return(NULL); + } + SDL_memset(device->hidden, 0, (sizeof *device->hidden)); + SDL_memset(device->gl_data, 0, (sizeof *device->gl_data)); + + /* Set the function pointers */ + device->VideoInit = DX5_VideoInit; + device->ListModes = DX5_ListModes; + device->SetVideoMode = DX5_SetVideoMode; + device->UpdateMouse = WIN_UpdateMouse; + device->CreateYUVOverlay = DX5_CreateYUVOverlay; + device->SetColors = DX5_SetColors; + device->UpdateRects = NULL; + device->VideoQuit = DX5_VideoQuit; + device->AllocHWSurface = DX5_AllocHWSurface; + device->CheckHWBlit = DX5_CheckHWBlit; + device->FillHWRect = DX5_FillHWRect; + device->SetHWColorKey = DX5_SetHWColorKey; + device->SetHWAlpha = DX5_SetHWAlpha; + device->LockHWSurface = DX5_LockHWSurface; + device->UnlockHWSurface = DX5_UnlockHWSurface; + device->FlipHWSurface = DX5_FlipHWSurface; + device->FreeHWSurface = DX5_FreeHWSurface; + device->SetGammaRamp = DX5_SetGammaRamp; + device->GetGammaRamp = DX5_GetGammaRamp; +#if SDL_VIDEO_OPENGL + device->GL_LoadLibrary = WIN_GL_LoadLibrary; + device->GL_GetProcAddress = WIN_GL_GetProcAddress; + device->GL_GetAttribute = WIN_GL_GetAttribute; + device->GL_MakeCurrent = WIN_GL_MakeCurrent; + device->GL_SwapBuffers = WIN_GL_SwapBuffers; +#endif + device->SetCaption = WIN_SetWMCaption; + device->SetIcon = WIN_SetWMIcon; + device->IconifyWindow = WIN_IconifyWindow; + device->GrabInput = WIN_GrabInput; + device->GetWMInfo = WIN_GetWMInfo; + device->FreeWMCursor = WIN_FreeWMCursor; + device->CreateWMCursor = WIN_CreateWMCursor; + device->ShowWMCursor = WIN_ShowWMCursor; + device->WarpWMCursor = WIN_WarpWMCursor; + device->CheckMouseMode = WIN_CheckMouseMode; + device->InitOSKeymap = DX5_InitOSKeymap; + device->PumpEvents = DX5_PumpEvents; + + /* Set up the windows message handling functions */ + WIN_Activate = DX5_Activate; + WIN_RealizePalette = DX5_RealizePalette; + WIN_PaletteChanged = DX5_PaletteChanged; + WIN_WinPAINT = DX5_WinPAINT; + HandleMessage = DX5_HandleMessage; + + device->free = DX5_DeleteDevice; + + /* We're finally ready */ + return device; +} + +VideoBootStrap DIRECTX_bootstrap = { + "directx", "Win95/98/2000 DirectX", + DX5_Available, DX5_CreateDevice +}; + +static int cmpmodes(const void *va, const void *vb) +{ + SDL_Rect *a = *(SDL_Rect **)va; + SDL_Rect *b = *(SDL_Rect **)vb; + if ( a->w == b->w ) + return b->h - a->h; + else + return b->w - a->w; +} + +static HRESULT WINAPI EnumModes2(DDSURFACEDESC *desc, VOID *udata) +{ + SDL_VideoDevice *this = (SDL_VideoDevice *)udata; + struct DX5EnumRect *enumrect; +#if defined(NONAMELESSUNION) + int bpp = desc->ddpfPixelFormat.u1.dwRGBBitCount; + int refreshRate = desc->u2.dwRefreshRate; +#else + int bpp = desc->ddpfPixelFormat.dwRGBBitCount; + int refreshRate = desc->dwRefreshRate; +#endif + int maxRefreshRate; + + if ( desc->dwWidth <= SDL_desktop_mode.dmPelsWidth && + desc->dwHeight <= SDL_desktop_mode.dmPelsHeight ) { + maxRefreshRate = SDL_desktop_mode.dmDisplayFrequency; + } else { + maxRefreshRate = 85; /* safe value? */ + } + + switch (bpp) { + case 8: + case 16: + case 24: + case 32: + bpp /= 8; --bpp; + if ( enumlists[bpp] && + enumlists[bpp]->r.w == (Uint16)desc->dwWidth && + enumlists[bpp]->r.h == (Uint16)desc->dwHeight ) { + if ( refreshRate > enumlists[bpp]->refreshRate && + refreshRate <= maxRefreshRate ) { + enumlists[bpp]->refreshRate = refreshRate; +#ifdef DDRAW_DEBUG + fprintf(stderr, "New refresh rate for %d bpp: %dx%d at %d Hz\n", (bpp+1)*8, (int)desc->dwWidth, (int)desc->dwHeight, refreshRate); +#endif + } + break; + } + ++SDL_nummodes[bpp]; + enumrect = (struct DX5EnumRect*)SDL_malloc(sizeof(struct DX5EnumRect)); + if ( !enumrect ) { + SDL_OutOfMemory(); + return(DDENUMRET_CANCEL); + } + enumrect->refreshRate = refreshRate; + enumrect->r.x = 0; + enumrect->r.y = 0; + enumrect->r.w = (Uint16)desc->dwWidth; + enumrect->r.h = (Uint16)desc->dwHeight; + enumrect->next = enumlists[bpp]; + enumlists[bpp] = enumrect; +#ifdef DDRAW_DEBUG + fprintf(stderr, "New mode for %d bpp: %dx%d at %d Hz\n", (bpp+1)*8, (int)desc->dwWidth, (int)desc->dwHeight, refreshRate); +#endif + break; + } + + return(DDENUMRET_OK); +} + +void SetDDerror(const char *function, int code) +{ + static char *error; + static char errbuf[1024]; + + errbuf[0] = 0; + switch (code) { + case DDERR_GENERIC: + error = "Undefined error!"; + break; + case DDERR_EXCEPTION: + error = "Exception encountered"; + break; + case DDERR_INVALIDOBJECT: + error = "Invalid object"; + break; + case DDERR_INVALIDPARAMS: + error = "Invalid parameters"; + break; + case DDERR_NOTFOUND: + error = "Object not found"; + break; + case DDERR_INVALIDRECT: + error = "Invalid rectangle"; + break; + case DDERR_INVALIDCAPS: + error = "Invalid caps member"; + break; + case DDERR_INVALIDPIXELFORMAT: + error = "Invalid pixel format"; + break; + case DDERR_OUTOFMEMORY: + error = "Out of memory"; + break; + case DDERR_OUTOFVIDEOMEMORY: + error = "Out of video memory"; + break; + case DDERR_SURFACEBUSY: + error = "Surface busy"; + break; + case DDERR_SURFACELOST: + error = "Surface was lost"; + break; + case DDERR_WASSTILLDRAWING: + error = "DirectDraw is still drawing"; + break; + case DDERR_INVALIDSURFACETYPE: + error = "Invalid surface type"; + break; + case DDERR_NOEXCLUSIVEMODE: + error = "Not in exclusive access mode"; + break; + case DDERR_NOPALETTEATTACHED: + error = "No palette attached"; + break; + case DDERR_NOPALETTEHW: + error = "No palette hardware"; + break; + case DDERR_NOT8BITCOLOR: + error = "Not 8-bit color"; + break; + case DDERR_EXCLUSIVEMODEALREADYSET: + error = "Exclusive mode was already set"; + break; + case DDERR_HWNDALREADYSET: + error = "Window handle already set"; + break; + case DDERR_HWNDSUBCLASSED: + error = "Window handle is subclassed"; + break; + case DDERR_NOBLTHW: + error = "No blit hardware"; + break; + case DDERR_IMPLICITLYCREATED: + error = "Surface was implicitly created"; + break; + case DDERR_INCOMPATIBLEPRIMARY: + error = "Incompatible primary surface"; + break; + case DDERR_NOCOOPERATIVELEVELSET: + error = "No cooperative level set"; + break; + case DDERR_NODIRECTDRAWHW: + error = "No DirectDraw hardware"; + break; + case DDERR_NOEMULATION: + error = "No emulation available"; + break; + case DDERR_NOFLIPHW: + error = "No flip hardware"; + break; + case DDERR_NOTFLIPPABLE: + error = "Surface not flippable"; + break; + case DDERR_PRIMARYSURFACEALREADYEXISTS: + error = "Primary surface already exists"; + break; + case DDERR_UNSUPPORTEDMODE: + error = "Unsupported mode"; + break; + case DDERR_WRONGMODE: + error = "Surface created in different mode"; + break; + case DDERR_UNSUPPORTED: + error = "Operation not supported"; + break; + case E_NOINTERFACE: + error = "Interface not present"; + break; + default: + SDL_snprintf(errbuf, SDL_arraysize(errbuf), + "%s: Unknown DirectDraw error: 0x%x", + function, code); + break; + } + if ( ! errbuf[0] ) { + SDL_snprintf(errbuf, SDL_arraysize(errbuf), "%s: %s", function, error); + } + SDL_SetError("%s", errbuf); + return; +} + + +static int DX5_UpdateVideoInfo(_THIS) +{ + /* This needs to be DDCAPS_DX5 for the DirectDraw2 interface */ +#if DIRECTDRAW_VERSION <= 0x300 +#error Your version of DirectX must be greater than or equal to 5.0 +#endif +#ifndef IDirectDrawGammaControl_SetGammaRamp + /*if gamma is undefined then we really have directx <= 0x500*/ + DDCAPS DDCaps; +#else + DDCAPS_DX5 DDCaps; +#endif + HRESULT result; + + /* Fill in our hardware acceleration capabilities */ + SDL_memset(&DDCaps, 0, sizeof(DDCaps)); + DDCaps.dwSize = sizeof(DDCaps); + result = IDirectDraw2_GetCaps(ddraw2, (DDCAPS *)&DDCaps, NULL); + if ( result != DD_OK ) { + SetDDerror("DirectDraw2::GetCaps", result); + return(-1); + } + this->info.hw_available = 1; + if ( (DDCaps.dwCaps & DDCAPS_BLT) == DDCAPS_BLT ) { + this->info.blit_hw = 1; + } + if ( ((DDCaps.dwCaps & DDCAPS_COLORKEY) == DDCAPS_COLORKEY) && + ((DDCaps.dwCKeyCaps & DDCKEYCAPS_SRCBLT) == DDCKEYCAPS_SRCBLT) ) { + this->info.blit_hw_CC = 1; + } + if ( (DDCaps.dwCaps & DDCAPS_ALPHA) == DDCAPS_ALPHA ) { + /* This is only for alpha channel, and DirectX 6 + doesn't support 2D alpha blits yet, so set it 0 + */ + this->info.blit_hw_A = 0; + } + if ( (DDCaps.dwCaps & DDCAPS_CANBLTSYSMEM) == DDCAPS_CANBLTSYSMEM ) { + this->info.blit_sw = 1; + /* This isn't necessarily true, but the HEL will cover us */ + this->info.blit_sw_CC = this->info.blit_hw_CC; + this->info.blit_sw_A = this->info.blit_hw_A; + } + if ( (DDCaps.dwCaps & DDCAPS_BLTCOLORFILL) == DDCAPS_BLTCOLORFILL ) { + this->info.blit_fill = 1; + } + + /* Find out how much video memory is available */ + { DDSCAPS ddsCaps; + DWORD total_mem; + ddsCaps.dwCaps = DDSCAPS_VIDEOMEMORY; + result = IDirectDraw2_GetAvailableVidMem(ddraw2, + &ddsCaps, &total_mem, NULL); + if ( result != DD_OK ) { + total_mem = DDCaps.dwVidMemTotal; + } + this->info.video_mem = total_mem/1024; + } + return(0); +} + +int DX5_VideoInit(_THIS, SDL_PixelFormat *vformat) +{ + HRESULT result; + LPDIRECTDRAW ddraw; + int i, j; + HDC hdc; + + /* Intialize everything */ + ddraw2 = NULL; + SDL_primary = NULL; + SDL_clipper = NULL; + SDL_palette = NULL; + for ( i=0; i<NUM_MODELISTS; ++i ) { + SDL_nummodes[i] = 0; + SDL_modelist[i] = NULL; + SDL_modeindex[i] = 0; + } + colorchange_expected = 0; + + /* Create the window */ + if ( DX5_CreateWindow(this) < 0 ) { + return(-1); + } + +#if !SDL_AUDIO_DISABLED + DX5_SoundFocus(SDL_Window); +#endif + + /* Create the DirectDraw object */ + result = DDrawCreate(NULL, &ddraw, NULL); + if ( result != DD_OK ) { + SetDDerror("DirectDrawCreate", result); + return(-1); + } + result = IDirectDraw_QueryInterface(ddraw, &IID_IDirectDraw2, + (LPVOID *)&ddraw2); + IDirectDraw_Release(ddraw); + if ( result != DD_OK ) { + SetDDerror("DirectDraw::QueryInterface", result); + return(-1); + } + + /* Determine the screen depth */ + hdc = GetDC(SDL_Window); + vformat->BitsPerPixel = GetDeviceCaps(hdc,PLANES) * + GetDeviceCaps(hdc,BITSPIXEL); + ReleaseDC(SDL_Window, hdc); + +#ifndef NO_CHANGEDISPLAYSETTINGS + /* Query for the desktop resolution */ + EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &SDL_desktop_mode); + this->info.current_w = SDL_desktop_mode.dmPelsWidth; + this->info.current_h = SDL_desktop_mode.dmPelsHeight; +#endif + + /* Enumerate the available fullscreen modes */ + for ( i=0; i<NUM_MODELISTS; ++i ) + enumlists[i] = NULL; + + result = IDirectDraw2_EnumDisplayModes(ddraw2,DDEDM_REFRESHRATES,NULL,this,EnumModes2); + if ( result != DD_OK ) { + SetDDerror("DirectDraw2::EnumDisplayModes", result); + return(-1); + } + for ( i=0; i<NUM_MODELISTS; ++i ) { + struct DX5EnumRect *rect; + SDL_modelist[i] = (SDL_Rect **) + SDL_malloc((SDL_nummodes[i]+1)*sizeof(SDL_Rect *)); + if ( SDL_modelist[i] == NULL ) { + SDL_OutOfMemory(); + return(-1); + } + for ( j = 0, rect = enumlists[i]; rect; ++j, rect = rect->next ) { + SDL_modelist[i][j] = &rect->r; + } + SDL_modelist[i][j] = NULL; + + if ( SDL_nummodes[i] > 0 ) { + SDL_qsort(SDL_modelist[i], SDL_nummodes[i], sizeof *SDL_modelist[i], cmpmodes); + } + } + + /* Fill in some window manager capabilities */ + this->info.wm_available = 1; + + /* Fill in the video hardware capabilities */ + DX5_UpdateVideoInfo(this); + + return(0); +} + +SDL_Rect **DX5_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags) +{ + int bpp; + + bpp = format->BitsPerPixel; + if ( (flags & SDL_FULLSCREEN) == SDL_FULLSCREEN ) { + /* FIXME: No support for 1 bpp or 4 bpp formats */ + switch (bpp) { /* Does windows support other BPP? */ + case 8: + case 16: + case 24: + case 32: + bpp = (bpp/8)-1; + if ( SDL_nummodes[bpp] > 0 ) + return(SDL_modelist[bpp]); + /* Fall through */ + default: + return((SDL_Rect **)0); + } + } else { + if ( this->screen->format->BitsPerPixel == bpp ) { + return((SDL_Rect **)-1); + } else { + return((SDL_Rect **)0); + } + } +} + +/* Various screen update functions available */ +static void DX5_WindowUpdate(_THIS, int numrects, SDL_Rect *rects); +static void DX5_DirectUpdate(_THIS, int numrects, SDL_Rect *rects); + +SDL_Surface *DX5_SetVideoMode(_THIS, SDL_Surface *current, + int width, int height, int bpp, Uint32 flags) +{ + SDL_Surface *video; + int prev_w = -1; + int prev_h = -1; + HRESULT result; + DWORD sharemode; + DWORD style; + const DWORD directstyle = + (WS_POPUP); + const DWORD windowstyle = + (WS_OVERLAPPED|WS_CAPTION|WS_SYSMENU|WS_MINIMIZEBOX); + const DWORD resizestyle = + (WS_THICKFRAME|WS_MAXIMIZEBOX); + DDSURFACEDESC ddsd; + LPDIRECTDRAWSURFACE dd_surface1; + LPDIRECTDRAWSURFACE3 dd_surface3; + + SDL_resizing = 1; +#ifdef DDRAW_DEBUG + fprintf(stderr, "Setting %dx%dx%d video mode\n", width, height, bpp); +#endif + /* Clean up any previous DirectDraw surfaces */ + if ( current->hwdata ) { + this->FreeHWSurface(this, current); + current->hwdata = NULL; + } + if ( SDL_primary != NULL ) { + IDirectDrawSurface3_Release(SDL_primary); + SDL_primary = NULL; + } + +#ifndef NO_CHANGEDISPLAYSETTINGS + /* Unset any previous OpenGL fullscreen mode */ + if ( (current->flags & (SDL_OPENGL|SDL_FULLSCREEN)) == + (SDL_OPENGL|SDL_FULLSCREEN) ) { + ChangeDisplaySettings(NULL, 0); + } +#endif + + /* Clean up any GL context that may be hanging around */ + if ( current->flags & SDL_OPENGL ) { + WIN_GL_ShutDown(this); + } + + /* If we are setting a GL mode, use GDI, not DirectX (yuck) */ + if ( flags & SDL_OPENGL ) { + Uint32 Rmask, Gmask, Bmask; + + /* Recalculate the bitmasks if necessary */ + if ( bpp == current->format->BitsPerPixel ) { + video = current; + } else { + switch (bpp) { + case 15: + case 16: + if ( 0 /*DIB_SussScreenDepth() == 15*/ ) { + /* 5-5-5 */ + Rmask = 0x00007c00; + Gmask = 0x000003e0; + Bmask = 0x0000001f; + } else { + /* 5-6-5 */ + Rmask = 0x0000f800; + Gmask = 0x000007e0; + Bmask = 0x0000001f; + } + break; + case 24: + case 32: + /* GDI defined as 8-8-8 */ + Rmask = 0x00ff0000; + Gmask = 0x0000ff00; + Bmask = 0x000000ff; + break; + default: + Rmask = 0x00000000; + Gmask = 0x00000000; + Bmask = 0x00000000; + break; + } + video = SDL_CreateRGBSurface(SDL_SWSURFACE, 0, 0, bpp, + Rmask, Gmask, Bmask, 0); + if ( video == NULL ) { + SDL_OutOfMemory(); + return(NULL); + } + } + + /* Fill in part of the video surface */ + prev_w = video->w; + prev_h = video->h; + video->flags = 0; /* Clear flags */ + video->w = width; + video->h = height; + video->pitch = SDL_CalculatePitch(video); + +#ifndef NO_CHANGEDISPLAYSETTINGS + /* Set fullscreen mode if appropriate. + Ugh, since our list of valid video modes comes from + the DirectX driver, we may not actually be able to + change to the desired resolution here. + FIXME: Should we do a closest match? + */ + if ( (flags & SDL_FULLSCREEN) == SDL_FULLSCREEN ) { + DEVMODE settings; + BOOL changed; + + SDL_memset(&settings, 0, sizeof(DEVMODE)); + settings.dmSize = sizeof(DEVMODE); + settings.dmBitsPerPel = video->format->BitsPerPixel; + settings.dmPelsWidth = width; + settings.dmPelsHeight = height; + settings.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT | DM_BITSPERPEL; + if ( width <= (int)SDL_desktop_mode.dmPelsWidth && + height <= (int)SDL_desktop_mode.dmPelsHeight ) { + settings.dmDisplayFrequency = SDL_desktop_mode.dmDisplayFrequency; + settings.dmFields |= DM_DISPLAYFREQUENCY; + } + changed = (ChangeDisplaySettings(&settings, CDS_FULLSCREEN) == DISP_CHANGE_SUCCESSFUL); + if ( ! changed && (settings.dmFields & DM_DISPLAYFREQUENCY) ) { + settings.dmFields &= ~DM_DISPLAYFREQUENCY; + changed = (ChangeDisplaySettings(&settings, CDS_FULLSCREEN) == DISP_CHANGE_SUCCESSFUL); + } + if ( changed ) { + video->flags |= SDL_FULLSCREEN; + SDL_fullscreen_mode = settings; + } + } +#endif /* !NO_CHANGEDISPLAYSETTINGS */ + + style = GetWindowLong(SDL_Window, GWL_STYLE); + style &= ~(resizestyle|WS_MAXIMIZE); + if ( video->flags & SDL_FULLSCREEN ) { + style &= ~windowstyle; + style |= directstyle; + } else { + if ( flags & SDL_NOFRAME ) { + style &= ~windowstyle; + style |= directstyle; + video->flags |= SDL_NOFRAME; + } else { + style &= ~directstyle; + style |= windowstyle; + if ( flags & SDL_RESIZABLE ) { + style |= resizestyle; + video->flags |= SDL_RESIZABLE; + } + } +#if WS_MAXIMIZE + if (IsZoomed(SDL_Window)) style |= WS_MAXIMIZE; +#endif + } + + /* DJM: Don't piss of anyone who has setup his own window */ + if ( !SDL_windowid ) + SetWindowLong(SDL_Window, GWL_STYLE, style); + + /* Resize the window (copied from SDL WinDIB driver) */ + if ( !SDL_windowid && !IsZoomed(SDL_Window) ) { + RECT bounds; + int x, y; + HWND top; + UINT swp_flags; + const char *window = NULL; + const char *center = NULL; + + if ( video->w != prev_w || video->h != prev_h ) { + window = SDL_getenv("SDL_VIDEO_WINDOW_POS"); + center = SDL_getenv("SDL_VIDEO_CENTERED"); + if ( window ) { + if ( SDL_sscanf(window, "%d,%d", &x, &y) == 2 ) { + SDL_windowX = x; + SDL_windowY = y; + } + if ( SDL_strcmp(window, "center") == 0 ) { + center = window; + } + } + } + swp_flags = (SWP_NOCOPYBITS | SWP_SHOWWINDOW); + + bounds.left = SDL_windowX; + bounds.top = SDL_windowY; + bounds.right = SDL_windowX+video->w; + bounds.bottom = SDL_windowY+video->h; + AdjustWindowRectEx(&bounds, GetWindowLong(SDL_Window, GWL_STYLE), (GetMenu(SDL_Window) != NULL), 0); + width = bounds.right-bounds.left; + height = bounds.bottom-bounds.top; + if ( (flags & SDL_FULLSCREEN) ) { + x = (GetSystemMetrics(SM_CXSCREEN)-width)/2; + y = (GetSystemMetrics(SM_CYSCREEN)-height)/2; + } else if ( center ) { + x = (GetSystemMetrics(SM_CXSCREEN)-width)/2; + y = (GetSystemMetrics(SM_CYSCREEN)-height)/2; + } else if ( SDL_windowX || SDL_windowY || window ) { + x = bounds.left; + y = bounds.top; + } else { + x = y = -1; + swp_flags |= SWP_NOMOVE; + } + if ( flags & SDL_FULLSCREEN ) { + top = HWND_TOPMOST; + } else { + top = HWND_NOTOPMOST; + } + SetWindowPos(SDL_Window, top, x, y, width, height, swp_flags); + if ( !(flags & SDL_FULLSCREEN) ) { + SDL_windowX = SDL_bounds.left; + SDL_windowY = SDL_bounds.top; + } + SetForegroundWindow(SDL_Window); + } + SDL_resizing = 0; + + /* Set up for OpenGL */ + if ( WIN_GL_SetupWindow(this) < 0 ) { + return(NULL); + } + video->flags |= SDL_OPENGL; + return(video); + } + + /* Set the appropriate window style */ + style = GetWindowLong(SDL_Window, GWL_STYLE); + style &= ~(resizestyle|WS_MAXIMIZE); + if ( (flags & SDL_FULLSCREEN) == SDL_FULLSCREEN ) { + style &= ~windowstyle; + style |= directstyle; + } else { + if ( flags & SDL_NOFRAME ) { + style &= ~windowstyle; + style |= directstyle; + } else { + style &= ~directstyle; + style |= windowstyle; + if ( flags & SDL_RESIZABLE ) { + style |= resizestyle; + } + } +#if WS_MAXIMIZE + if (IsZoomed(SDL_Window)) style |= WS_MAXIMIZE; +#endif + } + /* DJM: Don't piss of anyone who has setup his own window */ + if ( !SDL_windowid ) + SetWindowLong(SDL_Window, GWL_STYLE, style); + + /* Set DirectDraw sharing mode.. exclusive when fullscreen */ + if ( (flags & SDL_FULLSCREEN) == SDL_FULLSCREEN ) { + sharemode = DDSCL_FULLSCREEN|DDSCL_EXCLUSIVE|DDSCL_ALLOWREBOOT; + } else { + sharemode = DDSCL_NORMAL; + } + result = IDirectDraw2_SetCooperativeLevel(ddraw2,SDL_Window,sharemode); + if ( result != DD_OK ) { + SetDDerror("DirectDraw2::SetCooperativeLevel", result); + return(NULL); + } + + /* Set the display mode, if we are in fullscreen mode */ + if ( (flags & SDL_FULLSCREEN) == SDL_FULLSCREEN ) { + RECT bounds; + struct DX5EnumRect *rect; + int maxRefreshRate; + + /* Cover up desktop during mode change */ + bounds.left = 0; + bounds.top = 0; + bounds.right = GetSystemMetrics(SM_CXSCREEN); + bounds.bottom = GetSystemMetrics(SM_CYSCREEN); + AdjustWindowRectEx(&bounds, GetWindowLong(SDL_Window, GWL_STYLE), (GetMenu(SDL_Window) != NULL), 0); + SetWindowPos(SDL_Window, HWND_TOPMOST, + bounds.left, bounds.top, + bounds.right - bounds.left, + bounds.bottom - bounds.top, SWP_NOCOPYBITS); + ShowWindow(SDL_Window, SW_SHOW); + while ( GetForegroundWindow() != SDL_Window ) { + SetForegroundWindow(SDL_Window); + SDL_Delay(100); + } + + /* find maximum monitor refresh rate for this resolution */ + /* Dmitry Yakimov ftech@tula.net */ + maxRefreshRate = 0; /* system default */ + for ( rect = enumlists[bpp / 8 - 1]; rect; rect = rect->next ) { + if ( (width == rect->r.w) && (height == rect->r.h) ) { + maxRefreshRate = rect->refreshRate; + break; + } + } +#ifdef DDRAW_DEBUG + fprintf(stderr, "refresh rate = %d Hz\n", maxRefreshRate); +#endif + + result = IDirectDraw2_SetDisplayMode(ddraw2, width, height, bpp, maxRefreshRate, 0); + if ( result != DD_OK ) { + result = IDirectDraw2_SetDisplayMode(ddraw2, width, height, bpp, 0, 0); + if ( result != DD_OK ) { + /* We couldn't set fullscreen mode, try window */ + return(DX5_SetVideoMode(this, current, width, height, bpp, flags & ~SDL_FULLSCREEN)); + } + } + DX5_DInputReset(this, 1); + } else { + DX5_DInputReset(this, 0); + } + DX5_UpdateVideoInfo(this); + + /* Create a primary DirectDraw surface */ + SDL_memset(&ddsd, 0, sizeof(ddsd)); + ddsd.dwSize = sizeof(ddsd); + ddsd.dwFlags = DDSD_CAPS; + ddsd.ddsCaps.dwCaps = (DDSCAPS_PRIMARYSURFACE|DDSCAPS_VIDEOMEMORY); + if ( (flags & SDL_FULLSCREEN) != SDL_FULLSCREEN ) { + /* There's no windowed double-buffering */ + flags &= ~SDL_DOUBLEBUF; + } + if ( (flags & SDL_DOUBLEBUF) == SDL_DOUBLEBUF ) { + ddsd.dwFlags |= DDSD_BACKBUFFERCOUNT; + ddsd.ddsCaps.dwCaps |= (DDSCAPS_COMPLEX|DDSCAPS_FLIP); + ddsd.dwBackBufferCount = 1; + } + result = IDirectDraw2_CreateSurface(ddraw2, &ddsd, &dd_surface1, NULL); + if ( (result != DD_OK) && ((flags & SDL_DOUBLEBUF) == SDL_DOUBLEBUF) ) { + ddsd.dwFlags &= ~DDSD_BACKBUFFERCOUNT; + ddsd.ddsCaps.dwCaps &= ~(DDSCAPS_COMPLEX|DDSCAPS_FLIP); + ddsd.dwBackBufferCount = 0; + result = IDirectDraw2_CreateSurface(ddraw2, + &ddsd, &dd_surface1, NULL); + } + if ( result != DD_OK ) { + SetDDerror("DirectDraw2::CreateSurface(PRIMARY)", result); + return(NULL); + } + result = IDirectDrawSurface_QueryInterface(dd_surface1, + &IID_IDirectDrawSurface3, (LPVOID *)&SDL_primary); + if ( result != DD_OK ) { + SetDDerror("DirectDrawSurface::QueryInterface", result); + return(NULL); + } + IDirectDrawSurface_Release(dd_surface1); + + /* Get the format of the primary DirectDraw surface */ + SDL_memset(&ddsd, 0, sizeof(ddsd)); + ddsd.dwSize = sizeof(ddsd); + ddsd.dwFlags = DDSD_PIXELFORMAT|DDSD_CAPS; + result = IDirectDrawSurface3_GetSurfaceDesc(SDL_primary, &ddsd); + if ( result != DD_OK ) { + SetDDerror("DirectDrawSurface::GetSurfaceDesc", result); + return(NULL); + } + if ( ! (ddsd.ddpfPixelFormat.dwFlags&DDPF_RGB) ) { + SDL_SetError("Primary DDRAW surface is not RGB format"); + return(NULL); + } + + /* Free old palette and create a new one if we're in 8-bit mode */ + if ( SDL_palette != NULL ) { + IDirectDrawPalette_Release(SDL_palette); + SDL_palette = NULL; + } +#if defined(NONAMELESSUNION) + if ( ddsd.ddpfPixelFormat.u1.dwRGBBitCount == 8 ) { +#else + if ( ddsd.ddpfPixelFormat.dwRGBBitCount == 8 ) { +#endif + int i; + + if ( (flags & SDL_FULLSCREEN) == SDL_FULLSCREEN ) { + /* We have access to the entire palette */ + for ( i=0; i<256; ++i ) { + SDL_colors[i].peFlags = + (PC_NOCOLLAPSE|PC_RESERVED); + SDL_colors[i].peRed = 0; + SDL_colors[i].peGreen = 0; + SDL_colors[i].peBlue = 0; + } + } else { + /* First 10 colors are reserved by Windows */ + for ( i=0; i<10; ++i ) { + SDL_colors[i].peFlags = PC_EXPLICIT; + SDL_colors[i].peRed = i; + SDL_colors[i].peGreen = 0; + SDL_colors[i].peBlue = 0; + } + for ( i=10; i<(10+236); ++i ) { + SDL_colors[i].peFlags = PC_NOCOLLAPSE; + SDL_colors[i].peRed = 0; + SDL_colors[i].peGreen = 0; + SDL_colors[i].peBlue = 0; + } + /* Last 10 colors are reserved by Windows */ + for ( i=246; i<256; ++i ) { + SDL_colors[i].peFlags = PC_EXPLICIT; + SDL_colors[i].peRed = i; + SDL_colors[i].peGreen = 0; + SDL_colors[i].peBlue = 0; + } + } + result = IDirectDraw2_CreatePalette(ddraw2, + (DDPCAPS_8BIT|DDPCAPS_ALLOW256), + SDL_colors, &SDL_palette, NULL); + if ( result != DD_OK ) { + SetDDerror("DirectDraw2::CreatePalette", result); + return(NULL); + } + result = IDirectDrawSurface3_SetPalette(SDL_primary, + SDL_palette); + if ( result != DD_OK ) { + SetDDerror("DirectDrawSurface3::SetPalette", result); + return(NULL); + } + } + + /* Create our video surface using the same pixel format */ + video = current; + if ( (width != video->w) || (height != video->h) + || (video->format->BitsPerPixel != +#if defined(NONAMELESSUNION) + ddsd.ddpfPixelFormat.u1.dwRGBBitCount) ) { +#else + ddsd.ddpfPixelFormat.dwRGBBitCount) ) { +#endif + SDL_FreeSurface(video); + video = SDL_CreateRGBSurface(SDL_SWSURFACE, 0, 0, +#if defined(NONAMELESSUNION) + ddsd.ddpfPixelFormat.u1.dwRGBBitCount, + ddsd.ddpfPixelFormat.u2.dwRBitMask, + ddsd.ddpfPixelFormat.u3.dwGBitMask, + ddsd.ddpfPixelFormat.u4.dwBBitMask, +#else + ddsd.ddpfPixelFormat.dwRGBBitCount, + ddsd.ddpfPixelFormat.dwRBitMask, + ddsd.ddpfPixelFormat.dwGBitMask, + ddsd.ddpfPixelFormat.dwBBitMask, +#endif + 0); + if ( video == NULL ) { + SDL_OutOfMemory(); + return(NULL); + } + prev_w = video->w; + prev_h = video->h; + video->w = width; + video->h = height; + video->pitch = 0; + } + video->flags = 0; /* Clear flags */ + + /* If not fullscreen, locking is possible, but it doesn't do what + the caller really expects -- if the locked surface is written to, + the appropriate portion of the entire screen is modified, not + the application window, as we would like. + Note that it is still possible to write directly to display + memory, but the application must respect the clip list of + the surface. There might be some odd timing interactions + involving clip list updates and background refreshing as + Windows moves other windows across our window. + We currently don't support this, even though it might be a + good idea since BeOS has an implementation of BDirectWindow + that does the same thing. This would be most useful for + applications that do complete screen updates every frame. + -- Fixme? + */ + if ( (flags & SDL_FULLSCREEN) != SDL_FULLSCREEN ) { + /* Necessary if we're going from fullscreen to window */ + if ( video->pixels == NULL ) { + video->pitch = (width*video->format->BytesPerPixel); + /* Pitch needs to be QWORD (8-byte) aligned */ + video->pitch = (video->pitch + 7) & ~7; + video->pixels = (void *)SDL_malloc(video->h*video->pitch); + if ( video->pixels == NULL ) { + if ( video != current ) { + SDL_FreeSurface(video); + } + SDL_OutOfMemory(); + return(NULL); + } + } + dd_surface3 = NULL; +#if 0 /* FIXME: enable this when SDL consistently reports lost surfaces */ + if ( (flags & SDL_HWSURFACE) == SDL_HWSURFACE ) { + video->flags |= SDL_HWSURFACE; + } else { + video->flags |= SDL_SWSURFACE; + } +#else + video->flags |= SDL_SWSURFACE; +#endif + if ( (flags & SDL_RESIZABLE) && !(flags & SDL_NOFRAME) ) { + video->flags |= SDL_RESIZABLE; + } + if ( flags & SDL_NOFRAME ) { + video->flags |= SDL_NOFRAME; + } + } else { + /* Necessary if we're going from window to fullscreen */ + if ( video->pixels != NULL ) { + SDL_free(video->pixels); + video->pixels = NULL; + } + dd_surface3 = SDL_primary; + video->flags |= SDL_HWSURFACE; + } + + /* See if the primary surface has double-buffering enabled */ + if ( (ddsd.ddsCaps.dwCaps & DDSCAPS_FLIP) == DDSCAPS_FLIP ) { + video->flags |= SDL_DOUBLEBUF; + } + + /* Allocate the SDL surface associated with the primary surface */ + if ( DX5_AllocDDSurface(this, video, dd_surface3, + video->flags&SDL_HWSURFACE) < 0 ) { + if ( video != current ) { + SDL_FreeSurface(video); + } + return(NULL); + } + + /* Use the appropriate blitting function */ + if ( (flags & SDL_FULLSCREEN) == SDL_FULLSCREEN ) { + video->flags |= SDL_FULLSCREEN; + if ( video->format->palette != NULL ) { + video->flags |= SDL_HWPALETTE; + } + this->UpdateRects = DX5_DirectUpdate; + } else { + this->UpdateRects = DX5_WindowUpdate; + } + + /* Make our window the proper size, set the clipper, then show it */ + if ( (flags & SDL_FULLSCREEN) != SDL_FULLSCREEN ) { + /* Create and set a clipper on our primary surface */ + if ( SDL_clipper == NULL ) { + result = IDirectDraw2_CreateClipper(ddraw2, + 0, &SDL_clipper, NULL); + if ( result != DD_OK ) { + if ( video != current ) { + SDL_FreeSurface(video); + } + SetDDerror("DirectDraw2::CreateClipper",result); + return(NULL); + } + } + result = IDirectDrawClipper_SetHWnd(SDL_clipper, 0, SDL_Window); + if ( result != DD_OK ) { + if ( video != current ) { + SDL_FreeSurface(video); + } + SetDDerror("DirectDrawClipper::SetHWnd", result); + return(NULL); + } + result = IDirectDrawSurface3_SetClipper(SDL_primary, + SDL_clipper); + if ( result != DD_OK ) { + if ( video != current ) { + SDL_FreeSurface(video); + } + SetDDerror("DirectDrawSurface3::SetClipper", result); + return(NULL); + } + + /* Resize the window (copied from SDL WinDIB driver) */ + if ( !SDL_windowid && !IsZoomed(SDL_Window) ) { + RECT bounds; + int x, y; + UINT swp_flags; + const char *window = NULL; + const char *center = NULL; + + if ( video->w != prev_w || video->h != prev_h ) { + window = SDL_getenv("SDL_VIDEO_WINDOW_POS"); + center = SDL_getenv("SDL_VIDEO_CENTERED"); + if ( window ) { + if ( SDL_sscanf(window, "%d,%d", &x, &y) == 2 ) { + SDL_windowX = x; + SDL_windowY = y; + } + if ( SDL_strcmp(window, "center") == 0 ) { + center = window; + } + } + } + swp_flags = SWP_NOCOPYBITS; + + bounds.left = SDL_windowX; + bounds.top = SDL_windowY; + bounds.right = SDL_windowX+video->w; + bounds.bottom = SDL_windowY+video->h; + AdjustWindowRectEx(&bounds, GetWindowLong(SDL_Window, GWL_STYLE), (GetMenu(SDL_Window) != NULL), 0); + width = bounds.right-bounds.left; + height = bounds.bottom-bounds.top; + if ( center ) { + x = (GetSystemMetrics(SM_CXSCREEN)-width)/2; + y = (GetSystemMetrics(SM_CYSCREEN)-height)/2; + } else if ( SDL_windowX || SDL_windowY || window ) { + x = bounds.left; + y = bounds.top; + } else { + x = y = -1; + swp_flags |= SWP_NOMOVE; + } + SetWindowPos(SDL_Window, HWND_NOTOPMOST, x, y, width, height, swp_flags); + SDL_windowX = SDL_bounds.left; + SDL_windowY = SDL_bounds.top; + } + + } + ShowWindow(SDL_Window, SW_SHOW); + SetForegroundWindow(SDL_Window); + SDL_resizing = 0; + + /* JC 14 Mar 2006 + Flush the message loop or this can cause big problems later + Especially if the user decides to use dialog boxes or assert()! + */ + WIN_FlushMessageQueue(); + + /* We're live! */ + return(video); +} + +struct private_hwdata { + LPDIRECTDRAWSURFACE3 dd_surface; + LPDIRECTDRAWSURFACE3 dd_writebuf; +}; + +static int DX5_AllocDDSurface(_THIS, SDL_Surface *surface, + LPDIRECTDRAWSURFACE3 requested, Uint32 flag) +{ + LPDIRECTDRAWSURFACE dd_surface1; + LPDIRECTDRAWSURFACE3 dd_surface3; + DDSURFACEDESC ddsd; + HRESULT result; + + /* Clear the hardware flag, in case we fail */ + surface->flags &= ~flag; + + /* Allocate the hardware acceleration data */ + surface->hwdata = (struct private_hwdata *) + SDL_malloc(sizeof(*surface->hwdata)); + if ( surface->hwdata == NULL ) { + SDL_OutOfMemory(); + return(-1); + } + dd_surface3 = NULL; + + /* Set up the surface description */ + SDL_memset(&ddsd, 0, sizeof(ddsd)); + ddsd.dwSize = sizeof(ddsd); + ddsd.dwFlags = (DDSD_WIDTH|DDSD_HEIGHT|DDSD_CAPS| + DDSD_PITCH|DDSD_PIXELFORMAT); + ddsd.dwWidth = surface->w; + ddsd.dwHeight= surface->h; +#if defined(NONAMELESSUNION) + ddsd.u1.lPitch = surface->pitch; +#else + ddsd.lPitch = surface->pitch; +#endif + if ( (flag & SDL_HWSURFACE) == SDL_HWSURFACE ) { + ddsd.ddsCaps.dwCaps = + (DDSCAPS_OFFSCREENPLAIN|DDSCAPS_VIDEOMEMORY); + } else { + ddsd.ddsCaps.dwCaps = + (DDSCAPS_OFFSCREENPLAIN|DDSCAPS_SYSTEMMEMORY); + } + ddsd.ddpfPixelFormat.dwSize = sizeof(ddsd.ddpfPixelFormat); + ddsd.ddpfPixelFormat.dwFlags = DDPF_RGB; + if ( surface->format->palette ) { + ddsd.ddpfPixelFormat.dwFlags |= DDPF_PALETTEINDEXED8; + } +#if defined(NONAMELESSUNION) + ddsd.ddpfPixelFormat.u1.dwRGBBitCount = surface->format->BitsPerPixel; + ddsd.ddpfPixelFormat.u2.dwRBitMask = surface->format->Rmask; + ddsd.ddpfPixelFormat.u3.dwGBitMask = surface->format->Gmask; + ddsd.ddpfPixelFormat.u4.dwBBitMask = surface->format->Bmask; +#else + ddsd.ddpfPixelFormat.dwRGBBitCount = surface->format->BitsPerPixel; + ddsd.ddpfPixelFormat.dwRBitMask = surface->format->Rmask; + ddsd.ddpfPixelFormat.dwGBitMask = surface->format->Gmask; + ddsd.ddpfPixelFormat.dwBBitMask = surface->format->Bmask; +#endif + + /* Create the DirectDraw video surface */ + if ( requested != NULL ) { + dd_surface3 = requested; + } else { + result = IDirectDraw2_CreateSurface(ddraw2, + &ddsd, &dd_surface1, NULL); + if ( result != DD_OK ) { + SetDDerror("DirectDraw2::CreateSurface", result); + goto error_end; + } + result = IDirectDrawSurface_QueryInterface(dd_surface1, + &IID_IDirectDrawSurface3, (LPVOID *)&dd_surface3); + IDirectDrawSurface_Release(dd_surface1); + if ( result != DD_OK ) { + SetDDerror("DirectDrawSurface::QueryInterface", result); + goto error_end; + } + } + + if ( (flag & SDL_HWSURFACE) == SDL_HWSURFACE ) { + /* Check to see whether the surface actually ended up + in video memory, and fail if not. We expect the + surfaces we create here to actually be in hardware! + */ + result = IDirectDrawSurface3_GetCaps(dd_surface3,&ddsd.ddsCaps); + if ( result != DD_OK ) { + SetDDerror("DirectDrawSurface3::GetCaps", result); + goto error_end; + } + if ( (ddsd.ddsCaps.dwCaps&DDSCAPS_VIDEOMEMORY) != + DDSCAPS_VIDEOMEMORY ) { + SDL_SetError("No room in video memory"); + goto error_end; + } + } else { + /* Try to hook our surface memory */ + ddsd.dwFlags = DDSD_LPSURFACE; + ddsd.lpSurface = surface->pixels; + result = IDirectDrawSurface3_SetSurfaceDesc(dd_surface3, + &ddsd, 0); + if ( result != DD_OK ) { + SetDDerror("DirectDraw2::SetSurfaceDesc", result); + goto error_end; + } + + } + + /* Make sure the surface format was set properly */ + SDL_memset(&ddsd, 0, sizeof(ddsd)); + ddsd.dwSize = sizeof(ddsd); + result = IDirectDrawSurface3_Lock(dd_surface3, NULL, + &ddsd, (DDLOCK_NOSYSLOCK|DDLOCK_WAIT), NULL); + if ( result != DD_OK ) { + SetDDerror("DirectDrawSurface3::Lock", result); + goto error_end; + } + IDirectDrawSurface3_Unlock(dd_surface3, NULL); + + if ( (flag & SDL_HWSURFACE) == SDL_SWSURFACE ) { + if ( ddsd.lpSurface != surface->pixels ) { + SDL_SetError("DDraw didn't use SDL surface memory"); + goto error_end; + } + if ( +#if defined(NONAMELESSUNION) + ddsd.u1.lPitch +#else + ddsd.lPitch +#endif + != (LONG)surface->pitch ) { + SDL_SetError("DDraw created surface with wrong pitch"); + goto error_end; + } + } else { +#if defined(NONAMELESSUNION) + surface->pitch = (Uint16)ddsd.u1.lPitch; +#else + surface->pitch = (Uint16)ddsd.lPitch; +#endif + } +#if defined(NONAMELESSUNION) + if ( (ddsd.ddpfPixelFormat.u1.dwRGBBitCount != + surface->format->BitsPerPixel) || + (ddsd.ddpfPixelFormat.u2.dwRBitMask != surface->format->Rmask) || + (ddsd.ddpfPixelFormat.u3.dwGBitMask != surface->format->Gmask) || + (ddsd.ddpfPixelFormat.u4.dwBBitMask != surface->format->Bmask) ){ +#else + if ( (ddsd.ddpfPixelFormat.dwRGBBitCount != + surface->format->BitsPerPixel) || + (ddsd.ddpfPixelFormat.dwRBitMask != surface->format->Rmask) || + (ddsd.ddpfPixelFormat.dwGBitMask != surface->format->Gmask) || + (ddsd.ddpfPixelFormat.dwBBitMask != surface->format->Bmask) ){ +#endif + SDL_SetError("DDraw didn't use SDL surface description"); + goto error_end; + } + if ( (ddsd.dwWidth != (DWORD)surface->w) || + (ddsd.dwHeight != (DWORD)surface->h) ) { + SDL_SetError("DDraw created surface with wrong size"); + goto error_end; + } + + /* Set the surface private data */ + surface->flags |= flag; + surface->hwdata->dd_surface = dd_surface3; + if ( (surface->flags & SDL_DOUBLEBUF) == SDL_DOUBLEBUF ) { + LPDIRECTDRAWSURFACE3 dd_writebuf; + + ddsd.ddsCaps.dwCaps = DDSCAPS_BACKBUFFER; + result = IDirectDrawSurface3_GetAttachedSurface(dd_surface3, + &ddsd.ddsCaps, &dd_writebuf); + if ( result != DD_OK ) { + SetDDerror("DirectDrawSurface3::GetAttachedSurface", + result); + } else { + dd_surface3 = dd_writebuf; + } + } + surface->hwdata->dd_writebuf = dd_surface3; + + /* We're ready to go! */ + return(0); + + /* Okay, so goto's are cheesy, but there are so many possible + errors in this function, and the cleanup is the same in + every single case. Is there a better way, other than deeply + nesting the code? + */ +error_end: + if ( (dd_surface3 != NULL) && (dd_surface3 != requested) ) { + IDirectDrawSurface_Release(dd_surface3); + } + SDL_free(surface->hwdata); + surface->hwdata = NULL; + return(-1); +} + +static int DX5_AllocHWSurface(_THIS, SDL_Surface *surface) +{ + /* DDraw limitation -- you need to set cooperative level first */ + if ( SDL_primary == NULL ) { + SDL_SetError("You must set a non-GL video mode first"); + return(-1); + } + return(DX5_AllocDDSurface(this, surface, NULL, SDL_HWSURFACE)); +} + +#ifdef DDRAW_DEBUG +void PrintSurface(char *title, LPDIRECTDRAWSURFACE3 surface, Uint32 flags) +{ + DDSURFACEDESC ddsd; + + /* Lock and load! */ + SDL_memset(&ddsd, 0, sizeof(ddsd)); + ddsd.dwSize = sizeof(ddsd); + if ( IDirectDrawSurface3_Lock(surface, NULL, &ddsd, + (DDLOCK_NOSYSLOCK|DDLOCK_WAIT), NULL) != DD_OK ) { + return; + } + IDirectDrawSurface3_Unlock(surface, NULL); + + fprintf(stderr, "%s:\n", title); + fprintf(stderr, "\tSize: %dx%d in %s at %ld bpp (pitch = %ld)\n", + ddsd.dwWidth, ddsd.dwHeight, + (flags & SDL_HWSURFACE) ? "hardware" : "software", +#if defined(NONAMELESSUNION) + ddsd.ddpfPixelFormat.u1.dwRGBBitCount, ddsd.u1.lPitch); +#else + ddsd.ddpfPixelFormat.dwRGBBitCount, ddsd.lPitch); +#endif + fprintf(stderr, "\tR = 0x%X, G = 0x%X, B = 0x%X\n", +#if defined(NONAMELESSUNION) + ddsd.ddpfPixelFormat.u2.dwRBitMask, + ddsd.ddpfPixelFormat.u3.dwGBitMask, + ddsd.ddpfPixelFormat.u4.dwBBitMask); +#else + ddsd.ddpfPixelFormat.dwRBitMask, + ddsd.ddpfPixelFormat.dwGBitMask, + ddsd.ddpfPixelFormat.dwBBitMask); +#endif +} +#endif /* DDRAW_DEBUG */ + +static int DX5_HWAccelBlit(SDL_Surface *src, SDL_Rect *srcrect, + SDL_Surface *dst, SDL_Rect *dstrect) +{ + LPDIRECTDRAWSURFACE3 src_surface; + LPDIRECTDRAWSURFACE3 dst_surface; + DWORD flags; + RECT rect; + HRESULT result; + + /* Set it up.. the desination must have a DDRAW surface */ + src_surface = src->hwdata->dd_writebuf; + dst_surface = dst->hwdata->dd_writebuf; + rect.top = (LONG)srcrect->y; + rect.bottom = (LONG)srcrect->y+srcrect->h; + rect.left = (LONG)srcrect->x; + rect.right = (LONG)srcrect->x+srcrect->w; + if ( (src->flags & SDL_SRCCOLORKEY) == SDL_SRCCOLORKEY ) + flags = DDBLTFAST_SRCCOLORKEY; + else + flags = DDBLTFAST_NOCOLORKEY; + /* FIXME: We can remove this flag for _really_ fast blit queuing, + but it will affect the return values of locks and flips. + */ + flags |= DDBLTFAST_WAIT; + + /* Do the blit! */ + result = IDirectDrawSurface3_BltFast(dst_surface, + dstrect->x, dstrect->y, src_surface, &rect, flags); + if ( result != DD_OK ) { + if ( result == DDERR_SURFACELOST ) { + result = IDirectDrawSurface3_Restore(src_surface); + result = IDirectDrawSurface3_Restore(dst_surface); + /* The surfaces need to be reloaded with artwork */ + SDL_SetError("Blit surfaces were lost, reload them"); + return(-2); + } + SetDDerror("IDirectDrawSurface3::BltFast", result); +#ifdef DDRAW_DEBUG + fprintf(stderr, "Original dest rect: %dx%d at %d,%d\n", dstrect->w, dstrect->h, dstrect->x, dstrect->y); + fprintf(stderr, "HW accelerated %sblit to from 0x%p to 0x%p at (%d,%d)\n", + (src->flags & SDL_SRCCOLORKEY) ? "colorkey " : "", src, dst, + dstrect->x, dstrect->y); + PrintSurface("SRC", src_surface, src->flags); + PrintSurface("DST", dst_surface, dst->flags); + fprintf(stderr, "Source rectangle: (%d,%d) - (%d,%d)\n", + rect.left, rect.top, rect.right, rect.bottom); +#endif + /* Unexpected error, fall back to software blit */ + return(src->map->sw_blit(src, srcrect, dst, dstrect)); + } + return(0); +} + +static int DX5_CheckHWBlit(_THIS, SDL_Surface *src, SDL_Surface *dst) +{ + int accelerated; + + /* We need to have a DDraw surface for HW blits */ + if ( (src->flags & SDL_HWSURFACE) == SDL_SWSURFACE ) { + /* Allocate a DDraw surface for the blit */ + if ( src->hwdata == NULL ) { + DX5_AllocDDSurface(this, src, NULL, SDL_SWSURFACE); + } + } + if ( src->hwdata == NULL ) { + return(0); + } + + /* Set initial acceleration on */ + src->flags |= SDL_HWACCEL; + + /* Set the surface attributes */ + if ( (src->flags & SDL_SRCCOLORKEY) == SDL_SRCCOLORKEY ) { + if ( DX5_SetHWColorKey(this, src, src->format->colorkey) < 0 ) { + src->flags &= ~SDL_HWACCEL; + } + } + if ( (src->flags & SDL_SRCALPHA) == SDL_SRCALPHA ) { + if ( DX5_SetHWAlpha(this, src, src->format->alpha) < 0 ) { + src->flags &= ~SDL_HWACCEL; + } + } + + /* Check to see if final surface blit is accelerated */ + accelerated = !!(src->flags & SDL_HWACCEL); + if ( accelerated ) { +#ifdef DDRAW_DEBUG + fprintf(stderr, "Setting accelerated blit on 0x%p\n", src); +#endif + src->map->hw_blit = DX5_HWAccelBlit; + } + return(accelerated); +} + +static int DX5_FillHWRect(_THIS, SDL_Surface *dst, SDL_Rect *dstrect, Uint32 color) +{ + LPDIRECTDRAWSURFACE3 dst_surface; + RECT area; + DDBLTFX bltfx; + HRESULT result; + +#ifdef DDRAW_DEBUG + fprintf(stderr, "HW accelerated fill at (%d,%d)\n", dstrect->x, dstrect->y); +#endif + dst_surface = dst->hwdata->dd_writebuf; + area.top = (LONG)dstrect->y; + area.bottom = (LONG)dstrect->y+dstrect->h; + area.left = (LONG)dstrect->x; + area.right = (LONG)dstrect->x+dstrect->w; + bltfx.dwSize = sizeof(bltfx); +#if defined(NONAMELESSUNION) + bltfx.u5.dwFillColor = color; +#else + bltfx.dwFillColor = color; +#endif + result = IDirectDrawSurface3_Blt(dst_surface, + &area, NULL, NULL, DDBLT_COLORFILL|DDBLT_WAIT, &bltfx); + if ( result == DDERR_SURFACELOST ) { + IDirectDrawSurface3_Restore(dst_surface); + result = IDirectDrawSurface3_Blt(dst_surface, + &area, NULL, NULL, DDBLT_COLORFILL|DDBLT_WAIT, &bltfx); + } + if ( result != DD_OK ) { + SetDDerror("IDirectDrawSurface3::Blt", result); + return(-1); + } + return(0); +} + +static int DX5_SetHWColorKey(_THIS, SDL_Surface *surface, Uint32 key) +{ + DDCOLORKEY colorkey; + HRESULT result; + + /* Set the surface colorkey */ + colorkey.dwColorSpaceLowValue = key; + colorkey.dwColorSpaceHighValue = key; + result = IDirectDrawSurface3_SetColorKey( + surface->hwdata->dd_surface, DDCKEY_SRCBLT, &colorkey); + if ( result != DD_OK ) { + SetDDerror("IDirectDrawSurface3::SetColorKey", result); + return(-1); + } + return(0); +} +static int DX5_SetHWAlpha(_THIS, SDL_Surface *surface, Uint8 alpha) +{ + return(-1); +} + +static int DX5_LockHWSurface(_THIS, SDL_Surface *surface) +{ + HRESULT result; + LPDIRECTDRAWSURFACE3 dd_surface; + DDSURFACEDESC ddsd; + + /* Lock and load! */ + dd_surface = surface->hwdata->dd_writebuf; + SDL_memset(&ddsd, 0, sizeof(ddsd)); + ddsd.dwSize = sizeof(ddsd); + result = IDirectDrawSurface3_Lock(dd_surface, NULL, &ddsd, + (DDLOCK_NOSYSLOCK|DDLOCK_WAIT), NULL); + if ( result == DDERR_SURFACELOST ) { + result = IDirectDrawSurface3_Restore( + surface->hwdata->dd_surface); + result = IDirectDrawSurface3_Lock(dd_surface, NULL, &ddsd, + (DDLOCK_NOSYSLOCK|DDLOCK_WAIT), NULL); + } + if ( result != DD_OK ) { + SetDDerror("DirectDrawSurface3::Lock", result); + return(-1); + } + /* Pitch might have changed -- recalculate pitch and offset */ +#if defined(NONAMELESSUNION) + if ( surface->pitch != ddsd.u1.lPitch ) { + surface->pitch = ddsd.u1.lPitch; +#else + if ( surface->pitch != ddsd.lPitch ) { + surface->pitch = (Uint16)ddsd.lPitch; +#endif + surface->offset = + ((ddsd.dwHeight-surface->h)/2)*surface->pitch + + ((ddsd.dwWidth-surface->w)/2)* + surface->format->BytesPerPixel; + } + surface->pixels = ddsd.lpSurface; + return(0); +} + +static void DX5_UnlockHWSurface(_THIS, SDL_Surface *surface) +{ + IDirectDrawSurface3_Unlock(surface->hwdata->dd_writebuf, NULL); + surface->pixels = NULL; +} + +static int DX5_FlipHWSurface(_THIS, SDL_Surface *surface) +{ + HRESULT result; + LPDIRECTDRAWSURFACE3 dd_surface; + + dd_surface = surface->hwdata->dd_surface; + + /* to prevent big slowdown on fast computers, wait here instead of driver ring 0 code */ + /* Dmitry Yakimov (ftech@tula.net) */ + while(IDirectDrawSurface3_GetFlipStatus(dd_surface, DDGBS_ISBLTDONE) == DDERR_WASSTILLDRAWING); + + result = IDirectDrawSurface3_Flip(dd_surface, NULL, DDFLIP_WAIT); + if ( result == DDERR_SURFACELOST ) { + result = IDirectDrawSurface3_Restore( + surface->hwdata->dd_surface); + while(IDirectDrawSurface3_GetFlipStatus(dd_surface, DDGBS_ISBLTDONE) == DDERR_WASSTILLDRAWING); + result = IDirectDrawSurface3_Flip(dd_surface, NULL, DDFLIP_WAIT); + } + if ( result != DD_OK ) { + SetDDerror("DirectDrawSurface3::Flip", result); + return(-1); + } + return(0); +} + +static void DX5_FreeHWSurface(_THIS, SDL_Surface *surface) +{ + if ( surface->hwdata ) { + if ( surface->hwdata->dd_surface != SDL_primary ) { + IDirectDrawSurface3_Release(surface->hwdata->dd_surface); + } + SDL_free(surface->hwdata); + surface->hwdata = NULL; + } +} + +void DX5_WindowUpdate(_THIS, int numrects, SDL_Rect *rects) +{ + HRESULT result; + int i; + RECT src, dst; + + for ( i=0; i<numrects; ++i ) { + src.top = (LONG)rects[i].y; + src.bottom = (LONG)rects[i].y+rects[i].h; + src.left = (LONG)rects[i].x; + src.right = (LONG)rects[i].x+rects[i].w; + dst.top = SDL_bounds.top+src.top; + dst.left = SDL_bounds.left+src.left; + dst.bottom = SDL_bounds.top+src.bottom; + dst.right = SDL_bounds.left+src.right; + result = IDirectDrawSurface3_Blt(SDL_primary, &dst, + this->screen->hwdata->dd_surface, &src, + DDBLT_WAIT, NULL); + /* Doh! Check for lost surface and restore it */ + if ( result == DDERR_SURFACELOST ) { + IDirectDrawSurface3_Restore(SDL_primary); + IDirectDrawSurface3_Blt(SDL_primary, &dst, + this->screen->hwdata->dd_surface, &src, + DDBLT_WAIT, NULL); + } + } +} + +void DX5_DirectUpdate(_THIS, int numrects, SDL_Rect *rects) +{ +} + +/* Compress a full palette into the limited number of colors given to us + by windows. + + The "best" way to do this is to sort the colors by diversity and place + the most diverse colors into the limited palette. Unfortunately this + results in widely varying colors being displayed in the interval during + which the windows palette has been set, and the mapping of the shadow + surface to the new palette. This is especially noticeable during fades. + + To deal with this problem, we can copy a predetermined portion of the + full palette, and use that as the limited palette. This allows colors + to fade smoothly as the remapping is very similar on each palette change. + Unfortunately, this breaks applications which partition the palette into + distinct and widely varying areas, expecting all colors to be available. + + I'm making them both available, chosen at compile time. + If you want the chunk-o-palette algorithm, define SIMPLE_COMPRESSION, + otherwise the sort-by-diversity algorithm will be used. +*/ +#define SIMPLE_COMPRESSION +#define CS_CS_DIST(A, B) ({ \ + int r = (A.r - B.r); \ + int g = (A.g - B.g); \ + int b = (A.b - B.b); \ + (r*r + g*g + b*b); \ +}) +static void DX5_CompressPalette(_THIS, SDL_Color *colors, int ncolors, int maxcolors) +{ +#ifdef SIMPLE_COMPRESSION + int i, j; +#else + static SDL_Color zero = { 0, 0, 0, 0 }; + int i, j; + int max, dist; + int prev, next; + int *pool; + int *seen, *order; +#endif + + /* Does this happen? */ + if ( maxcolors > ncolors ) { + maxcolors = ncolors; + } + +#ifdef SIMPLE_COMPRESSION + /* Just copy the first "maxcolors" colors */ + for ( j=10, i=0; i<maxcolors; ++i, ++j ) { + SDL_colors[j].peRed = colors[i].r; + SDL_colors[j].peGreen = colors[i].g; + SDL_colors[j].peBlue = colors[i].b; + } +#else + /* Allocate memory for the arrays we use */ + pool = SDL_stack_alloc(int, 2*ncolors); + if ( pool == NULL ) { + /* No worries, just return */; + return; + } + seen = pool; + SDL_memset(seen, 0, ncolors*sizeof(int)); + order = pool+ncolors; + + /* Start with the brightest color */ + max = 0; + for ( i=0; i<ncolors; ++i ) { + dist = CS_CS_DIST(zero, colors[i]); + if ( dist >= max ) { + max = dist; + next = i; + } + } + j = 0; + order[j++] = next; + seen[next] = 1; + prev = next; + + /* Keep going through all the colors */ + while ( j < maxcolors ) { + max = 0; + for ( i=0; i<ncolors; ++i ) { + if ( seen[i] ) { + continue; + } + dist = CS_CS_DIST(colors[i], colors[prev]); + if ( dist >= max ) { + max = dist; + next = i; + } + } + order[j++] = next; + seen[next] = 1; + prev = next; + } + + /* Compress the colors to the palette */ + for ( j=10, i=0; i<maxcolors; ++i, ++j ) { + SDL_colors[j].peRed = colors[order[i]].r; + SDL_colors[j].peGreen = colors[order[i]].g; + SDL_colors[j].peBlue = colors[order[i]].b; + } + SDL_stack_free(pool); +#endif /* SIMPLE_COMPRESSION */ +} + +/* Set the system colormap in both fullscreen and windowed modes */ +int DX5_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors) +{ + int i; + int alloct_all; + + /* Copy palette colors into display palette */ + alloct_all = 0; + if ( SDL_palette != NULL ) { + if ( (this->screen->flags&SDL_FULLSCREEN) == SDL_FULLSCREEN ) { + /* We can set all entries explicitly */ + for ( i=0; i< ncolors; ++i ) { + int j = firstcolor + i; + SDL_colors[j].peRed = colors[i].r; + SDL_colors[j].peGreen = colors[i].g; + SDL_colors[j].peBlue = colors[i].b; + } + /* This sends an WM_PALETTECHANGED message to us */ + colorchange_expected = 1; + IDirectDrawPalette_SetEntries(SDL_palette, 0, + firstcolor, ncolors, &SDL_colors[firstcolor]); + alloct_all = 1; + } else { + /* Grab the 236 most diverse colors in the palette */ + DX5_CompressPalette(this, colors, ncolors, 236); + /* This sends an WM_PALETTECHANGED message to us */ + colorchange_expected = 1; + IDirectDrawPalette_SetEntries(SDL_palette, 0, + 0, 256, SDL_colors); + } + } + return(alloct_all); +} + +/* Gamma code is only available on DirectX 7 and newer */ +static int DX5_SetGammaRamp(_THIS, Uint16 *ramp) +{ +#ifdef IDirectDrawGammaControl_SetGammaRamp + LPDIRECTDRAWGAMMACONTROL gamma; + DDGAMMARAMP gamma_ramp; + HRESULT result; +#endif + + /* In windowed or OpenGL mode, use windib gamma code */ + if ( ! DDRAW_FULLSCREEN() ) { + return DIB_SetGammaRamp(this, ramp); + } + +#ifndef IDirectDrawGammaControl_SetGammaRamp + SDL_SetError("SDL compiled without DirectX gamma ramp support"); + return -1; +#else + /* Check for a video mode! */ + if ( ! SDL_primary ) { + SDL_SetError("A video mode must be set for gamma correction"); + return(-1); + } + + /* Get the gamma control object */ + result = IDirectDrawSurface3_QueryInterface(SDL_primary, + &IID_IDirectDrawGammaControl, (LPVOID *)&gamma); + if ( result != DD_OK ) { + SetDDerror("DirectDrawSurface3::QueryInterface(GAMMA)", result); + return(-1); + } + + /* Set up the gamma ramp */ + SDL_memcpy(gamma_ramp.red, &ramp[0*256], 256*sizeof(*ramp)); + SDL_memcpy(gamma_ramp.green, &ramp[1*256], 256*sizeof(*ramp)); + SDL_memcpy(gamma_ramp.blue, &ramp[2*256], 256*sizeof(*ramp)); + result = IDirectDrawGammaControl_SetGammaRamp(gamma, 0, &gamma_ramp); + if ( result != DD_OK ) { + SetDDerror("DirectDrawGammaControl::SetGammaRamp()", result); + } + + /* Release the interface and return */ + IDirectDrawGammaControl_Release(gamma); + return (result == DD_OK) ? 0 : -1; +#endif /* !IDirectDrawGammaControl_SetGammaRamp */ +} + +static int DX5_GetGammaRamp(_THIS, Uint16 *ramp) +{ +#ifdef IDirectDrawGammaControl_SetGammaRamp + LPDIRECTDRAWGAMMACONTROL gamma; + DDGAMMARAMP gamma_ramp; + HRESULT result; +#endif + + /* In windowed or OpenGL mode, use windib gamma code */ + if ( ! DDRAW_FULLSCREEN() ) { + return DIB_GetGammaRamp(this, ramp); + } + +#ifndef IDirectDrawGammaControl_SetGammaRamp + SDL_SetError("SDL compiled without DirectX gamma ramp support"); + return -1; +#else + /* Check for a video mode! */ + if ( ! SDL_primary ) { + SDL_SetError("A video mode must be set for gamma correction"); + return(-1); + } + + /* Get the gamma control object */ + result = IDirectDrawSurface3_QueryInterface(SDL_primary, + &IID_IDirectDrawGammaControl, (LPVOID *)&gamma); + if ( result != DD_OK ) { + SetDDerror("DirectDrawSurface3::QueryInterface(GAMMA)", result); + return(-1); + } + + /* Set up the gamma ramp */ + result = IDirectDrawGammaControl_GetGammaRamp(gamma, 0, &gamma_ramp); + if ( result == DD_OK ) { + SDL_memcpy(&ramp[0*256], gamma_ramp.red, 256*sizeof(*ramp)); + SDL_memcpy(&ramp[1*256], gamma_ramp.green, 256*sizeof(*ramp)); + SDL_memcpy(&ramp[2*256], gamma_ramp.blue, 256*sizeof(*ramp)); + } else { + SetDDerror("DirectDrawGammaControl::GetGammaRamp()", result); + } + + /* Release the interface and return */ + IDirectDrawGammaControl_Release(gamma); + return (result == DD_OK) ? 0 : -1; +#endif /* !IDirectDrawGammaControl_SetGammaRamp */ +} + +void DX5_VideoQuit(_THIS) +{ + int i, j; + + /* If we're fullscreen GL, we need to reset the display */ + if ( this->screen != NULL ) { +#ifndef NO_CHANGEDISPLAYSETTINGS + if ( (this->screen->flags & (SDL_OPENGL|SDL_FULLSCREEN)) == + (SDL_OPENGL|SDL_FULLSCREEN) ) { + ChangeDisplaySettings(NULL, 0); + ShowWindow(SDL_Window, SW_HIDE); + } +#endif + if ( this->screen->flags & SDL_OPENGL ) { + WIN_GL_ShutDown(this); + } + } + + /* Free any palettes we used */ + if ( SDL_palette != NULL ) { + IDirectDrawPalette_Release(SDL_palette); + SDL_palette = NULL; + } + + /* Allow the primary surface to be freed */ + if ( SDL_primary != NULL ) { + SDL_primary = NULL; + } + + /* Free video mode lists */ + for ( i=0; i<NUM_MODELISTS; ++i ) { + if ( SDL_modelist[i] != NULL ) { + for ( j=0; SDL_modelist[i][j]; ++j ) + SDL_free(SDL_modelist[i][j]); + SDL_free(SDL_modelist[i]); + SDL_modelist[i] = NULL; + } + } + + /* Free the window */ + DIB_QuitGamma(this); + if ( SDL_Window ) { + DX5_DestroyWindow(this); + } + + /* Free our window icon */ + if ( screen_icn ) { + DestroyIcon(screen_icn); + screen_icn = NULL; + } +} + +/* Exported for the windows message loop only */ +void DX5_Activate(_THIS, BOOL active, BOOL minimized) +{ +} +void DX5_RealizePalette(_THIS) +{ + if ( SDL_palette ) { + IDirectDrawSurface3_SetPalette(SDL_primary, SDL_palette); + } +} +static void DX5_Recolor8Bit(_THIS, SDL_Surface *surface, Uint8 *mapping) +{ + int row, col; + Uint8 *pixels; + + if ( surface->w && surface->h ) { + if ( (surface->flags & SDL_HWSURFACE) == SDL_HWSURFACE ) { + if ( this->LockHWSurface(this, surface) < 0 ) { + return; + } + } + for ( row=0; row<surface->h; ++row ) { + pixels = (Uint8 *)surface->pixels+row*surface->pitch; + for ( col=0; col<surface->w; ++col, ++pixels ) { + *pixels = mapping[*pixels]; + } + } + if ( (surface->flags & SDL_HWSURFACE) == SDL_HWSURFACE ) { + this->UnlockHWSurface(this, surface); + } + SDL_UpdateRect(surface, 0, 0, 0, 0); + } +} +void DX5_PaletteChanged(_THIS, HWND window) +{ + SDL_Palette *palette; + SDL_Color *saved = NULL; + HDC hdc; + int i; + PALETTEENTRY *entries; + + /* This is true when the window is closing */ + if ( (SDL_primary == NULL) || (SDL_VideoSurface == NULL) ) + return; + + /* We need to get the colors as they were set */ + palette = this->physpal; + if(!palette) + palette = SDL_VideoSurface->format->palette; + if ( palette == NULL ) { /* Sometimes we don't have a palette */ + return; + } + entries = SDL_stack_alloc(PALETTEENTRY, palette->ncolors); + hdc = GetDC(window); + GetSystemPaletteEntries(hdc, 0, palette->ncolors, entries); + ReleaseDC(window, hdc); + if ( ! colorchange_expected ) { + saved = SDL_stack_alloc(SDL_Color, palette->ncolors); + SDL_memcpy(saved, palette->colors, + palette->ncolors*sizeof(SDL_Color)); + } + for ( i=0; i<palette->ncolors; ++i ) { + palette->colors[i].r = entries[i].peRed; + palette->colors[i].g = entries[i].peGreen; + palette->colors[i].b = entries[i].peBlue; + } + SDL_stack_free(entries); + if ( ! colorchange_expected ) { + Uint8 mapping[256]; + + SDL_memset(mapping, 0, sizeof(mapping)); + for ( i=0; i<palette->ncolors; ++i ) { + mapping[i] = SDL_FindColor(palette, + saved[i].r, saved[i].g, saved[i].b); + } + DX5_Recolor8Bit(this, SDL_VideoSurface, mapping); + SDL_stack_free(saved); + } + colorchange_expected = 0; + + /* Notify all mapped surfaces of the change */ + SDL_FormatChanged(SDL_VideoSurface); +} + +/* Exported for the windows message loop only */ +void DX5_WinPAINT(_THIS, HDC hdc) +{ + SDL_UpdateRect(SDL_PublicSurface, 0, 0, 0, 0); +} diff --git a/3rdparty/SDL/src/video/windx5/SDL_dx5video.h b/3rdparty/SDL/src/video/windx5/SDL_dx5video.h new file mode 100644 index 0000000..3d754a0 --- /dev/null +++ b/3rdparty/SDL/src/video/windx5/SDL_dx5video.h @@ -0,0 +1,61 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#ifndef _SDL_dx5video_h +#define _SDL_dx5video_h + +#include "directx.h" + +/* Private display data */ +struct SDL_PrivateVideoData { + LPDIRECTDRAW2 ddraw2; + LPDIRECTDRAWSURFACE3 SDL_primary; + LPDIRECTDRAWCLIPPER SDL_clipper; + LPDIRECTDRAWPALETTE SDL_palette; + PALETTEENTRY SDL_colors[256]; + int colorchange_expected; + +#define NUM_MODELISTS 4 /* 8, 16, 24, and 32 bits-per-pixel */ + int SDL_nummodes[NUM_MODELISTS]; + SDL_Rect **SDL_modelist[NUM_MODELISTS]; + int SDL_modeindex[NUM_MODELISTS]; +}; +/* Old variable names */ +#define ddraw2 (this->hidden->ddraw2) +#define SDL_primary (this->hidden->SDL_primary) +#define SDL_clipper (this->hidden->SDL_clipper) +#define SDL_palette (this->hidden->SDL_palette) +#define SDL_colors (this->hidden->SDL_colors) +#define colorchange_expected (this->hidden->colorchange_expected) +#define SDL_nummodes (this->hidden->SDL_nummodes) +#define SDL_modelist (this->hidden->SDL_modelist) +#define SDL_modeindex (this->hidden->SDL_modeindex) + +/* DirectX function pointers for video and events */ +extern HRESULT (WINAPI *DDrawCreate)( GUID FAR *lpGUID, LPDIRECTDRAW FAR *lplpDD, IUnknown FAR *pUnkOuter ); +extern HRESULT (WINAPI *DInputCreate)(HINSTANCE hinst, DWORD dwVersion, LPDIRECTINPUT *ppDI, LPUNKNOWN punkOuter); + +/* DirectDraw error reporting function */ +extern void SetDDerror(const char *function, int code); + +#endif /* _SDL_dx5video_h */ diff --git a/3rdparty/SDL/src/video/windx5/SDL_dx5yuv.c b/3rdparty/SDL/src/video/windx5/SDL_dx5yuv.c new file mode 100644 index 0000000..cb89fdc --- /dev/null +++ b/3rdparty/SDL/src/video/windx5/SDL_dx5yuv.c @@ -0,0 +1,296 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* This is the DirectDraw implementation of YUV video overlays */ +#include "directx.h" +#include "SDL_video.h" +#include "SDL_dx5yuv_c.h" +#include "../SDL_yuvfuncs.h" + +//#define USE_DIRECTX_OVERLAY + +/* The functions used to manipulate software video overlays */ +static struct private_yuvhwfuncs dx5_yuvfuncs = { + DX5_LockYUVOverlay, + DX5_UnlockYUVOverlay, + DX5_DisplayYUVOverlay, + DX5_FreeYUVOverlay +}; + +struct private_yuvhwdata { + LPDIRECTDRAWSURFACE3 surface; + + /* These are just so we don't have to allocate them separately */ + Uint16 pitches[3]; + Uint8 *planes[3]; +}; + + +static LPDIRECTDRAWSURFACE3 CreateYUVSurface(_THIS, + int width, int height, Uint32 format) +{ + HRESULT result; + LPDIRECTDRAWSURFACE dd_surface1; + LPDIRECTDRAWSURFACE3 dd_surface3; + DDSURFACEDESC ddsd; + + /* Set up the surface description */ + SDL_memset(&ddsd, 0, sizeof(ddsd)); + ddsd.dwSize = sizeof(ddsd); + ddsd.dwFlags = (DDSD_WIDTH|DDSD_HEIGHT|DDSD_CAPS|DDSD_PIXELFORMAT); + ddsd.dwWidth = width; + ddsd.dwHeight= height; +#ifdef USE_DIRECTX_OVERLAY + ddsd.ddsCaps.dwCaps = (DDSCAPS_OVERLAY|DDSCAPS_VIDEOMEMORY); +#else + ddsd.ddsCaps.dwCaps = (DDSCAPS_OFFSCREENPLAIN|DDSCAPS_VIDEOMEMORY); +#endif + ddsd.ddpfPixelFormat.dwSize = sizeof(ddsd.ddpfPixelFormat); + ddsd.ddpfPixelFormat.dwFlags = DDPF_FOURCC; + ddsd.ddpfPixelFormat.dwFourCC = format; + + /* Create the DirectDraw video surface */ + result = IDirectDraw2_CreateSurface(ddraw2, &ddsd, &dd_surface1, NULL); + if ( result != DD_OK ) { + SetDDerror("DirectDraw2::CreateSurface", result); + return(NULL); + } + result = IDirectDrawSurface_QueryInterface(dd_surface1, + &IID_IDirectDrawSurface3, (LPVOID *)&dd_surface3); + IDirectDrawSurface_Release(dd_surface1); + if ( result != DD_OK ) { + SetDDerror("DirectDrawSurface::QueryInterface", result); + return(NULL); + } + + /* Make sure the surface format was set properly */ + SDL_memset(&ddsd, 0, sizeof(ddsd)); + ddsd.dwSize = sizeof(ddsd); + result = IDirectDrawSurface3_Lock(dd_surface3, NULL, + &ddsd, DDLOCK_NOSYSLOCK, NULL); + if ( result != DD_OK ) { + SetDDerror("DirectDrawSurface3::Lock", result); + IDirectDrawSurface_Release(dd_surface3); + return(NULL); + } + IDirectDrawSurface3_Unlock(dd_surface3, NULL); + + if ( !(ddsd.ddpfPixelFormat.dwFlags & DDPF_FOURCC) || + (ddsd.ddpfPixelFormat.dwFourCC != format) ) { + SDL_SetError("DDraw didn't use requested FourCC format"); + IDirectDrawSurface_Release(dd_surface3); + return(NULL); + } + + /* We're ready to go! */ + return(dd_surface3); +} + +#ifdef DEBUG_YUV +static char *PrintFOURCC(Uint32 code) +{ + static char buf[5]; + + buf[3] = code >> 24; + buf[2] = (code >> 16) & 0xFF; + buf[1] = (code >> 8) & 0xFF; + buf[0] = (code & 0xFF); + return(buf); +} +#endif + +SDL_Overlay *DX5_CreateYUVOverlay(_THIS, int width, int height, Uint32 format, SDL_Surface *display) +{ + SDL_Overlay *overlay; + struct private_yuvhwdata *hwdata; + +#ifdef DEBUG_YUV + DWORD numcodes; + DWORD *codes; + + printf("FOURCC format requested: 0x%x\n", PrintFOURCC(format)); + IDirectDraw2_GetFourCCCodes(ddraw2, &numcodes, NULL); + if ( numcodes ) { + DWORD i; + codes = SDL_malloc(numcodes*sizeof(*codes)); + if ( codes ) { + IDirectDraw2_GetFourCCCodes(ddraw2, &numcodes, codes); + for ( i=0; i<numcodes; ++i ) { + fprintf(stderr, "Code %d: 0x%x\n", i, PrintFOURCC(codes[i])); + } + SDL_free(codes); + } + } else { + fprintf(stderr, "No FOURCC codes supported\n"); + } +#endif + + /* Create the overlay structure */ + overlay = (SDL_Overlay *)SDL_malloc(sizeof *overlay); + if ( overlay == NULL ) { + SDL_OutOfMemory(); + return(NULL); + } + SDL_memset(overlay, 0, (sizeof *overlay)); + + /* Fill in the basic members */ + overlay->format = format; + overlay->w = width; + overlay->h = height; + + /* Set up the YUV surface function structure */ + overlay->hwfuncs = &dx5_yuvfuncs; + + /* Create the pixel data and lookup tables */ + hwdata = (struct private_yuvhwdata *)SDL_malloc(sizeof *hwdata); + overlay->hwdata = hwdata; + if ( hwdata == NULL ) { + SDL_OutOfMemory(); + SDL_FreeYUVOverlay(overlay); + return(NULL); + } + hwdata->surface = CreateYUVSurface(this, width, height, format); + if ( hwdata->surface == NULL ) { + SDL_FreeYUVOverlay(overlay); + return(NULL); + } + overlay->hw_overlay = 1; + + /* Set up the plane pointers */ + overlay->pitches = hwdata->pitches; + overlay->pixels = hwdata->planes; + switch (format) { + case SDL_YV12_OVERLAY: + case SDL_IYUV_OVERLAY: + overlay->planes = 3; + break; + default: + overlay->planes = 1; + break; + } + + /* We're all done.. */ + return(overlay); +} + +int DX5_LockYUVOverlay(_THIS, SDL_Overlay *overlay) +{ + HRESULT result; + LPDIRECTDRAWSURFACE3 surface; + DDSURFACEDESC ddsd; + + surface = overlay->hwdata->surface; + SDL_memset(&ddsd, 0, sizeof(ddsd)); + ddsd.dwSize = sizeof(ddsd); + result = IDirectDrawSurface3_Lock(surface, NULL, + &ddsd, DDLOCK_NOSYSLOCK, NULL); + if ( result == DDERR_SURFACELOST ) { + result = IDirectDrawSurface3_Restore(surface); + result = IDirectDrawSurface3_Lock(surface, NULL, &ddsd, + (DDLOCK_NOSYSLOCK|DDLOCK_WAIT), NULL); + } + if ( result != DD_OK ) { + SetDDerror("DirectDrawSurface3::Lock", result); + return(-1); + } + + /* Find the pitch and offset values for the overlay */ +#if defined(NONAMELESSUNION) + overlay->pitches[0] = (Uint16)ddsd.u1.lPitch; +#else + overlay->pitches[0] = (Uint16)ddsd.lPitch; +#endif + overlay->pixels[0] = (Uint8 *)ddsd.lpSurface; + switch (overlay->format) { + case SDL_YV12_OVERLAY: + case SDL_IYUV_OVERLAY: + /* Add the two extra planes */ + overlay->pitches[1] = overlay->pitches[0] / 2; + overlay->pitches[2] = overlay->pitches[0] / 2; + overlay->pixels[1] = overlay->pixels[0] + + overlay->pitches[0] * overlay->h; + overlay->pixels[2] = overlay->pixels[1] + + overlay->pitches[1] * overlay->h / 2; + break; + default: + /* Only one plane, no worries */ + break; + } + return(0); +} + +void DX5_UnlockYUVOverlay(_THIS, SDL_Overlay *overlay) +{ + LPDIRECTDRAWSURFACE3 surface; + + surface = overlay->hwdata->surface; + IDirectDrawSurface3_Unlock(surface, NULL); +} + +int DX5_DisplayYUVOverlay(_THIS, SDL_Overlay *overlay, SDL_Rect *src, SDL_Rect *dst) +{ + HRESULT result; + LPDIRECTDRAWSURFACE3 surface; + RECT srcrect, dstrect; + + surface = overlay->hwdata->surface; + srcrect.top = src->y; + srcrect.bottom = srcrect.top+src->h; + srcrect.left = src->x; + srcrect.right = srcrect.left+src->w; + dstrect.top = SDL_bounds.top+dst->y; + dstrect.left = SDL_bounds.left+dst->x; + dstrect.bottom = dstrect.top+dst->h; + dstrect.right = dstrect.left+dst->w; +#ifdef USE_DIRECTX_OVERLAY + result = IDirectDrawSurface3_UpdateOverlay(surface, &srcrect, + SDL_primary, &dstrect, DDOVER_SHOW, NULL); + if ( result != DD_OK ) { + SetDDerror("DirectDrawSurface3::UpdateOverlay", result); + return(-1); + } +#else + result = IDirectDrawSurface3_Blt(SDL_primary, &dstrect, surface, &srcrect, + DDBLT_WAIT, NULL); + if ( result != DD_OK ) { + SetDDerror("DirectDrawSurface3::Blt", result); + return(-1); + } +#endif + return(0); +} + +void DX5_FreeYUVOverlay(_THIS, SDL_Overlay *overlay) +{ + struct private_yuvhwdata *hwdata; + + hwdata = overlay->hwdata; + if ( hwdata ) { + if ( hwdata->surface ) { + IDirectDrawSurface_Release(hwdata->surface); + } + SDL_free(hwdata); + overlay->hwdata = NULL; + } +} + diff --git a/3rdparty/SDL/src/video/windx5/SDL_dx5yuv_c.h b/3rdparty/SDL/src/video/windx5/SDL_dx5yuv_c.h new file mode 100644 index 0000000..dfceaf9 --- /dev/null +++ b/3rdparty/SDL/src/video/windx5/SDL_dx5yuv_c.h @@ -0,0 +1,38 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* This is the DirectDraw implementation of YUV video overlays */ + +#include "SDL_video.h" +#include "../wincommon/SDL_lowvideo.h" +#include "SDL_dx5video.h" + +extern SDL_Overlay *DX5_CreateYUVOverlay(_THIS, int width, int height, Uint32 format, SDL_Surface *display); + +extern int DX5_LockYUVOverlay(_THIS, SDL_Overlay *overlay); + +extern void DX5_UnlockYUVOverlay(_THIS, SDL_Overlay *overlay); + +extern int DX5_DisplayYUVOverlay(_THIS, SDL_Overlay *overlay, SDL_Rect *src, SDL_Rect *dst); + +extern void DX5_FreeYUVOverlay(_THIS, SDL_Overlay *overlay); diff --git a/3rdparty/SDL/src/video/windx5/directx.h b/3rdparty/SDL/src/video/windx5/directx.h new file mode 100644 index 0000000..c7f5365 --- /dev/null +++ b/3rdparty/SDL/src/video/windx5/directx.h @@ -0,0 +1,97 @@ + +#ifndef _directx_h +#define _directx_h + +/* Include all of the DirectX 5.0 headers and adds any necessary tweaks */ + +#define WIN32_LEAN_AND_MEAN +#include <windows.h> +#include <mmsystem.h> +#ifndef WIN32 +#define WIN32 +#endif +#undef WINNT + +/* Far pointers don't exist in 32-bit code */ +#ifndef FAR +#define FAR +#endif + +/* Error codes not yet included in Win32 API header files */ +#ifndef MAKE_HRESULT +#define MAKE_HRESULT(sev,fac,code) \ + ((HRESULT)(((unsigned long)(sev)<<31) | ((unsigned long)(fac)<<16) | ((unsigned long)(code)))) +#endif + +#ifndef S_OK +#define S_OK (HRESULT)0x00000000L +#endif + +#ifndef SUCCEEDED +#define SUCCEEDED(x) ((HRESULT)(x) >= 0) +#endif +#ifndef FAILED +#define FAILED(x) ((HRESULT)(x)<0) +#endif + +#ifndef E_FAIL +#define E_FAIL (HRESULT)0x80000008L +#endif +#ifndef E_NOINTERFACE +#define E_NOINTERFACE (HRESULT)0x80004002L +#endif +#ifndef E_OUTOFMEMORY +#define E_OUTOFMEMORY (HRESULT)0x8007000EL +#endif +#ifndef E_INVALIDARG +#define E_INVALIDARG (HRESULT)0x80070057L +#endif +#ifndef E_NOTIMPL +#define E_NOTIMPL (HRESULT)0x80004001L +#endif +#ifndef REGDB_E_CLASSNOTREG +#define REGDB_E_CLASSNOTREG (HRESULT)0x80040154L +#endif + +/* Severity codes */ +#ifndef SEVERITY_ERROR +#define SEVERITY_ERROR 1 +#endif + +/* Error facility codes */ +#ifndef FACILITY_WIN32 +#define FACILITY_WIN32 7 +#endif + +#ifndef FIELD_OFFSET +#define FIELD_OFFSET(type, field) ((LONG)&(((type *)0)->field)) +#endif + +/* DirectX headers (if it isn't included, I haven't tested it yet) + */ +/* We need these defines to mark what version of DirectX API we use */ +#define DIRECTDRAW_VERSION 0x0700 +#define DIRECTSOUND_VERSION 0x0500 +#define DIRECTINPUT_VERSION 0x0700 + +#include <ddraw.h> +#include <dsound.h> +#include <dinput.h> + +#if DIRECTINPUT_VERSION >= 0x0700 && !defined(DIMOFS_BUTTON4) +typedef struct _DIMOUSESTATE2 { + LONG lX; + LONG lY; + LONG lZ; + BYTE rgbButtons[8]; +} DIMOUSESTATE2, *LPDIMOUSESTATE2; + +#define DIMOFS_BUTTON4 (FIELD_OFFSET(DIMOUSESTATE2, rgbButtons) + 4) +#define DIMOFS_BUTTON5 (FIELD_OFFSET(DIMOUSESTATE2, rgbButtons) + 5) +#define DIMOFS_BUTTON6 (FIELD_OFFSET(DIMOUSESTATE2, rgbButtons) + 6) +#define DIMOFS_BUTTON7 (FIELD_OFFSET(DIMOUSESTATE2, rgbButtons) + 7) + +extern const DIDATAFORMAT c_dfDIMouse2; +#endif + +#endif /* _directx_h */ diff --git a/3rdparty/SDL/src/video/wscons/SDL_wsconsevents.c b/3rdparty/SDL/src/video/wscons/SDL_wsconsevents.c new file mode 100644 index 0000000..635b972 --- /dev/null +++ b/3rdparty/SDL/src/video/wscons/SDL_wsconsevents.c @@ -0,0 +1,233 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#include <sys/types.h> +#include <dev/wscons/wsdisplay_usl_io.h> +#include <sys/ioctl.h> +#include <fcntl.h> +#include <unistd.h> +#include <termios.h> +#include <errno.h> +#include <string.h> + +#include "SDL.h" +#include "../../events/SDL_sysevents.h" +#include "../../events/SDL_events_c.h" +#include "SDL_wsconsvideo.h" +#include "SDL_wsconsevents_c.h" + +static int posted = 0; + +int WSCONS_InitKeyboard(_THIS) +{ + struct termios tty; + + if (ioctl(private->fd, WSKBDIO_GTYPE, &private->kbdType) == -1) { + WSCONS_ReportError("cannot get keyboard type: %s", strerror(errno)); + return -1; + } + + if (tcgetattr(private->fd, &private->saved_tty) == -1) { + WSCONS_ReportError("cannot get terminal attributes: %s", strerror(errno)); + return -1; + } + private->did_save_tty = 1; + tty = private->saved_tty; + tty.c_iflag = IGNPAR | IGNBRK; + tty.c_oflag = 0; + tty.c_cflag = CREAD | CS8; + tty.c_lflag = 0; + tty.c_cc[VTIME] = 0; + tty.c_cc[VMIN] = 1; + cfsetispeed(&tty, 9600); + cfsetospeed(&tty, 9600); + if (tcsetattr(private->fd, TCSANOW, &tty) < 0) { + WSCONS_ReportError("cannot set terminal attributes: %s", strerror(errno)); + return -1; + } + if (ioctl(private->fd, KDSKBMODE, K_RAW) == -1) { + WSCONS_ReportError("cannot set raw keyboard mode: %s", strerror(errno)); + return -1; + } + + return 0; +} + +void WSCONS_ReleaseKeyboard(_THIS) +{ + if (private->fd != -1) { + if (ioctl(private->fd, KDSKBMODE, K_XLATE) == -1) { + WSCONS_ReportError("cannot restore keyboard to translated mode: %s", + strerror(errno)); + } + if (private->did_save_tty) { + if (tcsetattr(private->fd, TCSANOW, &private->saved_tty) < 0) { + WSCONS_ReportError("cannot restore keynoard attributes: %s", + strerror(errno)); + } + } + } +} + +static void updateMouse() +{ +} + +static SDLKey keymap[128]; + +static SDL_keysym *TranslateKey(int scancode, SDL_keysym *keysym) +{ + keysym->scancode = scancode; + keysym->sym = SDLK_UNKNOWN; + keysym->mod = KMOD_NONE; + + if (scancode < SDL_arraysize(keymap)) + keysym->sym = keymap[scancode]; + + if (keysym->sym == SDLK_UNKNOWN) + printf("Unknown mapping for scancode %d\n", scancode); + + return keysym; +} + +static void updateKeyboard(_THIS) +{ + unsigned char buf[100]; + SDL_keysym keysym; + int n, i; + + if ((n = read(private->fd, buf, sizeof(buf))) > 0) { + for (i = 0; i < n; i++) { + unsigned char c = buf[i] & 0x7f; + if (c == 224) // special key prefix -- what should we do with it? + continue; + posted += SDL_PrivateKeyboard((buf[i] & 0x80) ? SDL_RELEASED : SDL_PRESSED, + TranslateKey(c, &keysym)); + } + } +} + +void WSCONS_PumpEvents(_THIS) +{ + do { + posted = 0; + updateMouse(); + updateKeyboard(this); + } while (posted); +} + +void WSCONS_InitOSKeymap(_THIS) +{ + int i; + + /* Make sure unknown keys are mapped correctly */ + for (i=0; i < SDL_arraysize(keymap); i++) { + keymap[i] = SDLK_UNKNOWN; + } + + switch (private->kbdType) { +#ifdef WSKBD_TYPE_ZAURUS + case WSKBD_TYPE_ZAURUS: + /* top row */ + keymap[2] = SDLK_1; + keymap[3] = SDLK_2; + keymap[4] = SDLK_3; + keymap[5] = SDLK_4; + keymap[6] = SDLK_5; + keymap[7] = SDLK_6; + keymap[8] = SDLK_7; + keymap[9] = SDLK_8; + keymap[10] = SDLK_9; + keymap[11] = SDLK_0; + keymap[14] = SDLK_BACKSPACE; + + /* second row */ + keymap[16] = SDLK_q; + keymap[17] = SDLK_w; + keymap[18] = SDLK_e; + keymap[19] = SDLK_r; + keymap[20] = SDLK_t; + keymap[21] = SDLK_y; + keymap[22] = SDLK_u; + keymap[23] = SDLK_i; + keymap[24] = SDLK_o; + keymap[25] = SDLK_p; + + /* third row */ + keymap[15] = SDLK_TAB; + keymap[30] = SDLK_a; + keymap[31] = SDLK_s; + keymap[32] = SDLK_d; + keymap[33] = SDLK_f; + keymap[34] = SDLK_g; + keymap[35] = SDLK_h; + keymap[36] = SDLK_j; + keymap[37] = SDLK_k; + keymap[38] = SDLK_l; + + /* fourth row */ + keymap[42] = SDLK_LSHIFT; + keymap[44] = SDLK_z; + keymap[45] = SDLK_x; + keymap[46] = SDLK_c; + keymap[47] = SDLK_v; + keymap[48] = SDLK_b; + keymap[49] = SDLK_n; + keymap[50] = SDLK_m; + keymap[54] = SDLK_RSHIFT; + keymap[28] = SDLK_RETURN; + + /* fifth row */ + keymap[56] = SDLK_LALT; + keymap[29] = SDLK_LCTRL; + /* keymap[56] = ; */ + keymap[0] = SDLK_LSUPER; + keymap[12] = SDLK_MINUS; + keymap[57] = SDLK_SPACE; + keymap[51] = SDLK_COMMA; + keymap[52] = SDLK_PERIOD; + + /* misc */ + keymap[59] = SDLK_F1; + keymap[60] = SDLK_F2; + keymap[61] = SDLK_F3; + keymap[62] = SDLK_F4; + keymap[63] = SDLK_F5; + keymap[1] = SDLK_ESCAPE; + /* keymap[28] = SDLK_KP_ENTER; */ + keymap[72] = SDLK_UP; + keymap[75] = SDLK_LEFT; + keymap[77] = SDLK_RIGHT; + keymap[80] = SDLK_DOWN; + break; +#endif /* WSKBD_TYPE_ZAURUS */ + + default: + WSCONS_ReportError("Unable to map keys for keyboard type %u", + private->kbdType); + break; + } +} + +/* end of SDL_wsconsevents.c ... */ + diff --git a/3rdparty/SDL/src/video/wscons/SDL_wsconsevents_c.h b/3rdparty/SDL/src/video/wscons/SDL_wsconsevents_c.h new file mode 100644 index 0000000..f68ee6e --- /dev/null +++ b/3rdparty/SDL/src/video/wscons/SDL_wsconsevents_c.h @@ -0,0 +1,36 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#include "SDL_wsconsvideo.h" + +int WSCONS_InitKeyboard(_THIS); +void WSCONS_ReleaseKeyboard(_THIS); + +/* Variables and functions exported by SDL_sysevents.c to other parts + of the native video subsystem (SDL_sysvideo.c) +*/ +extern void WSCONS_InitOSKeymap(_THIS); +extern void WSCONS_PumpEvents(_THIS); + +/* end of SDL_wsconsevents_c.h ... */ + diff --git a/3rdparty/SDL/src/video/wscons/SDL_wsconsmouse.c b/3rdparty/SDL/src/video/wscons/SDL_wsconsmouse.c new file mode 100644 index 0000000..b69e0c5 --- /dev/null +++ b/3rdparty/SDL/src/video/wscons/SDL_wsconsmouse.c @@ -0,0 +1,33 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#include "SDL_mouse.h" +#include "../../events/SDL_events_c.h" + +#include "SDL_wsconsmouse_c.h" + + +/* The implementation dependent data for the window manager cursor */ +struct WMcursor { + int unused; +}; diff --git a/3rdparty/SDL/src/video/wscons/SDL_wsconsmouse_c.h b/3rdparty/SDL/src/video/wscons/SDL_wsconsmouse_c.h new file mode 100644 index 0000000..875437b --- /dev/null +++ b/3rdparty/SDL/src/video/wscons/SDL_wsconsmouse_c.h @@ -0,0 +1,26 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#include "SDL_wsconsvideo.h" + +/* Functions to be exported */ diff --git a/3rdparty/SDL/src/video/wscons/SDL_wsconsvideo.c b/3rdparty/SDL/src/video/wscons/SDL_wsconsvideo.c new file mode 100644 index 0000000..0e850d1 --- /dev/null +++ b/3rdparty/SDL/src/video/wscons/SDL_wsconsvideo.c @@ -0,0 +1,609 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#include <sys/time.h> +#include <sys/mman.h> +#include <sys/ioctl.h> +#include <dev/wscons/wsdisplay_usl_io.h> +#include <fcntl.h> +#include <unistd.h> +#include <errno.h> + +#include "SDL_video.h" +#include "SDL_mouse.h" +#include "../SDL_sysvideo.h" +#include "../SDL_pixels_c.h" +#include "../../events/SDL_events_c.h" + +#include "SDL_wsconsvideo.h" +#include "SDL_wsconsevents_c.h" +#include "SDL_wsconsmouse_c.h" + +#define WSCONSVID_DRIVER_NAME "wscons" +enum { + WSCONS_ROTATE_NONE = 0, + WSCONS_ROTATE_CCW = 90, + WSCONS_ROTATE_UD = 180, + WSCONS_ROTATE_CW = 270 +}; + +#define min(a,b) ((a)<(b)?(a):(b)) + +/* Initialization/Query functions */ +static int WSCONS_VideoInit(_THIS, SDL_PixelFormat *vformat); +static SDL_Rect **WSCONS_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags); +static SDL_Surface *WSCONS_SetVideoMode(_THIS, SDL_Surface *current, int width, int height, int bpp, Uint32 flags); +static int WSCONS_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors); +static void WSCONS_VideoQuit(_THIS); + +/* Hardware surface functions */ +static int WSCONS_AllocHWSurface(_THIS, SDL_Surface *surface); +static int WSCONS_LockHWSurface(_THIS, SDL_Surface *surface); +static void WSCONS_UnlockHWSurface(_THIS, SDL_Surface *surface); +static void WSCONS_FreeHWSurface(_THIS, SDL_Surface *surface); + +/* etc. */ +static WSCONS_bitBlit WSCONS_blit16; +static WSCONS_bitBlit WSCONS_blit16blocked; +static void WSCONS_UpdateRects(_THIS, int numrects, SDL_Rect *rects); + +void WSCONS_ReportError(char *fmt, ...) +{ + char message[200]; + va_list vaArgs; + + message[199] = '\0'; + + va_start(vaArgs, fmt); + vsnprintf(message, 199, fmt, vaArgs); + va_end(vaArgs); + + SDL_SetError(message); + fprintf(stderr, "WSCONS error: %s\n", message); +} + +/* WSCONS driver bootstrap functions */ + +static int WSCONS_Available(void) +{ + return 1; +} + +static void WSCONS_DeleteDevice(SDL_VideoDevice *device) +{ + SDL_free(device->hidden); + SDL_free(device); +} + +static SDL_VideoDevice *WSCONS_CreateDevice(int devindex) +{ + SDL_VideoDevice *device; + + /* Initialize all variables that we clean on shutdown */ + device = (SDL_VideoDevice *)SDL_malloc(sizeof(SDL_VideoDevice)); + if (device == NULL) { + SDL_OutOfMemory(); + return 0; + } + SDL_memset(device, 0, (sizeof *device)); + device->hidden = + (struct SDL_PrivateVideoData *)SDL_malloc((sizeof *device->hidden)); + if (device->hidden == NULL) { + SDL_OutOfMemory(); + SDL_free(device); + return(0); + } + SDL_memset(device->hidden, 0, (sizeof *device->hidden)); + device->hidden->fd = -1; + + /* Set the function pointers */ + device->VideoInit = WSCONS_VideoInit; + device->ListModes = WSCONS_ListModes; + device->SetVideoMode = WSCONS_SetVideoMode; + device->SetColors = WSCONS_SetColors; + device->UpdateRects = WSCONS_UpdateRects; + device->VideoQuit = WSCONS_VideoQuit; + device->AllocHWSurface = WSCONS_AllocHWSurface; + device->LockHWSurface = WSCONS_LockHWSurface; + device->UnlockHWSurface = WSCONS_UnlockHWSurface; + device->FreeHWSurface = WSCONS_FreeHWSurface; + device->InitOSKeymap = WSCONS_InitOSKeymap; + device->PumpEvents = WSCONS_PumpEvents; + device->free = WSCONS_DeleteDevice; + + return device; +} + +VideoBootStrap WSCONS_bootstrap = { + WSCONSVID_DRIVER_NAME, + "SDL wscons video driver", + WSCONS_Available, + WSCONS_CreateDevice +}; + +#define WSCONSDEV_FORMAT "/dev/ttyC%01x" + +int WSCONS_VideoInit(_THIS, SDL_PixelFormat *vformat) +{ + char devnamebuf[30]; + char *devname; + char *rotation; + int wstype; + int wsmode = WSDISPLAYIO_MODE_DUMBFB; + size_t len, mapsize; + int pagemask; + int width, height; + + devname = SDL_getenv("SDL_WSCONSDEV"); + if (devname == NULL) { + int activeVT; + if (ioctl(STDIN_FILENO, VT_GETACTIVE, &activeVT) == -1) { + WSCONS_ReportError("Unable to determine active terminal: %s", + strerror(errno)); + return -1; + } + SDL_snprintf(devnamebuf, sizeof(devnamebuf), WSCONSDEV_FORMAT, activeVT - 1); + devname = devnamebuf; + } + + private->fd = open(devname, O_RDWR | O_NONBLOCK, 0); + if (private->fd == -1) { + WSCONS_ReportError("open %s: %s", devname, strerror(errno)); + return -1; + } + if (ioctl(private->fd, WSDISPLAYIO_GINFO, &private->info) == -1) { + WSCONS_ReportError("ioctl WSDISPLAY_GINFO: %s", strerror(errno)); + return -1; + } + if (ioctl(private->fd, WSDISPLAYIO_GTYPE, &wstype) == -1) { + WSCONS_ReportError("ioctl WSDISPLAY_GTYPE: %s", strerror(errno)); + return -1; + } + if (ioctl(private->fd, WSDISPLAYIO_LINEBYTES, &private->physlinebytes) == -1) { + WSCONS_ReportError("ioctl WSDISPLAYIO_LINEBYTES: %s", strerror(errno)); + return -1; + } + if (private->info.depth > 8) { + if (wstype == WSDISPLAY_TYPE_SUN24 || + wstype == WSDISPLAY_TYPE_SUNCG12 || + wstype == WSDISPLAY_TYPE_SUNCG14 || + wstype == WSDISPLAY_TYPE_SUNTCX || + wstype == WSDISPLAY_TYPE_SUNFFB) { + private->redMask = 0x0000ff; + private->greenMask = 0x00ff00; + private->blueMask = 0xff0000; +#ifdef WSDISPLAY_TYPE_PXALCD + } else if (wstype == WSDISPLAY_TYPE_PXALCD) { + private->redMask = 0x1f << 11; + private->greenMask = 0x3f << 5; + private->blueMask = 0x1f; +#endif + } else { + WSCONS_ReportError("Unknown video hardware"); + return -1; + } + } else { + WSCONS_ReportError("Displays with 8 bpp or less are not supported"); + return -1; + } + + private->rotate = WSCONS_ROTATE_NONE; + rotation = SDL_getenv("SDL_VIDEO_WSCONS_ROTATION"); + if (rotation != NULL) { + if (SDL_strlen(rotation) == 0) { + private->shadowFB = 0; + private->rotate = WSCONS_ROTATE_NONE; + printf("Not rotating, no shadow\n"); + } else if (!SDL_strcmp(rotation, "NONE")) { + private->shadowFB = 1; + private->rotate = WSCONS_ROTATE_NONE; + printf("Not rotating, but still using shadow\n"); + } else if (!SDL_strcmp(rotation, "CW")) { + private->shadowFB = 1; + private->rotate = WSCONS_ROTATE_CW; + printf("Rotating screen clockwise\n"); + } else if (!SDL_strcmp(rotation, "CCW")) { + private->shadowFB = 1; + private->rotate = WSCONS_ROTATE_CCW; + printf("Rotating screen counter clockwise\n"); + } else if (!SDL_strcmp(rotation, "UD")) { + private->shadowFB = 1; + private->rotate = WSCONS_ROTATE_UD; + printf("Rotating screen upside down\n"); + } else { + WSCONS_ReportError("\"%s\" is not a valid value for " + "SDL_VIDEO_WSCONS_ROTATION", rotation); + return -1; + } + } + + switch (private->info.depth) { + case 1: + case 4: + case 8: + len = private->physlinebytes * private->info.height; + break; + case 16: + if (private->physlinebytes == private->info.width) { + len = private->info.width * private->info.height * sizeof(short); + } else { + len = private->physlinebytes * private->info.height; + } + if (private->rotate == WSCONS_ROTATE_NONE || + private->rotate == WSCONS_ROTATE_UD) { + private->blitFunc = WSCONS_blit16; + } else { + private->blitFunc = WSCONS_blit16blocked; + } + break; + case 32: + if (private->physlinebytes == private->info.width) { + len = private->info.width * private->info.height * sizeof(int); + } else { + len = private->physlinebytes * private->info.height; + } + break; + default: + WSCONS_ReportError("unsupported depth %d", private->info.depth); + return -1; + } + + if (private->shadowFB && private->blitFunc == NULL) { + WSCONS_ReportError("Using software buffer, but no blitter function is " + "available for this %d bpp.", private->info.depth); + return -1; + } + + if (ioctl(private->fd, WSDISPLAYIO_SMODE, &wsmode) == -1) { + WSCONS_ReportError("ioctl SMODE"); + return -1; + } + + pagemask = getpagesize() - 1; + mapsize = ((int)len + pagemask) & ~pagemask; + private->physmem = (Uint8 *)mmap(NULL, mapsize, + PROT_READ | PROT_WRITE, MAP_SHARED, + private->fd, (off_t)0); + if (private->physmem == (Uint8 *)MAP_FAILED) { + private->physmem = NULL; + WSCONS_ReportError("mmap: %s", strerror(errno)); + return -1; + } + private->fbmem_len = len; + + if (private->rotate == WSCONS_ROTATE_CW || + private->rotate == WSCONS_ROTATE_CCW) { + width = private->info.height; + height = private->info.width; + } else { + width = private->info.width; + height = private->info.height; + } + + this->info.current_w = width; + this->info.current_h = height; + + if (private->shadowFB) { + private->shadowmem = (Uint8 *)SDL_malloc(len); + if (private->shadowmem == NULL) { + WSCONS_ReportError("No memory for shadow"); + return -1; + } + private->fbstart = private->shadowmem; + private->fblinebytes = width * ((private->info.depth + 7) / 8); + } else { + private->fbstart = private->physmem; + private->fblinebytes = private->physlinebytes; + } + + private->SDL_modelist[0] = (SDL_Rect *)SDL_malloc(sizeof(SDL_Rect)); + private->SDL_modelist[0]->w = width; + private->SDL_modelist[0]->h = height; + + vformat->BitsPerPixel = private->info.depth; + vformat->BytesPerPixel = private->info.depth / 8; + + if (WSCONS_InitKeyboard(this) == -1) { + return -1; + } + + return 0; +} + +SDL_Rect **WSCONS_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags) +{ + if (format->BitsPerPixel == private->info.depth) { + return private->SDL_modelist; + } else { + return NULL; + } +} + +SDL_Surface *WSCONS_SetVideoMode(_THIS, SDL_Surface *current, + int width, int height, int bpp, Uint32 flags) +{ + if (width != private->SDL_modelist[0]->w || + height != private->SDL_modelist[0]->h) { + WSCONS_ReportError("Requested video mode %dx%d not supported.", + width, height); + return NULL; + } + if (bpp != private->info.depth) { + WSCONS_ReportError("Requested video depth %d bpp not supported.", bpp); + return NULL; + } + + if (!SDL_ReallocFormat(current, + bpp, + private->redMask, + private->greenMask, + private->blueMask, + 0)) { + WSCONS_ReportError("Couldn't allocate new pixel format"); + return NULL; + } + + current->flags &= SDL_FULLSCREEN; + if (private->shadowFB) { + current->flags |= SDL_SWSURFACE; + } else { + current->flags |= SDL_HWSURFACE; + } + current->w = width; + current->h = height; + current->pitch = private->fblinebytes; + current->pixels = private->fbstart; + + SDL_memset(private->fbstart, 0, private->fbmem_len); + + return current; +} + +static int WSCONS_AllocHWSurface(_THIS, SDL_Surface *surface) +{ + return -1; +} +static void WSCONS_FreeHWSurface(_THIS, SDL_Surface *surface) +{ +} + +static int WSCONS_LockHWSurface(_THIS, SDL_Surface *surface) +{ + return 0; +} + +static void WSCONS_UnlockHWSurface(_THIS, SDL_Surface *surface) +{ +} + +static void WSCONS_blit16(Uint8 *byte_src_pos, + int srcRightDelta, + int srcDownDelta, + Uint8 *byte_dst_pos, + int dst_linebytes, + int width, + int height) +{ + int w; + Uint16 *src_pos = (Uint16 *)byte_src_pos; + Uint16 *dst_pos = (Uint16 *)byte_dst_pos; + + while (height) { + Uint16 *src = src_pos; + Uint16 *dst = dst_pos; + for (w = width; w != 0; w--) { + *dst = *src; + src += srcRightDelta; + dst++; + } + dst_pos = (Uint16 *)((Uint8 *)dst_pos + dst_linebytes); + src_pos += srcDownDelta; + height--; + } +} + +#define BLOCKSIZE_W 32 +#define BLOCKSIZE_H 32 + +static void WSCONS_blit16blocked(Uint8 *byte_src_pos, + int srcRightDelta, + int srcDownDelta, + Uint8 *byte_dst_pos, + int dst_linebytes, + int width, + int height) +{ + int w; + Uint16 *src_pos = (Uint16 *)byte_src_pos; + Uint16 *dst_pos = (Uint16 *)byte_dst_pos; + + while (height > 0) { + Uint16 *src = src_pos; + Uint16 *dst = dst_pos; + for (w = width; w > 0; w -= BLOCKSIZE_W) { + WSCONS_blit16((Uint8 *)src, + srcRightDelta, + srcDownDelta, + (Uint8 *)dst, + dst_linebytes, + min(w, BLOCKSIZE_W), + min(height, BLOCKSIZE_H)); + src += srcRightDelta * BLOCKSIZE_W; + dst += BLOCKSIZE_W; + } + dst_pos = (Uint16 *)((Uint8 *)dst_pos + dst_linebytes * BLOCKSIZE_H); + src_pos += srcDownDelta * BLOCKSIZE_H; + height -= BLOCKSIZE_H; + } +} + +static void WSCONS_UpdateRects(_THIS, int numrects, SDL_Rect *rects) +{ + int width = private->SDL_modelist[0]->w; + int height = private->SDL_modelist[0]->h; + int bytesPerPixel = (private->info.depth + 7) / 8; + int i; + + if (!private->shadowFB) { + return; + } + + if (private->info.depth != 16) { + WSCONS_ReportError("Shadow copy only implemented for 16 bpp"); + return; + } + + for (i = 0; i < numrects; i++) { + int x1, y1, x2, y2; + int scr_x1, scr_y1, scr_x2, scr_y2; + int sha_x1, sha_y1; + int shadowRightDelta; /* Address change when moving right in dest */ + int shadowDownDelta; /* Address change when moving down in dest */ + Uint8 *src_start; + Uint8 *dst_start; + + x1 = rects[i].x; + y1 = rects[i].y; + x2 = x1 + rects[i].w; + y2 = y1 + rects[i].h; + + if (x1 < 0) { + x1 = 0; + } else if (x1 > width) { + x1 = width; + } + if (x2 < 0) { + x2 = 0; + } else if (x2 > width) { + x2 = width; + } + if (y1 < 0) { + y1 = 0; + } else if (y1 > height) { + y1 = height; + } + if (y2 < 0) { + y2 = 0; + } else if (y2 > height) { + y2 = height; + } + if (x2 <= x1 || y2 <= y1) { + continue; + } + + switch (private->rotate) { + case WSCONS_ROTATE_NONE: + sha_x1 = scr_x1 = x1; + sha_y1 = scr_y1 = y1; + scr_x2 = x2; + scr_y2 = y2; + shadowRightDelta = 1; + shadowDownDelta = width; + break; + case WSCONS_ROTATE_CCW: + scr_x1 = y1; + scr_y1 = width - x2; + scr_x2 = y2; + scr_y2 = width - x1; + sha_x1 = x2 - 1; + sha_y1 = y1; + shadowRightDelta = width; + shadowDownDelta = -1; + break; + case WSCONS_ROTATE_UD: + scr_x1 = width - x2; + scr_y1 = height - y2; + scr_x2 = width - x1; + scr_y2 = height - y1; + sha_x1 = x2 - 1; + sha_y1 = y2 - 1; + shadowRightDelta = -1; + shadowDownDelta = -width; + break; + case WSCONS_ROTATE_CW: + scr_x1 = height - y2; + scr_y1 = x1; + scr_x2 = height - y1; + scr_y2 = x2; + sha_x1 = x1; + sha_y1 = y2 - 1; + shadowRightDelta = -width; + shadowDownDelta = 1; + break; + default: + WSCONS_ReportError("Unknown rotation"); + return; + } + + src_start = private->shadowmem + (sha_y1 * width + sha_x1) * bytesPerPixel; + dst_start = private->physmem + scr_y1 * private->physlinebytes + + scr_x1 * bytesPerPixel; + + private->blitFunc(src_start, + shadowRightDelta, + shadowDownDelta, + dst_start, + private->physlinebytes, + scr_x2 - scr_x1, + scr_y2 - scr_y1); + } +} + +int WSCONS_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors) +{ + return 0; +} + +/* + * Note: If we are terminated, this could be called in the middle of + * another SDL video routine -- notably UpdateRects. + */ +void WSCONS_VideoQuit(_THIS) +{ + int mode = WSDISPLAYIO_MODE_EMUL; + + if (private->shadowmem != NULL) { + SDL_free(private->shadowmem); + private->shadowmem = NULL; + } + private->fbstart = NULL; + if (this->screen != NULL) { + this->screen->pixels = NULL; + } + + if (private->SDL_modelist[0] != NULL) { + SDL_free(private->SDL_modelist[0]); + private->SDL_modelist[0] = NULL; + } + + if (ioctl(private->fd, WSDISPLAYIO_SMODE, &mode) == -1) { + WSCONS_ReportError("ioctl SMODE"); + } + + WSCONS_ReleaseKeyboard(this); + + if (private->fd != -1) { + close(private->fd); + private->fd = -1; + } +} diff --git a/3rdparty/SDL/src/video/wscons/SDL_wsconsvideo.h b/3rdparty/SDL/src/video/wscons/SDL_wsconsvideo.h new file mode 100644 index 0000000..9d75c17 --- /dev/null +++ b/3rdparty/SDL/src/video/wscons/SDL_wsconsvideo.h @@ -0,0 +1,76 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#ifndef _SDL_wsconsvideo_h +#define _SDL_wsconsvideo_h + +#include <sys/time.h> +#include <termios.h> +#include <dev/wscons/wsconsio.h> + +#include "SDL_mouse.h" +#include "SDL_mutex.h" +#include "../SDL_sysvideo.h" + +void WSCONS_ReportError(char *fmt, ...); + +/* Hidden "this" pointer for the video functions */ +#define _THIS SDL_VideoDevice *this +#define private (this->hidden) + +/* Private display data */ + +typedef void WSCONS_bitBlit(Uint8 *src_pos, + int srcRightDelta, // pixels, not bytes + int srcDownDelta, // pixels, not bytes + Uint8 *dst_pos, + int dst_linebytes, + int width, + int height); + +struct SDL_PrivateVideoData { + int fd; /* file descriptor of open device */ + struct wsdisplay_fbinfo info; /* frame buffer characteristics */ + int physlinebytes; /* number of bytes per row */ + int redMask, greenMask, blueMask; + + Uint8 *fbstart; /* These refer to the surface used, */ + int fblinebytes; /* physical frame buffer or shadow. */ + + size_t fbmem_len; + Uint8 *physmem; + Uint8 *shadowmem; + int rotate; + int shadowFB; /* Tells whether a shadow is being used. */ + + WSCONS_bitBlit *blitFunc; + + SDL_Rect *SDL_modelist[2]; + + unsigned int kbdType; + int did_save_tty; + struct termios saved_tty; +}; + + +#endif /* _SDL_wsconsvideo_h */ diff --git a/3rdparty/SDL/src/video/x11/SDL_x11dga.c b/3rdparty/SDL/src/video/x11/SDL_x11dga.c new file mode 100644 index 0000000..e1c0c2e --- /dev/null +++ b/3rdparty/SDL/src/video/x11/SDL_x11dga.c @@ -0,0 +1,90 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* This is currently only used to enable DGA mouse. + There is a completely separate DGA driver that is fullscreen-only. +*/ + +#include "SDL_video.h" +#include "../SDL_cursor_c.h" +#include "SDL_x11dga_c.h" + +/* Global for the error handler */ +int dga_event, dga_error = -1; + +void X11_EnableDGAMouse(_THIS) +{ +#if SDL_VIDEO_DRIVER_X11_DGAMOUSE + static int use_dgamouse = -1; + + /* Check configuration to see if we should use DGA mouse */ + if ( use_dgamouse < 0 ) { + int dga_major, dga_minor; + int dga_flags; + const char *env_use_dgamouse; + + use_dgamouse = 1; + env_use_dgamouse = SDL_getenv("SDL_VIDEO_X11_DGAMOUSE"); + if ( env_use_dgamouse ) { + use_dgamouse = SDL_atoi(env_use_dgamouse); + } + /* Check for buggy X servers */ + if ( use_dgamouse && BUGGY_XFREE86(==, 4000) ) { + use_dgamouse = 0; + } + if ( !use_dgamouse || !local_X11 || + !SDL_NAME(XF86DGAQueryExtension)(SDL_Display, &dga_event, &dga_error) || + !SDL_NAME(XF86DGAQueryVersion)(SDL_Display, &dga_major, &dga_minor) || + !SDL_NAME(XF86DGAQueryDirectVideo)(SDL_Display, SDL_Screen, &dga_flags) || + !(dga_flags & XF86DGADirectPresent) ) { + use_dgamouse = 0; + } + } + + if ( use_dgamouse && !(using_dga & DGA_MOUSE) ) { + if ( SDL_NAME(XF86DGADirectVideo)(SDL_Display, SDL_Screen, XF86DGADirectMouse) ) { + using_dga |= DGA_MOUSE; + } + } +#endif /* SDL_VIDEO_DRIVER_X11_DGAMOUSE */ +} + +/* Argh. Glide resets DGA mouse mode when it makes the context current! */ +void X11_CheckDGAMouse(_THIS) +{ +#if SDL_VIDEO_DRIVER_X11_DGAMOUSE + if ( using_dga & DGA_MOUSE ) { + SDL_NAME(XF86DGADirectVideo)(SDL_Display,SDL_Screen,XF86DGADirectMouse); + } +#endif +} + +void X11_DisableDGAMouse(_THIS) +{ +#if SDL_VIDEO_DRIVER_X11_DGAMOUSE + if ( using_dga & DGA_MOUSE ) { + SDL_NAME(XF86DGADirectVideo)(SDL_Display, SDL_Screen, 0); + using_dga &= ~DGA_MOUSE; + } +#endif /* SDL_VIDEO_DRIVER_X11_DGAMOUSE */ +} diff --git a/3rdparty/SDL/src/video/x11/SDL_x11dga_c.h b/3rdparty/SDL/src/video/x11/SDL_x11dga_c.h new file mode 100644 index 0000000..a57511c --- /dev/null +++ b/3rdparty/SDL/src/video/x11/SDL_x11dga_c.h @@ -0,0 +1,33 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#include "SDL_x11video.h" + +/* Different DGA access states */ +#define DGA_GRAPHICS 0x01 +#define DGA_KEYBOARD 0x02 +#define DGA_MOUSE 0x04 + +extern void X11_EnableDGAMouse(_THIS); +extern void X11_CheckDGAMouse(_THIS); +extern void X11_DisableDGAMouse(_THIS); diff --git a/3rdparty/SDL/src/video/x11/SDL_x11dyn.c b/3rdparty/SDL/src/video/x11/SDL_x11dyn.c new file mode 100644 index 0000000..7058add --- /dev/null +++ b/3rdparty/SDL/src/video/x11/SDL_x11dyn.c @@ -0,0 +1,222 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#define DEBUG_DYNAMIC_X11 0 + +#include "SDL_x11dyn.h" + +#if DEBUG_DYNAMIC_X11 +#include <stdio.h> +#endif + +#ifdef SDL_VIDEO_DRIVER_X11_DYNAMIC + +#include "SDL_name.h" +#include "SDL_loadso.h" + +typedef struct +{ + void *lib; + const char *libname; +} x11dynlib; + +#ifndef SDL_VIDEO_DRIVER_X11_DYNAMIC +#define SDL_VIDEO_DRIVER_X11_DYNAMIC NULL +#endif +#ifndef SDL_VIDEO_DRIVER_X11_DYNAMIC_XEXT +#define SDL_VIDEO_DRIVER_X11_DYNAMIC_XEXT NULL +#endif +#ifndef SDL_VIDEO_DRIVER_X11_DYNAMIC_XRENDER +#define SDL_VIDEO_DRIVER_X11_DYNAMIC_XRENDER NULL +#endif +#ifndef SDL_VIDEO_DRIVER_X11_DYNAMIC_XRANDR +#define SDL_VIDEO_DRIVER_X11_DYNAMIC_XRANDR NULL +#endif + +static x11dynlib x11libs[] = +{ + { NULL, SDL_VIDEO_DRIVER_X11_DYNAMIC }, + { NULL, SDL_VIDEO_DRIVER_X11_DYNAMIC_XEXT }, + { NULL, SDL_VIDEO_DRIVER_X11_DYNAMIC_XRENDER }, + { NULL, SDL_VIDEO_DRIVER_X11_DYNAMIC_XRANDR }, +}; + +static void *X11_GetSym(const char *fnname, int *rc) +{ + void *fn = NULL; + int i; + for (i = 0; i < SDL_TABLESIZE(x11libs); i++) { + if (x11libs[i].lib != NULL) + { + fn = SDL_LoadFunction(x11libs[i].lib, fnname); + if (fn != NULL) + break; + } + } + + #if DEBUG_DYNAMIC_X11 + if (fn != NULL) + printf("X11: Found '%s' in %s (%p)\n", fnname, x11libs[i].libname, *fn); + else + printf("X11: Symbol '%s' NOT FOUND!\n", fnname); + #endif + + if (fn == NULL) + *rc = 0; /* kill this module. */ + + return fn; +} + + +/* Define all the function pointers and wrappers... */ +#define SDL_X11_MODULE(modname) +#define SDL_X11_SYM(rc,fn,params,args,ret) \ + static rc (*p##fn) params = NULL; \ + rc fn params { ret p##fn args ; } +#include "SDL_x11sym.h" +#undef SDL_X11_MODULE +#undef SDL_X11_SYM +#endif /* SDL_VIDEO_DRIVER_X11_DYNAMIC */ + +/* Annoying varargs entry point... */ +#ifdef X_HAVE_UTF8_STRING +XIC (*pXCreateIC)(XIM,...) = NULL; +char *(*pXGetICValues)(XIC, ...) = NULL; +#endif + +/* These SDL_X11_HAVE_* flags are here whether you have dynamic X11 or not. */ +#define SDL_X11_MODULE(modname) int SDL_X11_HAVE_##modname = 1; +#define SDL_X11_SYM(rc,fn,params,args,ret) +#include "SDL_x11sym.h" +#undef SDL_X11_MODULE +#undef SDL_X11_SYM + + +static void *SDL_XGetRequest_workaround(Display* dpy, CARD8 type, size_t len) +{ + xReq *req; + WORD64ALIGN + if (dpy->bufptr + len > dpy->bufmax) + _XFlush(dpy); + dpy->last_req = dpy->bufptr; + req = (xReq*)dpy->bufptr; + req->reqType = type; + req->length = len / 4; + dpy->bufptr += len; + dpy->request++; + return req; +} + +static int x11_load_refcount = 0; + +void SDL_X11_UnloadSymbols(void) +{ + #ifdef SDL_VIDEO_DRIVER_X11_DYNAMIC + /* Don't actually unload if more than one module is using the libs... */ + if (x11_load_refcount > 0) { + if (--x11_load_refcount == 0) { + int i; + + /* set all the function pointers to NULL. */ + #define SDL_X11_MODULE(modname) SDL_X11_HAVE_##modname = 1; + #define SDL_X11_SYM(rc,fn,params,args,ret) p##fn = NULL; + #include "SDL_x11sym.h" + #undef SDL_X11_MODULE + #undef SDL_X11_SYM + + #ifdef X_HAVE_UTF8_STRING + pXCreateIC = NULL; + pXGetICValues = NULL; + #endif + + for (i = 0; i < SDL_TABLESIZE(x11libs); i++) { + if (x11libs[i].lib != NULL) { + SDL_UnloadObject(x11libs[i].lib); + x11libs[i].lib = NULL; + } + } + } + } + #endif +} + +/* returns non-zero if all needed symbols were loaded. */ +int SDL_X11_LoadSymbols(void) +{ + int rc = 1; /* always succeed if not using Dynamic X11 stuff. */ + + #ifdef SDL_VIDEO_DRIVER_X11_DYNAMIC + /* deal with multiple modules (dga, x11, etc) needing these symbols... */ + if (x11_load_refcount++ == 0) { + int i; + int *thismod = NULL; + for (i = 0; i < SDL_TABLESIZE(x11libs); i++) { + if (x11libs[i].libname != NULL) { + x11libs[i].lib = SDL_LoadObject(x11libs[i].libname); + } + } + #define SDL_X11_MODULE(modname) thismod = &SDL_X11_HAVE_##modname; + #define SDL_X11_SYM(rc,fn,params,args,ret) \ + p##fn = (rc(*)params) X11_GetSym(#fn, thismod); + #include "SDL_x11sym.h" + #undef SDL_X11_MODULE + #undef SDL_X11_SYM + + #ifdef X_HAVE_UTF8_STRING + pXCreateIC = (XIC(*)(XIM,...)) X11_GetSym("XCreateIC", + &SDL_X11_HAVE_UTF8); + pXGetICValues = (char * (*)(XIC,...)) X11_GetSym("XGetICValues", + &SDL_X11_HAVE_UTF8); + #endif + + /* + * In case we're built with newer Xlib headers, we need to make sure + * that _XGetRequest() is available, even on older systems. + * Otherwise, various Xlib macros we use will call a NULL pointer. + */ + if (!SDL_X11_HAVE_XGETREQUEST) { + p_XGetRequest = SDL_XGetRequest_workaround; + } + + if (SDL_X11_HAVE_BASEXLIB) { /* all required symbols loaded. */ + SDL_ClearError(); + } else { + SDL_X11_UnloadSymbols(); /* in case something got loaded... */ + rc = 0; + } + } + #else + #if DEBUG_DYNAMIC_X11 + printf("X11: No dynamic X11 support in this build of SDL.\n"); + #endif + #ifdef X_HAVE_UTF8_STRING + pXCreateIC = XCreateIC; + pXGetICValues = XGetICValues; + #endif + #endif + + return rc; +} + +/* end of SDL_x11dyn.c ... */ + diff --git a/3rdparty/SDL/src/video/x11/SDL_x11dyn.h b/3rdparty/SDL/src/video/x11/SDL_x11dyn.h new file mode 100644 index 0000000..c2ff82a --- /dev/null +++ b/3rdparty/SDL/src/video/x11/SDL_x11dyn.h @@ -0,0 +1,93 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#ifndef _SDL_x11dyn_h +#define _SDL_x11dyn_h + +#include <X11/Xlib.h> +#include <X11/Xutil.h> +#include <X11/Xatom.h> + +/* Apparently some X11 systems can't include this multiple times... */ +#ifndef SDL_INCLUDED_XLIBINT_H +#define SDL_INCLUDED_XLIBINT_H 1 +#include <X11/Xlibint.h> +#endif + +#include <X11/Xproto.h> + +#include "../Xext/extensions/Xext.h" +#include "../Xext/extensions/extutil.h" + +#ifndef NO_SHARED_MEMORY +#include <sys/ipc.h> +#include <sys/shm.h> +#include <X11/extensions/XShm.h> +#endif + +#if SDL_VIDEO_DRIVER_X11_XRANDR +#include <X11/extensions/Xrandr.h> +#endif + +/* + * When using the "dynamic X11" functionality, we duplicate all the Xlib + * symbols that would be referenced by SDL inside of SDL itself. + * These duplicated symbols just serve as passthroughs to the functions + * in Xlib, that was dynamically loaded. + * + * This allows us to use Xlib as-is when linking against it directly, but + * also handles all the strange cases where there was code in the Xlib + * headers that may or may not exist or vary on a given platform. + */ +#ifdef __cplusplus +extern "C" { +#endif + +/* evil function signatures... */ +typedef Bool (*SDL_X11_XESetWireToEventRetType)(Display*,XEvent*,xEvent*); +typedef int (*SDL_X11_XSynchronizeRetType)(Display*); +typedef Status (*SDL_X11_XESetEventToWireRetType)(Display*,XEvent*,xEvent*); + +int SDL_X11_LoadSymbols(void); +void SDL_X11_UnloadSymbols(void); + +/* That's really annoying...make this a function pointer no matter what. */ +#ifdef X_HAVE_UTF8_STRING +extern XIC (*pXCreateIC)(XIM,...); +extern char *(*pXGetICValues)(XIC, ...); +#endif + +/* These SDL_X11_HAVE_* flags are here whether you have dynamic X11 or not. */ +#define SDL_X11_MODULE(modname) extern int SDL_X11_HAVE_##modname; +#define SDL_X11_SYM(rc,fn,params,args,ret) +#include "SDL_x11sym.h" +#undef SDL_X11_MODULE +#undef SDL_X11_SYM + + +#ifdef __cplusplus +} +#endif + +#endif /* !defined _SDL_x11dyn_h */ + diff --git a/3rdparty/SDL/src/video/x11/SDL_x11events.c b/3rdparty/SDL/src/video/x11/SDL_x11events.c new file mode 100644 index 0000000..559a001 --- /dev/null +++ b/3rdparty/SDL/src/video/x11/SDL_x11events.c @@ -0,0 +1,1414 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* Handle the event stream, converting X11 events into SDL events */ + +#include <setjmp.h> +#include <X11/Xlib.h> +#include <X11/Xutil.h> +#include <X11/keysym.h> +#ifdef __SVR4 +#include <X11/Sunkeysym.h> +#endif +#include <sys/types.h> +#include <sys/time.h> +#include <unistd.h> + +#include "SDL_timer.h" +#include "SDL_syswm.h" +#include "../SDL_sysvideo.h" +#include "../../events/SDL_sysevents.h" +#include "../../events/SDL_events_c.h" +#include "SDL_x11video.h" +#include "SDL_x11dga_c.h" +#include "SDL_x11modes_c.h" +#include "SDL_x11image_c.h" +#include "SDL_x11gamma_c.h" +#include "SDL_x11wm_c.h" +#include "SDL_x11mouse_c.h" +#include "SDL_x11events_c.h" + + +/* Define this if you want to debug X11 events */ +/*#define DEBUG_XEVENTS*/ + +/* The translation tables from an X11 keysym to a SDL keysym */ +static SDLKey ODD_keymap[256]; +static SDLKey MISC_keymap[256]; +SDLKey X11_TranslateKeycode(Display *display, KeyCode kc); + +/* + Pending resize target for ConfigureNotify (so outdated events don't + cause inappropriate resize events) +*/ +int X11_PendingConfigureNotifyWidth = -1; +int X11_PendingConfigureNotifyHeight = -1; + +#ifdef X_HAVE_UTF8_STRING +Uint32 Utf8ToUcs4(const Uint8 *utf8) +{ + Uint32 c; + int i = 1; + int noOctets = 0; + int firstOctetMask = 0; + unsigned char firstOctet = utf8[0]; + if (firstOctet < 0x80) { + /* + Characters in the range: + 00000000 to 01111111 (ASCII Range) + are stored in one octet: + 0xxxxxxx (The same as its ASCII representation) + The least 6 significant bits of the first octet is the most 6 significant nonzero bits + of the UCS4 representation. + */ + noOctets = 1; + firstOctetMask = 0x7F; /* 0(1111111) - The most significant bit is ignored */ + } else if ((firstOctet & 0xE0) /* get the most 3 significant bits by AND'ing with 11100000 */ + == 0xC0 ) { /* see if those 3 bits are 110. If so, the char is in this range */ + /* + Characters in the range: + 00000000 10000000 to 00000111 11111111 + are stored in two octets: + 110xxxxx 10xxxxxx + The least 5 significant bits of the first octet is the most 5 significant nonzero bits + of the UCS4 representation. + */ + noOctets = 2; + firstOctetMask = 0x1F; /* 000(11111) - The most 3 significant bits are ignored */ + } else if ((firstOctet & 0xF0) /* get the most 4 significant bits by AND'ing with 11110000 */ + == 0xE0) { /* see if those 4 bits are 1110. If so, the char is in this range */ + /* + Characters in the range: + 00001000 00000000 to 11111111 11111111 + are stored in three octets: + 1110xxxx 10xxxxxx 10xxxxxx + The least 4 significant bits of the first octet is the most 4 significant nonzero bits + of the UCS4 representation. + */ + noOctets = 3; + firstOctetMask = 0x0F; /* 0000(1111) - The most 4 significant bits are ignored */ + } else if ((firstOctet & 0xF8) /* get the most 5 significant bits by AND'ing with 11111000 */ + == 0xF0) { /* see if those 5 bits are 11110. If so, the char is in this range */ + /* + Characters in the range: + 00000001 00000000 00000000 to 00011111 11111111 11111111 + are stored in four octets: + 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx + The least 3 significant bits of the first octet is the most 3 significant nonzero bits + of the UCS4 representation. + */ + noOctets = 4; + firstOctetMask = 0x07; /* 11110(111) - The most 5 significant bits are ignored */ + } else if ((firstOctet & 0xFC) /* get the most 6 significant bits by AND'ing with 11111100 */ + == 0xF8) { /* see if those 6 bits are 111110. If so, the char is in this range */ + /* + Characters in the range: + 00000000 00100000 00000000 00000000 to + 00000011 11111111 11111111 11111111 + are stored in five octets: + 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx + The least 2 significant bits of the first octet is the most 2 significant nonzero bits + of the UCS4 representation. + */ + noOctets = 5; + firstOctetMask = 0x03; /* 111110(11) - The most 6 significant bits are ignored */ + } else if ((firstOctet & 0xFE) /* get the most 7 significant bits by AND'ing with 11111110 */ + == 0xFC) { /* see if those 7 bits are 1111110. If so, the char is in this range */ + /* + Characters in the range: + 00000100 00000000 00000000 00000000 to + 01111111 11111111 11111111 11111111 + are stored in six octets: + 1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx + The least significant bit of the first octet is the most significant nonzero bit + of the UCS4 representation. + */ + noOctets = 6; + firstOctetMask = 0x01; /* 1111110(1) - The most 7 significant bits are ignored */ + } else + return 0; /* The given chunk is not a valid UTF-8 encoded Unicode character */ + + /* + The least noOctets significant bits of the first octet is the most 2 significant nonzero bits + of the UCS4 representation. + The first 6 bits of the UCS4 representation is the least 8-noOctets-1 significant bits of + firstOctet if the character is not ASCII. If so, it's the least 7 significant bits of firstOctet. + This done by AND'ing firstOctet with its mask to trim the bits used for identifying the + number of continuing octets (if any) and leave only the free bits (the x's) + Sample: + 1-octet: 0xxxxxxx & 01111111 = 0xxxxxxx + 2-octets: 110xxxxx & 00011111 = 000xxxxx + */ + c = firstOctet & firstOctetMask; + + /* Now, start filling c.ucs4 with the bits from the continuing octets from utf8. */ + for (i = 1; i < noOctets; i++) { + /* A valid continuing octet is of the form 10xxxxxx */ + if ((utf8[i] & 0xC0) /* get the most 2 significant bits by AND'ing with 11000000 */ + != 0x80) /* see if those 2 bits are 10. If not, the is a malformed sequence. */ + /*The given chunk is a partial sequence at the end of a string that could + begin a valid character */ + return 0; + + /* Make room for the next 6-bits */ + c <<= 6; + + /* + Take only the least 6 significance bits of the current octet (utf8[i]) and fill the created room + of c.ucs4 with them. + This done by AND'ing utf8[i] with 00111111 and the OR'ing the result with c.ucs4. + */ + c |= utf8[i] & 0x3F; + } + return c; +} + +/* Given a UTF-8 encoded string pointed to by utf8 of length length in + bytes, returns the corresponding UTF-16 encoded string in the + buffer pointed to by utf16. The maximum number of UTF-16 encoding + units (i.e., Unit16s) allowed in the buffer is specified in + utf16_max_length. The return value is the number of UTF-16 + encoding units placed in the output buffer pointed to by utf16. + + In case of an error, -1 is returned, leaving some unusable partial + results in the output buffer. + + The caller must estimate the size of utf16 buffer by itself before + calling this function. Insufficient output buffer is considered as + an error, and once an error occured, this function doesn't give any + clue how large the result will be. + + The error cases include following: + + - Invalid byte sequences were in the input UTF-8 bytes. The caller + has no way to know what point in the input buffer was the + errornous byte. + + - The input contained a character (a valid UTF-8 byte sequence) + whose scalar value exceeded the range that UTF-16 can represent + (i.e., characters whose Unicode scalar value above 0x110000). + + - The output buffer has no enough space to hold entire utf16 data. + + Please note: + + - '\0'-termination is not assumed both on the input UTF-8 string + and on the output UTF-16 string; any legal zero byte in the input + UTF-8 string will be converted to a 16-bit zero in output. As a + side effect, the last UTF-16 encoding unit stored in the output + buffer will have a non-zero value if the input UTF-8 was not + '\0'-terminated. + + - UTF-8 aliases are *not* considered as an error. They are + converted to UTF-16. For example, 0xC0 0xA0, 0xE0 0x80 0xA0, + and 0xF0 0x80 0x80 0xA0 are all mapped to a single UTF-16 + encoding unit 0x0020. + + - Three byte UTF-8 sequences whose value corresponds to a surrogate + code or other reserved scalar value are not considered as an + error either. They may cause an invalid UTF-16 data (e.g., those + containing unpaired surrogates). + +*/ + +static int Utf8ToUtf16(const Uint8 *utf8, const int utf8_length, Uint16 *utf16, const int utf16_max_length) { + + /* p moves over the output buffer. max_ptr points to the next to the last slot of the buffer. */ + Uint16 *p = utf16; + Uint16 const *const max_ptr = utf16 + utf16_max_length; + + /* end_of_input points to the last byte of input as opposed to the next to the last byte. */ + Uint8 const *const end_of_input = utf8 + utf8_length - 1; + + while (utf8 <= end_of_input) { + Uint8 const c = *utf8; + if (p >= max_ptr) { + /* No more output space. */ + return -1; + } + if (c < 0x80) { + /* One byte ASCII. */ + *p++ = c; + utf8 += 1; + } else if (c < 0xC0) { + /* Follower byte without preceeding leader bytes. */ + return -1; + } else if (c < 0xE0) { + /* Two byte sequence. We need one follower byte. */ + if (end_of_input - utf8 < 1 || (((utf8[1] ^ 0x80)) & 0xC0)) { + return -1; + } + *p++ = (Uint16)(0xCF80 + (c << 6) + utf8[1]); + utf8 += 2; + } else if (c < 0xF0) { + /* Three byte sequence. We need two follower byte. */ + if (end_of_input - utf8 < 2 || (((utf8[1] ^ 0x80) | (utf8[2] ^ 0x80)) & 0xC0)) { + return -1; + } + *p++ = (Uint16)(0xDF80 + (c << 12) + (utf8[1] << 6) + utf8[2]); + utf8 += 3; + } else if (c < 0xF8) { + int plane; + /* Four byte sequence. We need three follower bytes. */ + if (end_of_input - utf8 < 3 || (((utf8[1] ^ 0x80) | (utf8[2] ^0x80) | (utf8[3] ^ 0x80)) & 0xC0)) { + return -1; + } + plane = (-0xC8 + (c << 2) + (utf8[1] >> 4)); + if (plane == 0) { + /* This four byte sequence is an alias that + corresponds to a Unicode scalar value in BMP. + It fits in an UTF-16 encoding unit. */ + *p++ = (Uint16)(0xDF80 + (utf8[1] << 12) + (utf8[2] << 6) + utf8[3]); + } else if (plane <= 16) { + /* This is a legal four byte sequence that corresponds to a surrogate pair. */ + if (p + 1 >= max_ptr) { + /* No enough space on the output buffer for the pair. */ + return -1; + } + *p++ = (Uint16)(0xE5B8 + (c << 8) + (utf8[1] << 2) + (utf8[2] >> 4)); + *p++ = (Uint16)(0xDB80 + ((utf8[2] & 0x0F) << 6) + utf8[3]); + } else { + /* This four byte sequence is out of UTF-16 code space. */ + return -1; + } + utf8 += 4; + } else { + /* Longer sequence or unused byte. */ + return -1; + } + } + return p - utf16; +} + +#endif + +/* Check to see if this is a repeated key. + (idea shamelessly lifted from GII -- thanks guys! :) + */ +static int X11_KeyRepeat(Display *display, XEvent *event) +{ + XEvent peekevent; + int repeated; + + repeated = 0; + if ( XPending(display) ) { + XPeekEvent(display, &peekevent); + if ( (peekevent.type == KeyPress) && + (peekevent.xkey.keycode == event->xkey.keycode) && + ((peekevent.xkey.time-event->xkey.time) < 2) ) { + repeated = 1; + XNextEvent(display, &peekevent); + } + } + return(repeated); +} + +/* Note: The X server buffers and accumulates mouse motion events, so + the motion event generated by the warp may not appear exactly as we + expect it to. We work around this (and improve performance) by only + warping the pointer when it reaches the edge, and then wait for it. +*/ +#define MOUSE_FUDGE_FACTOR 8 + +static __inline__ int X11_WarpedMotion(_THIS, XEvent *xevent) +{ + int w, h, i; + int deltax, deltay; + int posted; + + w = SDL_VideoSurface->w; + h = SDL_VideoSurface->h; + deltax = xevent->xmotion.x - mouse_last.x; + deltay = xevent->xmotion.y - mouse_last.y; +#ifdef DEBUG_MOTION + printf("Warped mouse motion: %d,%d\n", deltax, deltay); +#endif + mouse_last.x = xevent->xmotion.x; + mouse_last.y = xevent->xmotion.y; + posted = SDL_PrivateMouseMotion(0, 1, deltax, deltay); + + if ( (xevent->xmotion.x < MOUSE_FUDGE_FACTOR) || + (xevent->xmotion.x > (w-MOUSE_FUDGE_FACTOR)) || + (xevent->xmotion.y < MOUSE_FUDGE_FACTOR) || + (xevent->xmotion.y > (h-MOUSE_FUDGE_FACTOR)) ) { + /* Get the events that have accumulated */ + while ( XCheckTypedEvent(SDL_Display, MotionNotify, xevent) ) { + deltax = xevent->xmotion.x - mouse_last.x; + deltay = xevent->xmotion.y - mouse_last.y; +#ifdef DEBUG_MOTION + printf("Extra mouse motion: %d,%d\n", deltax, deltay); +#endif + mouse_last.x = xevent->xmotion.x; + mouse_last.y = xevent->xmotion.y; + posted += SDL_PrivateMouseMotion(0, 1, deltax, deltay); + } + mouse_last.x = w/2; + mouse_last.y = h/2; + XWarpPointer(SDL_Display, None, SDL_Window, 0, 0, 0, 0, + mouse_last.x, mouse_last.y); + for ( i=0; i<10; ++i ) { + XMaskEvent(SDL_Display, PointerMotionMask, xevent); + if ( (xevent->xmotion.x > + (mouse_last.x-MOUSE_FUDGE_FACTOR)) && + (xevent->xmotion.x < + (mouse_last.x+MOUSE_FUDGE_FACTOR)) && + (xevent->xmotion.y > + (mouse_last.y-MOUSE_FUDGE_FACTOR)) && + (xevent->xmotion.y < + (mouse_last.y+MOUSE_FUDGE_FACTOR)) ) { + break; + } +#ifdef DEBUG_XEVENTS + printf("Lost mouse motion: %d,%d\n", xevent->xmotion.x, xevent->xmotion.y); +#endif + } +#ifdef DEBUG_XEVENTS + if ( i == 10 ) { + printf("Warning: didn't detect mouse warp motion\n"); + } +#endif + } + return(posted); +} + +static int X11_DispatchEvent(_THIS) +{ + int posted; + XEvent xevent; + + SDL_memset(&xevent, '\0', sizeof (XEvent)); /* valgrind fix. --ryan. */ + XNextEvent(SDL_Display, &xevent); + + /* Discard KeyRelease and KeyPress events generated by auto-repeat. + We need to do it before passing event to XFilterEvent. Otherwise, + KeyRelease aware IMs are confused... */ + if ( xevent.type == KeyRelease + && X11_KeyRepeat(SDL_Display, &xevent) ) { + return 0; + } + +#ifdef X_HAVE_UTF8_STRING + /* If we are translating with IM, we need to pass all events + to XFilterEvent, and discard those filtered events immediately. */ + if ( SDL_TranslateUNICODE + && SDL_IM != NULL + && XFilterEvent(&xevent, None) ) { + return 0; + } +#endif + + posted = 0; + switch (xevent.type) { + + /* Gaining mouse coverage? */ + case EnterNotify: { +#ifdef DEBUG_XEVENTS +printf("EnterNotify! (%d,%d)\n", xevent.xcrossing.x, xevent.xcrossing.y); +if ( xevent.xcrossing.mode == NotifyGrab ) +printf("Mode: NotifyGrab\n"); +if ( xevent.xcrossing.mode == NotifyUngrab ) +printf("Mode: NotifyUngrab\n"); +#endif + if ( this->input_grab == SDL_GRAB_OFF ) { + posted = SDL_PrivateAppActive(1, SDL_APPMOUSEFOCUS); + } + posted = SDL_PrivateMouseMotion(0, 0, + xevent.xcrossing.x, + xevent.xcrossing.y); + } + break; + + /* Losing mouse coverage? */ + case LeaveNotify: { +#ifdef DEBUG_XEVENTS +printf("LeaveNotify! (%d,%d)\n", xevent.xcrossing.x, xevent.xcrossing.y); +if ( xevent.xcrossing.mode == NotifyGrab ) +printf("Mode: NotifyGrab\n"); +if ( xevent.xcrossing.mode == NotifyUngrab ) +printf("Mode: NotifyUngrab\n"); +#endif + if ( (xevent.xcrossing.mode != NotifyGrab) && + (xevent.xcrossing.mode != NotifyUngrab) && + (xevent.xcrossing.detail != NotifyInferior) ) { + if ( this->input_grab == SDL_GRAB_OFF ) { + posted = SDL_PrivateAppActive(0, SDL_APPMOUSEFOCUS); + } else { + posted = SDL_PrivateMouseMotion(0, 0, + xevent.xcrossing.x, + xevent.xcrossing.y); + } + } + } + break; + + /* Gaining input focus? */ + case FocusIn: { +#ifdef DEBUG_XEVENTS +printf("FocusIn!\n"); +#endif + posted = SDL_PrivateAppActive(1, SDL_APPINPUTFOCUS); + +#ifdef X_HAVE_UTF8_STRING + if ( SDL_IC != NULL ) { + XSetICFocus(SDL_IC); + } +#endif + /* Queue entry into fullscreen mode */ + switch_waiting = 0x01 | SDL_FULLSCREEN; + switch_time = SDL_GetTicks() + 1500; + } + break; + + /* Losing input focus? */ + case FocusOut: { +#ifdef DEBUG_XEVENTS +printf("FocusOut!\n"); +#endif + posted = SDL_PrivateAppActive(0, SDL_APPINPUTFOCUS); + +#ifdef X_HAVE_UTF8_STRING + if ( SDL_IC != NULL ) { + XUnsetICFocus(SDL_IC); + } +#endif + /* Queue leaving fullscreen mode */ + switch_waiting = 0x01; + switch_time = SDL_GetTicks() + 200; + } + break; + +#ifdef X_HAVE_UTF8_STRING + /* Some IM requires MappingNotify to be passed to + XRefreshKeyboardMapping by the app. */ + case MappingNotify: { + XRefreshKeyboardMapping(&xevent.xmapping); + } + break; +#endif /* X_HAVE_UTF8_STRING */ + + /* Generated upon EnterWindow and FocusIn */ + case KeymapNotify: { +#ifdef DEBUG_XEVENTS +printf("KeymapNotify!\n"); +#endif + X11_SetKeyboardState(SDL_Display, xevent.xkeymap.key_vector); + } + break; + + /* Mouse motion? */ + case MotionNotify: { + if ( SDL_VideoSurface ) { + if ( mouse_relative ) { + if ( using_dga & DGA_MOUSE ) { +#ifdef DEBUG_MOTION + printf("DGA motion: %d,%d\n", xevent.xmotion.x_root, xevent.xmotion.y_root); +#endif + posted = SDL_PrivateMouseMotion(0, 1, + xevent.xmotion.x_root, + xevent.xmotion.y_root); + } else { + posted = X11_WarpedMotion(this,&xevent); + } + } else { +#ifdef DEBUG_MOTION + printf("X11 motion: %d,%d\n", xevent.xmotion.x, xevent.xmotion.y); +#endif + posted = SDL_PrivateMouseMotion(0, 0, + xevent.xmotion.x, + xevent.xmotion.y); + } + } + } + break; + + /* Mouse button press? */ + case ButtonPress: { + posted = SDL_PrivateMouseButton(SDL_PRESSED, + xevent.xbutton.button, 0, 0); + } + break; + + /* Mouse button release? */ + case ButtonRelease: { + posted = SDL_PrivateMouseButton(SDL_RELEASED, + xevent.xbutton.button, 0, 0); + } + break; + + /* Key press? */ + case KeyPress: { + SDL_keysym keysym; + KeyCode keycode = xevent.xkey.keycode; + +#ifdef DEBUG_XEVENTS +printf("KeyPress (X11 keycode = 0x%X)\n", xevent.xkey.keycode); +#endif + /* If we're not doing translation, we're done! */ + if ( !SDL_TranslateUNICODE ) { + /* Get the translated SDL virtual keysym and put it on the queue.*/ + keysym.scancode = keycode; + keysym.sym = X11_TranslateKeycode(SDL_Display, keycode); + keysym.mod = KMOD_NONE; + keysym.unicode = 0; + posted = SDL_PrivateKeyboard(SDL_PRESSED, &keysym); + break; + } + + /* Look up the translated value for the key event */ +#ifdef X_HAVE_UTF8_STRING + if ( SDL_IC != NULL ) { + Status status; + KeySym xkeysym; + int i; + /* A UTF-8 character can be at most 6 bytes */ + /* ... It's true, but Xutf8LookupString can + return more than one characters. Moreover, + the spec. put no upper bound, so we should + be ready for longer strings. */ + char keybuf[32]; + char *keydata = keybuf; + int count; + Uint16 utf16buf[32]; + Uint16 *utf16data = utf16buf; + int utf16size; + int utf16length; + + count = Xutf8LookupString(SDL_IC, &xevent.xkey, keydata, sizeof(keybuf), &xkeysym, &status); + if (XBufferOverflow == status) { + /* The IM has just generated somewhat long + string. We need a longer buffer in this + case. */ + keydata = SDL_malloc(count); + if ( keydata == NULL ) { + SDL_OutOfMemory(); + break; + } + count = Xutf8LookupString(SDL_IC, &xevent.xkey, keydata, count, &xkeysym, &status); + } + + switch (status) { + + case XBufferOverflow: { + /* Oops! We have allocated the bytes as + requested by Xutf8LookupString, so the + length of the buffer must be + sufficient. This case should never + happen! */ + SDL_SetError("Xutf8LookupString indicated a double buffer overflow!"); + break; + } + + case XLookupChars: + case XLookupBoth: { + if (0 == count) { + break; + } + + /* We got a converted string from IM. Make + sure to deliver all characters to the + application as SDL events. Note that + an SDL event can only carry one UTF-16 + encoding unit, and a surrogate pair is + delivered as two SDL events. I guess + this behaviour is probably _imported_ + from Windows or MacOS. To do so, we need + to convert the UTF-8 data into UTF-16 + data (not UCS4/UTF-32!). We need an + estimate of the number of UTF-16 encoding + units here. The worst case is pure ASCII + string. Assume so. */ + /* In 1.3 SDL may have a text event instead, that + carries the whole UTF-8 string with it. */ + utf16size = count * sizeof(Uint16); + if (utf16size > sizeof(utf16buf)) { + utf16data = (Uint16 *) SDL_malloc(utf16size); + if (utf16data == NULL) { + SDL_OutOfMemory(); + break; + } + } + utf16length = Utf8ToUtf16((Uint8 *)keydata, count, utf16data, utf16size); + if (utf16length < 0) { + /* The keydata contained an invalid byte + sequence. It should be a bug of the IM + or Xlib... */ + SDL_SetError("Oops! Xutf8LookupString returned an invalid UTF-8 sequence!"); + break; + } + + /* Deliver all UTF-16 encoding units. At + this moment, SDL event queue has a + fixed size (128 events), and an SDL + event can hold just one UTF-16 encoding + unit. So, if we receive more than 128 + UTF-16 encoding units from a commit, + exceeded characters will be lost. */ + for (i = 0; i < utf16length - 1; i++) { + keysym.scancode = 0; + keysym.sym = SDLK_UNKNOWN; + keysym.mod = KMOD_NONE; + keysym.unicode = utf16data[i]; + posted = SDL_PrivateKeyboard(SDL_PRESSED, &keysym); + } + /* The keysym for the last character carries the + scancode and symbol that corresponds to the X11 + keycode. */ + if (utf16length > 0) { + keysym.scancode = keycode; + keysym.sym = (keycode ? X11_TranslateKeycode(SDL_Display, keycode) : 0); + keysym.mod = KMOD_NONE; + keysym.unicode = utf16data[utf16length - 1]; + posted = SDL_PrivateKeyboard(SDL_PRESSED, &keysym); + } + break; + } + + case XLookupKeySym: { + /* I'm not sure whether it is possible that + a zero keycode makes XLookupKeySym + status. What I'm sure is that a + combination of a zero scan code and a non + zero sym makes SDL_PrivateKeyboard + strange state... So, just discard it. + If this doesn't work, I'm receiving bug + reports, and I can know under what + condition this case happens. */ + if (keycode) { + keysym.scancode = keycode; + keysym.sym = X11_TranslateKeycode(SDL_Display, keycode); + keysym.mod = KMOD_NONE; + keysym.unicode = 0; + posted = SDL_PrivateKeyboard(SDL_PRESSED, &keysym); + } + break; + } + + case XLookupNone: { + /* IM has eaten the event. */ + break; + } + + default: + /* An unknown status from Xutf8LookupString. */ + SDL_SetError("Oops! Xutf8LookupStringreturned an unknown status"); + } + + /* Release dynamic buffers if allocated. */ + if (keydata != NULL && keybuf != keydata) { + SDL_free(keydata); + } + if (utf16data != NULL && utf16buf != utf16data) { + SDL_free(utf16data); + } + } + else +#endif + { + static XComposeStatus state; + char keybuf[32]; + + keysym.scancode = keycode; + keysym.sym = X11_TranslateKeycode(SDL_Display, keycode); + keysym.mod = KMOD_NONE; + keysym.unicode = 0; + if ( XLookupString(&xevent.xkey, + keybuf, sizeof(keybuf), + NULL, &state) ) { + /* + * FIXME: XLookupString() may yield more than one + * character, so we need a mechanism to allow for + * this (perhaps null keypress events with a + * unicode value) + */ + keysym.unicode = (Uint8)keybuf[0]; + } + + posted = SDL_PrivateKeyboard(SDL_PRESSED, &keysym); + } + } + break; + + /* Key release? */ + case KeyRelease: { + SDL_keysym keysym; + KeyCode keycode = xevent.xkey.keycode; + + if (keycode == 0) { + /* There should be no KeyRelease for keycode == 0, + since it is a notification from IM but a real + keystroke. */ + /* We need to emit some diagnostic message here. */ + break; + } + +#ifdef DEBUG_XEVENTS +printf("KeyRelease (X11 keycode = 0x%X)\n", xevent.xkey.keycode); +#endif + + /* Get the translated SDL virtual keysym */ + keysym.scancode = keycode; + keysym.sym = X11_TranslateKeycode(SDL_Display, keycode); + keysym.mod = KMOD_NONE; + keysym.unicode = 0; + + posted = SDL_PrivateKeyboard(SDL_RELEASED, &keysym); + } + break; + + /* Have we been iconified? */ + case UnmapNotify: { +#ifdef DEBUG_XEVENTS +printf("UnmapNotify!\n"); +#endif + /* If we're active, make ourselves inactive */ + if ( SDL_GetAppState() & SDL_APPACTIVE ) { + /* Swap out the gamma before we go inactive */ + X11_SwapVidModeGamma(this); + + /* Send an internal deactivate event */ + posted = SDL_PrivateAppActive(0, + SDL_APPACTIVE|SDL_APPINPUTFOCUS); + } + } + break; + + /* Have we been restored? */ + case MapNotify: { +#ifdef DEBUG_XEVENTS +printf("MapNotify!\n"); +#endif + /* If we're not active, make ourselves active */ + if ( !(SDL_GetAppState() & SDL_APPACTIVE) ) { + /* Send an internal activate event */ + posted = SDL_PrivateAppActive(1, SDL_APPACTIVE); + + /* Now that we're active, swap the gamma back */ + X11_SwapVidModeGamma(this); + } + + if ( SDL_VideoSurface && + (SDL_VideoSurface->flags & SDL_FULLSCREEN) ) { + X11_EnterFullScreen(this); + } else { + X11_GrabInputNoLock(this, this->input_grab); + } + X11_CheckMouseModeNoLock(this); + + if ( SDL_VideoSurface ) { + X11_RefreshDisplay(this); + } + } + break; + + /* Have we been resized or moved? */ + case ConfigureNotify: { +#ifdef DEBUG_XEVENTS +printf("ConfigureNotify! (resize: %dx%d)\n", xevent.xconfigure.width, xevent.xconfigure.height); +#endif + if ((X11_PendingConfigureNotifyWidth != -1) && + (X11_PendingConfigureNotifyHeight != -1)) { + if ((xevent.xconfigure.width != X11_PendingConfigureNotifyWidth) && + (xevent.xconfigure.height != X11_PendingConfigureNotifyHeight)) { + /* Event is from before the resize, so ignore. */ + break; + } + X11_PendingConfigureNotifyWidth = -1; + X11_PendingConfigureNotifyHeight = -1; + } + if ( SDL_VideoSurface ) { + if ((xevent.xconfigure.width != SDL_VideoSurface->w) || + (xevent.xconfigure.height != SDL_VideoSurface->h)) { + /* FIXME: Find a better fix for the bug with KDE 1.2 */ + if ( ! ((xevent.xconfigure.width == 32) && + (xevent.xconfigure.height == 32)) ) { + SDL_PrivateResize(xevent.xconfigure.width, + xevent.xconfigure.height); + } + } else { + /* OpenGL windows need to know about the change */ + if ( SDL_VideoSurface->flags & SDL_OPENGL ) { + SDL_PrivateExpose(); + } + } + } + } + break; + + /* Have we been requested to quit (or another client message?) */ + case ClientMessage: { + if ( (xevent.xclient.format == 32) && + (xevent.xclient.data.l[0] == WM_DELETE_WINDOW) ) + { + posted = SDL_PrivateQuit(); + } else + if ( SDL_ProcessEvents[SDL_SYSWMEVENT] == SDL_ENABLE ) { + SDL_SysWMmsg wmmsg; + + SDL_VERSION(&wmmsg.version); + wmmsg.subsystem = SDL_SYSWM_X11; + wmmsg.event.xevent = xevent; + posted = SDL_PrivateSysWMEvent(&wmmsg); + } + } + break; + + /* Do we need to refresh ourselves? */ + case Expose: { +#ifdef DEBUG_XEVENTS +printf("Expose (count = %d)\n", xevent.xexpose.count); +#endif + if ( SDL_VideoSurface && (xevent.xexpose.count == 0) ) { + X11_RefreshDisplay(this); + } + } + break; + + default: { +#ifdef DEBUG_XEVENTS +printf("Unhandled event %d\n", xevent.type); +#endif + /* Only post the event if we're watching for it */ + if ( SDL_ProcessEvents[SDL_SYSWMEVENT] == SDL_ENABLE ) { + SDL_SysWMmsg wmmsg; + + SDL_VERSION(&wmmsg.version); + wmmsg.subsystem = SDL_SYSWM_X11; + wmmsg.event.xevent = xevent; + posted = SDL_PrivateSysWMEvent(&wmmsg); + } + } + break; + } + return(posted); +} + +/* Ack! XPending() actually performs a blocking read if no events available */ +int X11_Pending(Display *display) +{ + /* Flush the display connection and look to see if events are queued */ + XFlush(display); + if ( XEventsQueued(display, QueuedAlready) ) { + return(1); + } + + /* More drastic measures are required -- see if X is ready to talk */ + { + static struct timeval zero_time; /* static == 0 */ + int x11_fd; + fd_set fdset; + + x11_fd = ConnectionNumber(display); + FD_ZERO(&fdset); + FD_SET(x11_fd, &fdset); + if ( select(x11_fd+1, &fdset, NULL, NULL, &zero_time) == 1 ) { + return(XPending(display)); + } + } + + /* Oh well, nothing is ready .. */ + return(0); +} + +void X11_PumpEvents(_THIS) +{ + int pending; + + /* Update activity every five seconds to prevent screensaver. --ryan. */ + if (!allow_screensaver) { + static Uint32 screensaverTicks; + Uint32 nowTicks = SDL_GetTicks(); + if ((nowTicks - screensaverTicks) > 5000) { + XResetScreenSaver(SDL_Display); + screensaverTicks = nowTicks; + } + } + + /* Keep processing pending events */ + pending = 0; + while ( X11_Pending(SDL_Display) ) { + X11_DispatchEvent(this); + ++pending; + } + if ( switch_waiting ) { + Uint32 now; + + now = SDL_GetTicks(); + if ( pending || !SDL_VideoSurface ) { + /* Try again later... */ + if ( switch_waiting & SDL_FULLSCREEN ) { + switch_time = now + 1500; + } else { + switch_time = now + 200; + } + } else if ( (int)(switch_time-now) <= 0 ) { + Uint32 go_fullscreen; + + go_fullscreen = switch_waiting & SDL_FULLSCREEN; + switch_waiting = 0; + if ( SDL_VideoSurface->flags & SDL_FULLSCREEN ) { + if ( go_fullscreen ) { + X11_EnterFullScreen(this); + } else { + X11_LeaveFullScreen(this); + } + } + /* Handle focus in/out when grabbed */ + if ( go_fullscreen ) { + X11_GrabInputNoLock(this, this->input_grab); + } else { + X11_GrabInputNoLock(this, SDL_GRAB_OFF); + } + X11_CheckMouseModeNoLock(this); + } + } +} + +void X11_InitKeymap(void) +{ + int i; + + /* Odd keys used in international keyboards */ + for ( i=0; i<SDL_arraysize(ODD_keymap); ++i ) + ODD_keymap[i] = SDLK_UNKNOWN; + + /* Some of these might be mappable to an existing SDLK_ code */ + ODD_keymap[XK_dead_grave&0xFF] = SDLK_COMPOSE; + ODD_keymap[XK_dead_acute&0xFF] = SDLK_COMPOSE; + ODD_keymap[XK_dead_tilde&0xFF] = SDLK_COMPOSE; + ODD_keymap[XK_dead_macron&0xFF] = SDLK_COMPOSE; + ODD_keymap[XK_dead_breve&0xFF] = SDLK_COMPOSE; + ODD_keymap[XK_dead_abovedot&0xFF] = SDLK_COMPOSE; + ODD_keymap[XK_dead_diaeresis&0xFF] = SDLK_COMPOSE; + ODD_keymap[XK_dead_abovering&0xFF] = SDLK_COMPOSE; + ODD_keymap[XK_dead_doubleacute&0xFF] = SDLK_COMPOSE; + ODD_keymap[XK_dead_caron&0xFF] = SDLK_COMPOSE; + ODD_keymap[XK_dead_cedilla&0xFF] = SDLK_COMPOSE; + ODD_keymap[XK_dead_ogonek&0xFF] = SDLK_COMPOSE; + ODD_keymap[XK_dead_iota&0xFF] = SDLK_COMPOSE; + ODD_keymap[XK_dead_voiced_sound&0xFF] = SDLK_COMPOSE; + ODD_keymap[XK_dead_semivoiced_sound&0xFF] = SDLK_COMPOSE; + ODD_keymap[XK_dead_belowdot&0xFF] = SDLK_COMPOSE; +#ifdef XK_dead_hook + ODD_keymap[XK_dead_hook&0xFF] = SDLK_COMPOSE; +#endif +#ifdef XK_dead_horn + ODD_keymap[XK_dead_horn&0xFF] = SDLK_COMPOSE; +#endif + +#ifdef XK_dead_circumflex + /* These X keysyms have 0xFE as the high byte */ + ODD_keymap[XK_dead_circumflex&0xFF] = SDLK_CARET; +#endif +#ifdef XK_ISO_Level3_Shift + ODD_keymap[XK_ISO_Level3_Shift&0xFF] = SDLK_MODE; /* "Alt Gr" key */ +#endif + + /* Map the miscellaneous keys */ + for ( i=0; i<SDL_arraysize(MISC_keymap); ++i ) + MISC_keymap[i] = SDLK_UNKNOWN; + + /* These X keysyms have 0xFF as the high byte */ + MISC_keymap[XK_BackSpace&0xFF] = SDLK_BACKSPACE; + MISC_keymap[XK_Tab&0xFF] = SDLK_TAB; + MISC_keymap[XK_Clear&0xFF] = SDLK_CLEAR; + MISC_keymap[XK_Return&0xFF] = SDLK_RETURN; + MISC_keymap[XK_Pause&0xFF] = SDLK_PAUSE; + MISC_keymap[XK_Escape&0xFF] = SDLK_ESCAPE; + MISC_keymap[XK_Delete&0xFF] = SDLK_DELETE; + + MISC_keymap[XK_KP_0&0xFF] = SDLK_KP0; /* Keypad 0-9 */ + MISC_keymap[XK_KP_1&0xFF] = SDLK_KP1; + MISC_keymap[XK_KP_2&0xFF] = SDLK_KP2; + MISC_keymap[XK_KP_3&0xFF] = SDLK_KP3; + MISC_keymap[XK_KP_4&0xFF] = SDLK_KP4; + MISC_keymap[XK_KP_5&0xFF] = SDLK_KP5; + MISC_keymap[XK_KP_6&0xFF] = SDLK_KP6; + MISC_keymap[XK_KP_7&0xFF] = SDLK_KP7; + MISC_keymap[XK_KP_8&0xFF] = SDLK_KP8; + MISC_keymap[XK_KP_9&0xFF] = SDLK_KP9; + MISC_keymap[XK_KP_Insert&0xFF] = SDLK_KP0; + MISC_keymap[XK_KP_End&0xFF] = SDLK_KP1; + MISC_keymap[XK_KP_Down&0xFF] = SDLK_KP2; + MISC_keymap[XK_KP_Page_Down&0xFF] = SDLK_KP3; + MISC_keymap[XK_KP_Left&0xFF] = SDLK_KP4; + MISC_keymap[XK_KP_Begin&0xFF] = SDLK_KP5; + MISC_keymap[XK_KP_Right&0xFF] = SDLK_KP6; + MISC_keymap[XK_KP_Home&0xFF] = SDLK_KP7; + MISC_keymap[XK_KP_Up&0xFF] = SDLK_KP8; + MISC_keymap[XK_KP_Page_Up&0xFF] = SDLK_KP9; + MISC_keymap[XK_KP_Delete&0xFF] = SDLK_KP_PERIOD; + MISC_keymap[XK_KP_Decimal&0xFF] = SDLK_KP_PERIOD; + MISC_keymap[XK_KP_Divide&0xFF] = SDLK_KP_DIVIDE; + MISC_keymap[XK_KP_Multiply&0xFF] = SDLK_KP_MULTIPLY; + MISC_keymap[XK_KP_Subtract&0xFF] = SDLK_KP_MINUS; + MISC_keymap[XK_KP_Add&0xFF] = SDLK_KP_PLUS; + MISC_keymap[XK_KP_Enter&0xFF] = SDLK_KP_ENTER; + MISC_keymap[XK_KP_Equal&0xFF] = SDLK_KP_EQUALS; + + MISC_keymap[XK_Up&0xFF] = SDLK_UP; + MISC_keymap[XK_Down&0xFF] = SDLK_DOWN; + MISC_keymap[XK_Right&0xFF] = SDLK_RIGHT; + MISC_keymap[XK_Left&0xFF] = SDLK_LEFT; + MISC_keymap[XK_Insert&0xFF] = SDLK_INSERT; + MISC_keymap[XK_Home&0xFF] = SDLK_HOME; + MISC_keymap[XK_End&0xFF] = SDLK_END; + MISC_keymap[XK_Page_Up&0xFF] = SDLK_PAGEUP; + MISC_keymap[XK_Page_Down&0xFF] = SDLK_PAGEDOWN; + + MISC_keymap[XK_F1&0xFF] = SDLK_F1; + MISC_keymap[XK_F2&0xFF] = SDLK_F2; + MISC_keymap[XK_F3&0xFF] = SDLK_F3; + MISC_keymap[XK_F4&0xFF] = SDLK_F4; + MISC_keymap[XK_F5&0xFF] = SDLK_F5; + MISC_keymap[XK_F6&0xFF] = SDLK_F6; + MISC_keymap[XK_F7&0xFF] = SDLK_F7; + MISC_keymap[XK_F8&0xFF] = SDLK_F8; + MISC_keymap[XK_F9&0xFF] = SDLK_F9; + MISC_keymap[XK_F10&0xFF] = SDLK_F10; + MISC_keymap[XK_F11&0xFF] = SDLK_F11; + MISC_keymap[XK_F12&0xFF] = SDLK_F12; + MISC_keymap[XK_F13&0xFF] = SDLK_F13; + MISC_keymap[XK_F14&0xFF] = SDLK_F14; + MISC_keymap[XK_F15&0xFF] = SDLK_F15; + + MISC_keymap[XK_Num_Lock&0xFF] = SDLK_NUMLOCK; + MISC_keymap[XK_Caps_Lock&0xFF] = SDLK_CAPSLOCK; + MISC_keymap[XK_Scroll_Lock&0xFF] = SDLK_SCROLLOCK; + MISC_keymap[XK_Shift_R&0xFF] = SDLK_RSHIFT; + MISC_keymap[XK_Shift_L&0xFF] = SDLK_LSHIFT; + MISC_keymap[XK_Control_R&0xFF] = SDLK_RCTRL; + MISC_keymap[XK_Control_L&0xFF] = SDLK_LCTRL; + MISC_keymap[XK_Alt_R&0xFF] = SDLK_RALT; + MISC_keymap[XK_Alt_L&0xFF] = SDLK_LALT; + MISC_keymap[XK_Meta_R&0xFF] = SDLK_RMETA; + MISC_keymap[XK_Meta_L&0xFF] = SDLK_LMETA; + MISC_keymap[XK_Super_L&0xFF] = SDLK_LSUPER; /* Left "Windows" */ + MISC_keymap[XK_Super_R&0xFF] = SDLK_RSUPER; /* Right "Windows */ + MISC_keymap[XK_Mode_switch&0xFF] = SDLK_MODE; /* "Alt Gr" key */ + MISC_keymap[XK_Multi_key&0xFF] = SDLK_COMPOSE; /* Multi-key compose */ + + MISC_keymap[XK_Help&0xFF] = SDLK_HELP; + MISC_keymap[XK_Print&0xFF] = SDLK_PRINT; + MISC_keymap[XK_Sys_Req&0xFF] = SDLK_SYSREQ; + MISC_keymap[XK_Break&0xFF] = SDLK_BREAK; + MISC_keymap[XK_Menu&0xFF] = SDLK_MENU; + MISC_keymap[XK_Hyper_R&0xFF] = SDLK_MENU; /* Windows "Menu" key */ +} + +/* Get the translated SDL virtual keysym */ +SDLKey X11_TranslateKeycode(Display *display, KeyCode kc) +{ + KeySym xsym; + SDLKey key; + + xsym = XKeycodeToKeysym(display, kc, 0); +#ifdef DEBUG_KEYS + fprintf(stderr, "Translating key code %d -> 0x%.4x\n", kc, xsym); +#endif + key = SDLK_UNKNOWN; + if ( xsym ) { + switch (xsym>>8) { + case 0x1005FF: +#ifdef SunXK_F36 + if ( xsym == SunXK_F36 ) + key = SDLK_F11; +#endif +#ifdef SunXK_F37 + if ( xsym == SunXK_F37 ) + key = SDLK_F12; +#endif + break; + case 0x00: /* Latin 1 */ + key = (SDLKey)(xsym & 0xFF); + break; + case 0x01: /* Latin 2 */ + case 0x02: /* Latin 3 */ + case 0x03: /* Latin 4 */ + case 0x04: /* Katakana */ + case 0x05: /* Arabic */ + case 0x06: /* Cyrillic */ + case 0x07: /* Greek */ + case 0x08: /* Technical */ + case 0x0A: /* Publishing */ + case 0x0C: /* Hebrew */ + case 0x0D: /* Thai */ + /* These are wrong, but it's better than nothing */ + key = (SDLKey)(xsym & 0xFF); + break; + case 0xFE: + key = ODD_keymap[xsym&0xFF]; + break; + case 0xFF: + key = MISC_keymap[xsym&0xFF]; + break; + default: + /* + fprintf(stderr, "X11: Unhandled xsym, sym = 0x%04x\n", + (unsigned int)xsym); + */ + break; + } + } else { + /* X11 doesn't know how to translate the key! */ + switch (kc) { + /* Caution: + These keycodes are from the Microsoft Keyboard + */ + case 115: + key = SDLK_LSUPER; + break; + case 116: + key = SDLK_RSUPER; + break; + case 117: + key = SDLK_MENU; + break; + default: + /* + * no point in an error message; happens for + * several keys when we get a keymap notify + */ + break; + } + } + return key; +} + +/* X11 modifier masks for various keys */ +static unsigned meta_l_mask, meta_r_mask, alt_l_mask, alt_r_mask; +static unsigned num_mask, mode_switch_mask; + +static void get_modifier_masks(Display *display) +{ + static unsigned got_masks; + int i, j; + XModifierKeymap *xmods; + unsigned n; + + if(got_masks) + return; + + xmods = XGetModifierMapping(display); + n = xmods->max_keypermod; + for(i = 3; i < 8; i++) { + for(j = 0; j < n; j++) { + KeyCode kc = xmods->modifiermap[i * n + j]; + KeySym ks = XKeycodeToKeysym(display, kc, 0); + unsigned mask = 1 << i; + switch(ks) { + case XK_Num_Lock: + num_mask = mask; break; + case XK_Alt_L: + alt_l_mask = mask; break; + case XK_Alt_R: + alt_r_mask = mask; break; + case XK_Meta_L: + meta_l_mask = mask; break; + case XK_Meta_R: + meta_r_mask = mask; break; + case XK_Mode_switch: + mode_switch_mask = mask; break; + } + } + } + XFreeModifiermap(xmods); + got_masks = 1; +} + + +/* + * This function is semi-official; it is not officially exported and should + * not be considered part of the SDL API, but may be used by client code + * that *really* needs it (including legacy code). + * It is slow, though, and should be avoided if possible. + * + * Note that it isn't completely accurate either; in particular, multi-key + * sequences (dead accents, compose key sequences) will not work since the + * state has been irrevocably lost. + */ +Uint16 X11_KeyToUnicode(SDLKey keysym, SDLMod modifiers) +{ + struct SDL_VideoDevice *this = current_video; + char keybuf[32]; + int i; + KeySym xsym = 0; + XKeyEvent xkey; + Uint16 unicode; + + if ( !this || !SDL_Display ) { + return 0; + } + + SDL_memset(&xkey, 0, sizeof(xkey)); + xkey.display = SDL_Display; + + xsym = keysym; /* last resort if not found */ + for (i = 0; i < 256; ++i) { + if ( MISC_keymap[i] == keysym ) { + xsym = 0xFF00 | i; + break; + } else if ( ODD_keymap[i] == keysym ) { + xsym = 0xFE00 | i; + break; + } + } + + xkey.keycode = XKeysymToKeycode(xkey.display, xsym); + + get_modifier_masks(SDL_Display); + if(modifiers & KMOD_SHIFT) + xkey.state |= ShiftMask; + if(modifiers & KMOD_CAPS) + xkey.state |= LockMask; + if(modifiers & KMOD_CTRL) + xkey.state |= ControlMask; + if(modifiers & KMOD_MODE) + xkey.state |= mode_switch_mask; + if(modifiers & KMOD_LALT) + xkey.state |= alt_l_mask; + if(modifiers & KMOD_RALT) + xkey.state |= alt_r_mask; + if(modifiers & KMOD_LMETA) + xkey.state |= meta_l_mask; + if(modifiers & KMOD_RMETA) + xkey.state |= meta_r_mask; + if(modifiers & KMOD_NUM) + xkey.state |= num_mask; + + unicode = 0; + if ( XLookupString(&xkey, keybuf, sizeof(keybuf), NULL, NULL) ) + unicode = (unsigned char)keybuf[0]; + return(unicode); +} + + +/* + * Called when focus is regained, to read the keyboard state and generate + * synthetic keypress/release events. + * key_vec is a bit vector of keycodes (256 bits) + */ +void X11_SetKeyboardState(Display *display, const char *key_vec) +{ + char keys_return[32]; + int i; + Uint8 *kstate = SDL_GetKeyState(NULL); + SDLMod modstate; + Window junk_window; + int x, y; + unsigned int mask; + + /* The first time the window is mapped, we initialize key state */ + if ( ! key_vec ) { + XQueryKeymap(display, keys_return); + key_vec = keys_return; + } + + /* Get the keyboard modifier state */ + modstate = 0; + get_modifier_masks(display); + if ( XQueryPointer(display, DefaultRootWindow(display), + &junk_window, &junk_window, &x, &y, &x, &y, &mask) ) { + if ( mask & LockMask ) { + modstate |= KMOD_CAPS; + } + if ( mask & mode_switch_mask ) { + modstate |= KMOD_MODE; + } + if ( mask & num_mask ) { + modstate |= KMOD_NUM; + } + } + + /* Zero the new keyboard state and generate it */ + SDL_memset(kstate, 0, SDLK_LAST); + /* + * An obvious optimisation is to check entire longwords at a time in + * both loops, but we can't be sure the arrays are aligned so it's not + * worth the extra complexity + */ + for ( i = 0; i < 32; i++ ) { + int j; + if ( !key_vec[i] ) + continue; + for ( j = 0; j < 8; j++ ) { + if ( key_vec[i] & (1 << j) ) { + SDLKey key; + KeyCode kc = (i << 3 | j); + key = X11_TranslateKeycode(display, kc); + if ( key == SDLK_UNKNOWN ) { + continue; + } + kstate[key] = SDL_PRESSED; + switch (key) { + case SDLK_LSHIFT: + modstate |= KMOD_LSHIFT; + break; + case SDLK_RSHIFT: + modstate |= KMOD_RSHIFT; + break; + case SDLK_LCTRL: + modstate |= KMOD_LCTRL; + break; + case SDLK_RCTRL: + modstate |= KMOD_RCTRL; + break; + case SDLK_LALT: + modstate |= KMOD_LALT; + break; + case SDLK_RALT: + modstate |= KMOD_RALT; + break; + case SDLK_LMETA: + modstate |= KMOD_LMETA; + break; + case SDLK_RMETA: + modstate |= KMOD_RMETA; + break; + default: + break; + } + } + } + } + + /* Hack - set toggle key state */ + if ( modstate & KMOD_CAPS ) { + kstate[SDLK_CAPSLOCK] = SDL_PRESSED; + } else { + kstate[SDLK_CAPSLOCK] = SDL_RELEASED; + } + if ( modstate & KMOD_NUM ) { + kstate[SDLK_NUMLOCK] = SDL_PRESSED; + } else { + kstate[SDLK_NUMLOCK] = SDL_RELEASED; + } + + /* Set the final modifier state */ + SDL_SetModState(modstate); +} + +void X11_InitOSKeymap(_THIS) +{ + X11_InitKeymap(); +} + diff --git a/3rdparty/SDL/src/video/x11/SDL_x11events_c.h b/3rdparty/SDL/src/video/x11/SDL_x11events_c.h new file mode 100644 index 0000000..fe26d9c --- /dev/null +++ b/3rdparty/SDL/src/video/x11/SDL_x11events_c.h @@ -0,0 +1,34 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#include "SDL_x11video.h" + +/* Functions to be exported */ +extern void X11_InitOSKeymap(_THIS); +extern void X11_PumpEvents(_THIS); +extern void X11_SetKeyboardState(Display *display, const char *key_vec); + +/* Variables to be exported */ +extern int X11_PendingConfigureNotifyWidth; +extern int X11_PendingConfigureNotifyHeight; + diff --git a/3rdparty/SDL/src/video/x11/SDL_x11gamma.c b/3rdparty/SDL/src/video/x11/SDL_x11gamma.c new file mode 100644 index 0000000..c6afbda --- /dev/null +++ b/3rdparty/SDL/src/video/x11/SDL_x11gamma.c @@ -0,0 +1,142 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#include "SDL.h" +#include "SDL_events.h" +#include "../../events/SDL_events_c.h" +#include "SDL_x11video.h" + +/* From the X server sources... */ +#define MAX_GAMMA 10.0 +#define MIN_GAMMA (1.0/MAX_GAMMA) + +static int X11_SetGammaNoLock(_THIS, float red, float green, float blue) +{ +#if SDL_VIDEO_DRIVER_X11_VIDMODE + if (use_vidmode >= 200) { + SDL_NAME(XF86VidModeGamma) gamma; + Bool succeeded; + + /* Clamp the gamma values */ + if ( red < MIN_GAMMA ) { + gamma.red = MIN_GAMMA; + } else + if ( red > MAX_GAMMA ) { + gamma.red = MAX_GAMMA; + } else { + gamma.red = red; + } + if ( green < MIN_GAMMA ) { + gamma.green = MIN_GAMMA; + } else + if ( green > MAX_GAMMA ) { + gamma.green = MAX_GAMMA; + } else { + gamma.green = green; + } + if ( blue < MIN_GAMMA ) { + gamma.blue = MIN_GAMMA; + } else + if ( blue > MAX_GAMMA ) { + gamma.blue = MAX_GAMMA; + } else { + gamma.blue = blue; + } + if ( SDL_GetAppState() & SDL_APPACTIVE ) { + succeeded = SDL_NAME(XF86VidModeSetGamma)(SDL_Display, SDL_Screen, &gamma); + XSync(SDL_Display, False); + } else { + gamma_saved[0] = gamma.red; + gamma_saved[1] = gamma.green; + gamma_saved[2] = gamma.blue; + succeeded = True; + } + if ( succeeded ) { + ++gamma_changed; + } + return succeeded ? 0 : -1; + } +#endif + SDL_SetError("Gamma correction not supported"); + return -1; +} +int X11_SetVidModeGamma(_THIS, float red, float green, float blue) +{ + int result; + + SDL_Lock_EventThread(); + result = X11_SetGammaNoLock(this, red, green, blue); + SDL_Unlock_EventThread(); + + return(result); +} + +static int X11_GetGammaNoLock(_THIS, float *red, float *green, float *blue) +{ +#if SDL_VIDEO_DRIVER_X11_VIDMODE + if (use_vidmode >= 200) { + SDL_NAME(XF86VidModeGamma) gamma; + if (SDL_NAME(XF86VidModeGetGamma)(SDL_Display, SDL_Screen, &gamma)) { + *red = gamma.red; + *green = gamma.green; + *blue = gamma.blue; + return 0; + } + return -1; + } +#endif + return -1; +} +int X11_GetVidModeGamma(_THIS, float *red, float *green, float *blue) +{ + int result; + + SDL_Lock_EventThread(); + result = X11_GetGammaNoLock(this, red, green, blue); + SDL_Unlock_EventThread(); + + return(result); +} + +void X11_SaveVidModeGamma(_THIS) +{ + /* Try to save the current gamma, otherwise disable gamma control */ + if ( X11_GetGammaNoLock(this, + &gamma_saved[0], &gamma_saved[1], &gamma_saved[2]) < 0 ) { + this->SetGamma = 0; + this->GetGamma = 0; + } + gamma_changed = 0; +} +void X11_SwapVidModeGamma(_THIS) +{ + float new_gamma[3]; + + if ( gamma_changed ) { + new_gamma[0] = gamma_saved[0]; + new_gamma[1] = gamma_saved[1]; + new_gamma[2] = gamma_saved[2]; + X11_GetGammaNoLock(this, &gamma_saved[0], &gamma_saved[1], &gamma_saved[2]); + X11_SetGammaNoLock(this, new_gamma[0], new_gamma[1], new_gamma[2]); + } +} diff --git a/3rdparty/SDL/src/video/x11/SDL_x11gamma_c.h b/3rdparty/SDL/src/video/x11/SDL_x11gamma_c.h new file mode 100644 index 0000000..c46350f --- /dev/null +++ b/3rdparty/SDL/src/video/x11/SDL_x11gamma_c.h @@ -0,0 +1,32 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#ifndef _SDL_x11gamma_h +#define _SDL_x11gamma_h + +extern int X11_SetVidModeGamma(_THIS, float red, float green, float blue); +extern int X11_GetVidModeGamma(_THIS, float *red, float *green, float *blue); +extern void X11_SaveVidModeGamma(_THIS); +extern void X11_SwapVidModeGamma(_THIS); + +#endif diff --git a/3rdparty/SDL/src/video/x11/SDL_x11gl.c b/3rdparty/SDL/src/video/x11/SDL_x11gl.c new file mode 100644 index 0000000..aa5297b --- /dev/null +++ b/3rdparty/SDL/src/video/x11/SDL_x11gl.c @@ -0,0 +1,577 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#include "SDL_x11video.h" +#include "../../events/SDL_events_c.h" +#include "SDL_x11dga_c.h" +#include "SDL_x11gl_c.h" + +#if defined(__IRIX__) +/* IRIX doesn't have a GL library versioning system */ +#define DEFAULT_OPENGL "libGL.so" +#elif defined(__MACOSX__) +#define DEFAULT_OPENGL "/usr/X11R6/lib/libGL.1.dylib" +#elif defined(__QNXNTO__) +#define DEFAULT_OPENGL "libGL.so.3" +#elif defined(__OpenBSD__) +#define DEFAULT_OPENGL "libGL.so.4.0" +#else +#define DEFAULT_OPENGL "libGL.so.1" +#endif + +#ifndef GLX_ARB_multisample +#define GLX_ARB_multisample +#define GLX_SAMPLE_BUFFERS_ARB 100000 +#define GLX_SAMPLES_ARB 100001 +#endif + +/* GLX_EXT_visual_rating stuff that might not be in the system headers... */ +#ifndef GLX_VISUAL_CAVEAT_EXT +#define GLX_VISUAL_CAVEAT_EXT 0x20 +#endif +#ifndef GLX_NONE_EXT +#define GLX_NONE_EXT 0x8000 +#endif +#ifndef GLX_SLOW_VISUAL_EXT +#define GLX_SLOW_VISUAL_EXT 0x8001 +#endif +#ifndef GLX_NON_CONFORMANT_VISUAL_EXT +#define GLX_NON_CONFORMANT_VISUAL_EXT 0x800D +#endif + + +#if SDL_VIDEO_OPENGL_GLX +static int glXExtensionSupported(_THIS, const char *extension) +{ + const char *extensions; + const char *start; + const char *where, *terminator; + + /* Extension names should not have spaces. */ + where = SDL_strchr(extension, ' '); + if ( where || *extension == '\0' ) { + return 0; + } + + extensions = this->gl_data->glXQueryExtensionsString(GFX_Display,SDL_Screen); + /* It takes a bit of care to be fool-proof about parsing the + * OpenGL extensions string. Don't be fooled by sub-strings, etc. + */ + + /* http://bugs.debian.org/537487 */ + if (extensions == NULL) { + return 0; + } + + start = extensions; + + for (;;) { + where = SDL_strstr(start, extension); + if (!where) break; + + terminator = where + strlen(extension); + if (where == start || *(where - 1) == ' ') + if (*terminator == ' ' || *terminator == '\0') return 1; + + start = terminator; + } + return 0; +} +#endif /* SDL_VIDEO_OPENGL_GLX */ + +XVisualInfo *X11_GL_GetVisual(_THIS) +{ +#if SDL_VIDEO_OPENGL_GLX + /* 64 seems nice. */ + int attribs[64]; + int i; + + /* load the gl driver from a default path */ + if ( ! this->gl_config.driver_loaded ) { + /* no driver has been loaded, use default (ourselves) */ + if ( X11_GL_LoadLibrary(this, NULL) < 0 ) { + return NULL; + } + } + + /* See if we already have a window which we must use */ + if ( SDL_windowid ) { + XWindowAttributes a; + XVisualInfo vi_in; + int out_count; + + XGetWindowAttributes(SDL_Display, SDL_Window, &a); + vi_in.screen = SDL_Screen; + vi_in.visualid = XVisualIDFromVisual(a.visual); + glx_visualinfo = XGetVisualInfo(SDL_Display, + VisualScreenMask|VisualIDMask, &vi_in, &out_count); + return glx_visualinfo; + } + + /* Setup our GLX attributes according to the gl_config. */ + i = 0; + attribs[i++] = GLX_RGBA; + attribs[i++] = GLX_RED_SIZE; + attribs[i++] = this->gl_config.red_size; + attribs[i++] = GLX_GREEN_SIZE; + attribs[i++] = this->gl_config.green_size; + attribs[i++] = GLX_BLUE_SIZE; + attribs[i++] = this->gl_config.blue_size; + + if( this->gl_config.alpha_size ) { + attribs[i++] = GLX_ALPHA_SIZE; + attribs[i++] = this->gl_config.alpha_size; + } + + if( this->gl_config.double_buffer ) { + attribs[i++] = GLX_DOUBLEBUFFER; + } + + attribs[i++] = GLX_DEPTH_SIZE; + attribs[i++] = this->gl_config.depth_size; + + if( this->gl_config.stencil_size ) { + attribs[i++] = GLX_STENCIL_SIZE; + attribs[i++] = this->gl_config.stencil_size; + } + + if( this->gl_config.accum_red_size ) { + attribs[i++] = GLX_ACCUM_RED_SIZE; + attribs[i++] = this->gl_config.accum_red_size; + } + + if( this->gl_config.accum_green_size ) { + attribs[i++] = GLX_ACCUM_GREEN_SIZE; + attribs[i++] = this->gl_config.accum_green_size; + } + + if( this->gl_config.accum_blue_size ) { + attribs[i++] = GLX_ACCUM_BLUE_SIZE; + attribs[i++] = this->gl_config.accum_blue_size; + } + + if( this->gl_config.accum_alpha_size ) { + attribs[i++] = GLX_ACCUM_ALPHA_SIZE; + attribs[i++] = this->gl_config.accum_alpha_size; + } + + if( this->gl_config.stereo ) { + attribs[i++] = GLX_STEREO; + } + + if( this->gl_config.multisamplebuffers ) { + attribs[i++] = GLX_SAMPLE_BUFFERS_ARB; + attribs[i++] = this->gl_config.multisamplebuffers; + } + + if( this->gl_config.multisamplesamples ) { + attribs[i++] = GLX_SAMPLES_ARB; + attribs[i++] = this->gl_config.multisamplesamples; + } + + if( this->gl_config.accelerated >= 0 && + glXExtensionSupported(this, "GLX_EXT_visual_rating") ) { + attribs[i++] = GLX_VISUAL_CAVEAT_EXT; + attribs[i++] = GLX_NONE_EXT; + } + +#ifdef GLX_DIRECT_COLOR /* Try for a DirectColor visual for gamma support */ + if ( !SDL_getenv("SDL_VIDEO_X11_NODIRECTCOLOR") ) { + attribs[i++] = GLX_X_VISUAL_TYPE; + attribs[i++] = GLX_DIRECT_COLOR; + } +#endif + attribs[i++] = None; + + glx_visualinfo = this->gl_data->glXChooseVisual(GFX_Display, + SDL_Screen, attribs); +#ifdef GLX_DIRECT_COLOR + if( !glx_visualinfo && !SDL_getenv("SDL_VIDEO_X11_NODIRECTCOLOR") ) { /* No DirectColor visual? Try again.. */ + attribs[i-3] = None; + glx_visualinfo = this->gl_data->glXChooseVisual(GFX_Display, + SDL_Screen, attribs); + } +#endif + if( !glx_visualinfo ) { + SDL_SetError( "Couldn't find matching GLX visual"); + return NULL; + } +/* + printf("Found GLX visual 0x%x\n", glx_visualinfo->visualid); +*/ + return glx_visualinfo; +#else + SDL_SetError("X11 driver not configured with OpenGL"); + return NULL; +#endif +} + +int X11_GL_CreateWindow(_THIS, int w, int h) +{ + int retval; +#if SDL_VIDEO_OPENGL_GLX + XSetWindowAttributes attributes; + unsigned long mask; + unsigned long black; + + black = (glx_visualinfo->visual == DefaultVisual(SDL_Display, + SDL_Screen)) + ? BlackPixel(SDL_Display, SDL_Screen) : 0; + attributes.background_pixel = black; + attributes.border_pixel = black; + attributes.colormap = SDL_XColorMap; + mask = CWBackPixel | CWBorderPixel | CWColormap; + + SDL_Window = XCreateWindow(SDL_Display, WMwindow, + 0, 0, w, h, 0, glx_visualinfo->depth, + InputOutput, glx_visualinfo->visual, + mask, &attributes); + if ( !SDL_Window ) { + SDL_SetError("Could not create window"); + return -1; + } + retval = 0; +#else + SDL_SetError("X11 driver not configured with OpenGL"); + retval = -1; +#endif + return(retval); +} + +int X11_GL_CreateContext(_THIS) +{ + int retval; +#if SDL_VIDEO_OPENGL_GLX + + /* We do this to create a clean separation between X and GLX errors. */ + XSync( SDL_Display, False ); + glx_context = this->gl_data->glXCreateContext(GFX_Display, + glx_visualinfo, NULL, True); + XSync( GFX_Display, False ); + + if ( glx_context == NULL ) { + SDL_SetError("Could not create GL context"); + return(-1); + } + if ( X11_GL_MakeCurrent(this) < 0 ) { + return(-1); + } + gl_active = 1; + + if ( !glXExtensionSupported(this, "GLX_SGI_swap_control") ) { + this->gl_data->glXSwapIntervalSGI = NULL; + } + if ( !glXExtensionSupported(this, "GLX_MESA_swap_control") ) { + this->gl_data->glXSwapIntervalMESA = NULL; + } + if ( !glXExtensionSupported(this, "GLX_EXT_swap_control") ) { + this->gl_data->glXSwapIntervalEXT = NULL; + } + + if ( this->gl_config.swap_control >= 0 ) { + int rc = -1; + if ( this->gl_data->glXSwapIntervalEXT ) { + rc = this->gl_data->glXSwapIntervalEXT(GFX_Display, SDL_Window, + this->gl_config.swap_control); + } else if ( this->gl_data->glXSwapIntervalMESA ) { + rc = this->gl_data->glXSwapIntervalMESA(this->gl_config.swap_control); + } else if ( this->gl_data->glXSwapIntervalSGI ) { + rc = this->gl_data->glXSwapIntervalSGI(this->gl_config.swap_control); + } + if (rc == 0) { + this->gl_data->swap_interval = this->gl_config.swap_control; + } + } +#else + SDL_SetError("X11 driver not configured with OpenGL"); +#endif + if ( gl_active ) { + retval = 0; + } else { + retval = -1; + } + return(retval); +} + +void X11_GL_Shutdown(_THIS) +{ +#if SDL_VIDEO_OPENGL_GLX + /* Clean up OpenGL */ + if( glx_context ) { + this->gl_data->glXMakeCurrent(GFX_Display, None, NULL); + + if (glx_context != NULL) + this->gl_data->glXDestroyContext(GFX_Display, glx_context); + + glx_context = NULL; + } + gl_active = 0; +#endif /* SDL_VIDEO_OPENGL_GLX */ +} + +#if SDL_VIDEO_OPENGL_GLX + +/* Make the current context active */ +int X11_GL_MakeCurrent(_THIS) +{ + int retval; + + retval = 0; + if ( ! this->gl_data->glXMakeCurrent(GFX_Display, + SDL_Window, glx_context) ) { + SDL_SetError("Unable to make GL context current"); + retval = -1; + } + XSync( GFX_Display, False ); + + /* More Voodoo X server workarounds... Grr... */ + SDL_Lock_EventThread(); + X11_CheckDGAMouse(this); + SDL_Unlock_EventThread(); + + return(retval); +} + +/* Get attribute data from glX. */ +int X11_GL_GetAttribute(_THIS, SDL_GLattr attrib, int* value) +{ + int retval = -1; + int unsupported = 0; + int glx_attrib = None; + + switch( attrib ) { + case SDL_GL_RED_SIZE: + glx_attrib = GLX_RED_SIZE; + break; + case SDL_GL_GREEN_SIZE: + glx_attrib = GLX_GREEN_SIZE; + break; + case SDL_GL_BLUE_SIZE: + glx_attrib = GLX_BLUE_SIZE; + break; + case SDL_GL_ALPHA_SIZE: + glx_attrib = GLX_ALPHA_SIZE; + break; + case SDL_GL_DOUBLEBUFFER: + glx_attrib = GLX_DOUBLEBUFFER; + break; + case SDL_GL_BUFFER_SIZE: + glx_attrib = GLX_BUFFER_SIZE; + break; + case SDL_GL_DEPTH_SIZE: + glx_attrib = GLX_DEPTH_SIZE; + break; + case SDL_GL_STENCIL_SIZE: + glx_attrib = GLX_STENCIL_SIZE; + break; + case SDL_GL_ACCUM_RED_SIZE: + glx_attrib = GLX_ACCUM_RED_SIZE; + break; + case SDL_GL_ACCUM_GREEN_SIZE: + glx_attrib = GLX_ACCUM_GREEN_SIZE; + break; + case SDL_GL_ACCUM_BLUE_SIZE: + glx_attrib = GLX_ACCUM_BLUE_SIZE; + break; + case SDL_GL_ACCUM_ALPHA_SIZE: + glx_attrib = GLX_ACCUM_ALPHA_SIZE; + break; + case SDL_GL_STEREO: + glx_attrib = GLX_STEREO; + break; + case SDL_GL_MULTISAMPLEBUFFERS: + glx_attrib = GLX_SAMPLE_BUFFERS_ARB; + break; + case SDL_GL_MULTISAMPLESAMPLES: + glx_attrib = GLX_SAMPLES_ARB; + break; + case SDL_GL_ACCELERATED_VISUAL: + if ( glXExtensionSupported(this, "GLX_EXT_visual_rating") ) { + glx_attrib = GLX_VISUAL_CAVEAT_EXT; + retval = this->gl_data->glXGetConfig(GFX_Display, glx_visualinfo, glx_attrib, value); + if ( *value == GLX_SLOW_VISUAL_EXT ) { + *value = SDL_FALSE; + } else { + *value = SDL_TRUE; + } + return retval; + } else { + unsupported = 1; + } + break; + case SDL_GL_SWAP_CONTROL: + if ( ( this->gl_data->glXSwapIntervalEXT ) || + ( this->gl_data->glXSwapIntervalMESA ) || + ( this->gl_data->glXSwapIntervalSGI ) ) { + *value = this->gl_data->swap_interval; + return 0; + } else { + unsupported = 1; + } + break; + default: + unsupported = 1; + break; + } + + if (unsupported) { + SDL_SetError("OpenGL attribute is unsupported on this system"); + } else { + retval = this->gl_data->glXGetConfig(GFX_Display, glx_visualinfo, glx_attrib, value); + } + return retval; +} + +void X11_GL_SwapBuffers(_THIS) +{ + this->gl_data->glXSwapBuffers(GFX_Display, SDL_Window); +} + +#endif /* SDL_VIDEO_OPENGL_GLX */ + +#define OPENGL_REQUIRS_DLOPEN +#if defined(OPENGL_REQUIRS_DLOPEN) && defined(SDL_LOADSO_DLOPEN) +#include <dlfcn.h> +#define GL_LoadObject(X) dlopen(X, (RTLD_NOW|RTLD_GLOBAL)) +#define GL_LoadFunction dlsym +#define GL_UnloadObject dlclose +#else +#define GL_LoadObject SDL_LoadObject +#define GL_LoadFunction SDL_LoadFunction +#define GL_UnloadObject SDL_UnloadObject +#endif + +void X11_GL_UnloadLibrary(_THIS) +{ +#if SDL_VIDEO_OPENGL_GLX + if ( this->gl_config.driver_loaded ) { + + GL_UnloadObject(this->gl_config.dll_handle); + + this->gl_data->glXGetProcAddress = NULL; + this->gl_data->glXChooseVisual = NULL; + this->gl_data->glXCreateContext = NULL; + this->gl_data->glXDestroyContext = NULL; + this->gl_data->glXMakeCurrent = NULL; + this->gl_data->glXSwapBuffers = NULL; + this->gl_data->glXSwapIntervalSGI = NULL; + this->gl_data->glXSwapIntervalMESA = NULL; + this->gl_data->glXSwapIntervalEXT = NULL; + + this->gl_config.dll_handle = NULL; + this->gl_config.driver_loaded = 0; + } +#endif +} + +#if SDL_VIDEO_OPENGL_GLX + +/* Passing a NULL path means load pointers from the application */ +int X11_GL_LoadLibrary(_THIS, const char* path) +{ + void* handle = NULL; + + if ( gl_active ) { + SDL_SetError("OpenGL context already created"); + return -1; + } + + if ( path == NULL ) { + path = SDL_getenv("SDL_VIDEO_GL_DRIVER"); + if ( path == NULL ) { + path = DEFAULT_OPENGL; + } + } + + handle = GL_LoadObject(path); + if ( handle == NULL ) { +#if defined(OPENGL_REQUIRS_DLOPEN) && defined(SDL_LOADSO_DLOPEN) + SDL_SetError("Failed loading %s", path); +#else + /* SDL_LoadObject() will call SDL_SetError() for us. */ +#endif + return -1; + } + + /* Unload the old driver and reset the pointers */ + X11_GL_UnloadLibrary(this); + + /* Save the handle for X11_GL_GetProcAddress() */ + this->gl_config.dll_handle = handle; + + /* Load new function pointers */ + this->gl_data->glXGetProcAddress = + (void *(*)(const GLubyte *)) GL_LoadFunction(handle, "glXGetProcAddressARB"); + this->gl_data->glXChooseVisual = + (XVisualInfo *(*)(Display *, int, int *)) X11_GL_GetProcAddress(this, "glXChooseVisual"); + this->gl_data->glXCreateContext = + (GLXContext (*)(Display *, XVisualInfo *, GLXContext, int)) X11_GL_GetProcAddress(this, "glXCreateContext"); + this->gl_data->glXDestroyContext = + (void (*)(Display *, GLXContext)) X11_GL_GetProcAddress(this, "glXDestroyContext"); + this->gl_data->glXMakeCurrent = + (int (*)(Display *, GLXDrawable, GLXContext)) X11_GL_GetProcAddress(this, "glXMakeCurrent"); + this->gl_data->glXSwapBuffers = + (void (*)(Display *, GLXDrawable)) X11_GL_GetProcAddress(this, "glXSwapBuffers"); + this->gl_data->glXGetConfig = + (int (*)(Display *, XVisualInfo *, int, int *)) X11_GL_GetProcAddress(this, "glXGetConfig"); + this->gl_data->glXQueryExtensionsString = + (const char *(*)(Display *, int)) X11_GL_GetProcAddress(this, "glXQueryExtensionsString"); + this->gl_data->glXSwapIntervalSGI = + (int (*)(int)) X11_GL_GetProcAddress(this, "glXSwapIntervalSGI"); + this->gl_data->glXSwapIntervalMESA = + (GLint (*)(unsigned)) X11_GL_GetProcAddress(this, "glXSwapIntervalMESA"); + this->gl_data->glXSwapIntervalEXT = + (int (*)(Display*,GLXDrawable,int)) X11_GL_GetProcAddress(this, "glXSwapIntervalEXT"); + + if ( (this->gl_data->glXChooseVisual == NULL) || + (this->gl_data->glXCreateContext == NULL) || + (this->gl_data->glXDestroyContext == NULL) || + (this->gl_data->glXMakeCurrent == NULL) || + (this->gl_data->glXSwapBuffers == NULL) || + (this->gl_data->glXGetConfig == NULL) || + (this->gl_data->glXQueryExtensionsString == NULL)) { + GL_UnloadObject(this->gl_config.dll_handle); + this->gl_config.dll_handle = NULL; + SDL_SetError("Could not retrieve OpenGL functions"); + return -1; + } + + this->gl_config.driver_loaded = 1; + if ( path ) { + SDL_strlcpy(this->gl_config.driver_path, path, + SDL_arraysize(this->gl_config.driver_path)); + } else { + *this->gl_config.driver_path = '\0'; + } + return 0; +} + +void *X11_GL_GetProcAddress(_THIS, const char* proc) +{ + if ( this->gl_data->glXGetProcAddress ) { + return this->gl_data->glXGetProcAddress((const GLubyte *)proc); + } + return GL_LoadFunction(this->gl_config.dll_handle, proc); +} + +#endif /* SDL_VIDEO_OPENGL_GLX */ diff --git a/3rdparty/SDL/src/video/x11/SDL_x11gl_c.h b/3rdparty/SDL/src/video/x11/SDL_x11gl_c.h new file mode 100644 index 0000000..b4822cb --- /dev/null +++ b/3rdparty/SDL/src/video/x11/SDL_x11gl_c.h @@ -0,0 +1,99 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#if SDL_VIDEO_OPENGL_GLX +#include <GL/glx.h> +#include "SDL_loadso.h" +#endif + +#include "../SDL_sysvideo.h" + +struct SDL_PrivateGLData { + int gl_active; /* to stop switching drivers while we have a valid context */ + +#if SDL_VIDEO_OPENGL_GLX + GLXContext glx_context; /* Current GL context */ + XVisualInfo* glx_visualinfo; /* XVisualInfo* returned by glXChooseVisual */ + + void * (*glXGetProcAddress)(const GLubyte *procName); + + XVisualInfo* (*glXChooseVisual) + ( Display* dpy, + int screen, + int* attribList ); + + GLXContext (*glXCreateContext) + ( Display* dpy, + XVisualInfo* vis, + GLXContext shareList, + Bool direct ); + + void (*glXDestroyContext) + ( Display* dpy, + GLXContext ctx ); + + Bool (*glXMakeCurrent) + ( Display* dpy, + GLXDrawable drawable, + GLXContext ctx ); + + void (*glXSwapBuffers) + ( Display* dpy, + GLXDrawable drawable ); + + int (*glXGetConfig) + ( Display* dpy, + XVisualInfo* visual_info, + int attrib, + int* value ); + + const char *(*glXQueryExtensionsString) + ( Display* dpy, + int screen ); + + int (*glXSwapIntervalSGI) ( int interval ); + GLint (*glXSwapIntervalMESA) ( unsigned interval ); + int (*glXSwapIntervalEXT)( Display *dpy, GLXDrawable drw, int interval); + int swap_interval; +#endif /* SDL_VIDEO_OPENGL_GLX */ +}; + +/* Old variable names */ +#define gl_active (this->gl_data->gl_active) +#define glx_context (this->gl_data->glx_context) +#define glx_visualinfo (this->gl_data->glx_visualinfo) + +/* OpenGL functions */ +extern XVisualInfo *X11_GL_GetVisual(_THIS); +extern int X11_GL_CreateWindow(_THIS, int w, int h); +extern int X11_GL_CreateContext(_THIS); +extern void X11_GL_Shutdown(_THIS); +#if SDL_VIDEO_OPENGL_GLX +extern int X11_GL_MakeCurrent(_THIS); +extern int X11_GL_GetAttribute(_THIS, SDL_GLattr attrib, int* value); +extern void X11_GL_SwapBuffers(_THIS); +extern int X11_GL_LoadLibrary(_THIS, const char* path); +extern void *X11_GL_GetProcAddress(_THIS, const char* proc); +#endif +extern void X11_GL_UnloadLibrary(_THIS); + diff --git a/3rdparty/SDL/src/video/x11/SDL_x11image.c b/3rdparty/SDL/src/video/x11/SDL_x11image.c new file mode 100644 index 0000000..464bc37 --- /dev/null +++ b/3rdparty/SDL/src/video/x11/SDL_x11image.c @@ -0,0 +1,316 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#include <stdio.h> +#include <unistd.h> + +#include "SDL_endian.h" +#include "../../events/SDL_events_c.h" +#include "SDL_x11image_c.h" + +#ifndef NO_SHARED_MEMORY + +/* Shared memory error handler routine */ +static int shm_error; +static int (*X_handler)(Display *, XErrorEvent *) = NULL; +static int shm_errhandler(Display *d, XErrorEvent *e) +{ + if ( e->error_code == BadAccess ) { + shm_error = True; + return(0); + } else + return(X_handler(d,e)); +} + +static void try_mitshm(_THIS, SDL_Surface *screen) +{ + /* Dynamic X11 may not have SHM entry points on this box. */ + if ((use_mitshm) && (!SDL_X11_HAVE_SHM)) + use_mitshm = 0; + + if(!use_mitshm) + return; + shminfo.shmid = shmget(IPC_PRIVATE, screen->h*screen->pitch, + IPC_CREAT | 0777); + if ( shminfo.shmid >= 0 ) { + shminfo.shmaddr = (char *)shmat(shminfo.shmid, 0, 0); + shminfo.readOnly = False; + if ( shminfo.shmaddr != (char *)-1 ) { + shm_error = False; + X_handler = XSetErrorHandler(shm_errhandler); + XShmAttach(SDL_Display, &shminfo); + XSync(SDL_Display, True); + XSetErrorHandler(X_handler); + if ( shm_error ) + shmdt(shminfo.shmaddr); + } else { + shm_error = True; + } + shmctl(shminfo.shmid, IPC_RMID, NULL); + } else { + shm_error = True; + } + if ( shm_error ) + use_mitshm = 0; + if ( use_mitshm ) + screen->pixels = shminfo.shmaddr; +} +#endif /* ! NO_SHARED_MEMORY */ + +/* Various screen update functions available */ +static void X11_NormalUpdate(_THIS, int numrects, SDL_Rect *rects); +static void X11_MITSHMUpdate(_THIS, int numrects, SDL_Rect *rects); + +int X11_SetupImage(_THIS, SDL_Surface *screen) +{ +#ifndef NO_SHARED_MEMORY + try_mitshm(this, screen); + if(use_mitshm) { + SDL_Ximage = XShmCreateImage(SDL_Display, SDL_Visual, + this->hidden->depth, ZPixmap, + shminfo.shmaddr, &shminfo, + screen->w, screen->h); + if(!SDL_Ximage) { + XShmDetach(SDL_Display, &shminfo); + XSync(SDL_Display, False); + shmdt(shminfo.shmaddr); + screen->pixels = NULL; + goto error; + } + this->UpdateRects = X11_MITSHMUpdate; + } + if(!use_mitshm) +#endif /* not NO_SHARED_MEMORY */ + { + screen->pixels = SDL_malloc(screen->h*screen->pitch); + if ( screen->pixels == NULL ) { + SDL_OutOfMemory(); + return -1; + } + SDL_Ximage = XCreateImage(SDL_Display, SDL_Visual, + this->hidden->depth, ZPixmap, 0, + (char *)screen->pixels, + screen->w, screen->h, + 32, 0); + if ( SDL_Ximage == NULL ) + goto error; + /* XPutImage will convert byte sex automatically */ + SDL_Ximage->byte_order = (SDL_BYTEORDER == SDL_BIG_ENDIAN) + ? MSBFirst : LSBFirst; + this->UpdateRects = X11_NormalUpdate; + } + screen->pitch = SDL_Ximage->bytes_per_line; + return(0); + +error: + SDL_SetError("Couldn't create XImage"); + return 1; +} + +void X11_DestroyImage(_THIS, SDL_Surface *screen) +{ + if ( SDL_Ximage ) { + XDestroyImage(SDL_Ximage); +#ifndef NO_SHARED_MEMORY + if ( use_mitshm ) { + XShmDetach(SDL_Display, &shminfo); + XSync(SDL_Display, False); + shmdt(shminfo.shmaddr); + } +#endif /* ! NO_SHARED_MEMORY */ + SDL_Ximage = NULL; + } + if ( screen ) { + screen->pixels = NULL; + } +} + +/* Determine the number of CPUs in the system */ +static int num_CPU(void) +{ + static int num_cpus = 0; + + if(!num_cpus) { +#if defined(__LINUX__) + char line[BUFSIZ]; + FILE *pstat = fopen("/proc/stat", "r"); + if ( pstat ) { + while ( fgets(line, sizeof(line), pstat) ) { + if (SDL_memcmp(line, "cpu", 3) == 0 && line[3] != ' ') { + ++num_cpus; + } + } + fclose(pstat); + } +#elif defined(__IRIX__) + num_cpus = sysconf(_SC_NPROC_ONLN); +#elif defined(_SC_NPROCESSORS_ONLN) + /* number of processors online (SVR4.0MP compliant machines) */ + num_cpus = sysconf(_SC_NPROCESSORS_ONLN); +#elif defined(_SC_NPROCESSORS_CONF) + /* number of processors configured (SVR4.0MP compliant machines) */ + num_cpus = sysconf(_SC_NPROCESSORS_CONF); +#endif + if ( num_cpus <= 0 ) { + num_cpus = 1; + } + } + return num_cpus; +} + +int X11_ResizeImage(_THIS, SDL_Surface *screen, Uint32 flags) +{ + int retval; + + X11_DestroyImage(this, screen); + if ( flags & SDL_OPENGL ) { /* No image when using GL */ + retval = 0; + } else { + retval = X11_SetupImage(this, screen); + /* We support asynchronous blitting on the display */ + if ( flags & SDL_ASYNCBLIT ) { + /* This is actually slower on single-CPU systems, + probably because of CPU contention between the + X server and the application. + Note: Is this still true with XFree86 4.0? + */ + if ( num_CPU() > 1 ) { + screen->flags |= SDL_ASYNCBLIT; + } + } + } + return(retval); +} + +/* We don't actually allow hardware surfaces other than the main one */ +int X11_AllocHWSurface(_THIS, SDL_Surface *surface) +{ + return(-1); +} +void X11_FreeHWSurface(_THIS, SDL_Surface *surface) +{ + return; +} + +int X11_LockHWSurface(_THIS, SDL_Surface *surface) +{ + if ( (surface == SDL_VideoSurface) && blit_queued ) { + XSync(GFX_Display, False); + blit_queued = 0; + } + return(0); +} +void X11_UnlockHWSurface(_THIS, SDL_Surface *surface) +{ + return; +} + +int X11_FlipHWSurface(_THIS, SDL_Surface *surface) +{ + return(0); +} + +static void X11_NormalUpdate(_THIS, int numrects, SDL_Rect *rects) +{ + int i; + + for (i = 0; i < numrects; ++i) { + if ( rects[i].w == 0 || rects[i].h == 0 ) { /* Clipped? */ + continue; + } + XPutImage(GFX_Display, SDL_Window, SDL_GC, SDL_Ximage, + rects[i].x, rects[i].y, + rects[i].x, rects[i].y, rects[i].w, rects[i].h); + } + if ( SDL_VideoSurface->flags & SDL_ASYNCBLIT ) { + XFlush(GFX_Display); + blit_queued = 1; + } else { + XSync(GFX_Display, False); + } +} + +static void X11_MITSHMUpdate(_THIS, int numrects, SDL_Rect *rects) +{ +#ifndef NO_SHARED_MEMORY + int i; + + for ( i=0; i<numrects; ++i ) { + if ( rects[i].w == 0 || rects[i].h == 0 ) { /* Clipped? */ + continue; + } + XShmPutImage(GFX_Display, SDL_Window, SDL_GC, SDL_Ximage, + rects[i].x, rects[i].y, + rects[i].x, rects[i].y, rects[i].w, rects[i].h, + False); + } + if ( SDL_VideoSurface->flags & SDL_ASYNCBLIT ) { + XFlush(GFX_Display); + blit_queued = 1; + } else { + XSync(GFX_Display, False); + } +#endif /* ! NO_SHARED_MEMORY */ +} + +/* There's a problem with the automatic refreshing of the display. + Even though the XVideo code uses the GFX_Display to update the + video memory, it appears that updating the window asynchronously + from a different thread will cause "blackouts" of the window. + This is a sort of a hacked workaround for the problem. +*/ +static int enable_autorefresh = 1; + +void X11_DisableAutoRefresh(_THIS) +{ + --enable_autorefresh; +} + +void X11_EnableAutoRefresh(_THIS) +{ + ++enable_autorefresh; +} + +void X11_RefreshDisplay(_THIS) +{ + /* Don't refresh a display that doesn't have an image (like GL) + Instead, post an expose event so the application can refresh. + */ + if ( ! SDL_Ximage || (enable_autorefresh <= 0) ) { + SDL_PrivateExpose(); + return; + } +#ifndef NO_SHARED_MEMORY + if ( this->UpdateRects == X11_MITSHMUpdate ) { + XShmPutImage(SDL_Display, SDL_Window, SDL_GC, SDL_Ximage, + 0, 0, 0, 0, this->screen->w, this->screen->h, + False); + } else +#endif /* ! NO_SHARED_MEMORY */ + { + XPutImage(SDL_Display, SDL_Window, SDL_GC, SDL_Ximage, + 0, 0, 0, 0, this->screen->w, this->screen->h); + } + XSync(SDL_Display, False); +} + diff --git a/3rdparty/SDL/src/video/x11/SDL_x11image_c.h b/3rdparty/SDL/src/video/x11/SDL_x11image_c.h new file mode 100644 index 0000000..2de1571 --- /dev/null +++ b/3rdparty/SDL/src/video/x11/SDL_x11image_c.h @@ -0,0 +1,38 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#include "SDL_x11video.h" + +extern int X11_SetupImage(_THIS, SDL_Surface *screen); +extern void X11_DestroyImage(_THIS, SDL_Surface *screen); +extern int X11_ResizeImage(_THIS, SDL_Surface *screen, Uint32 flags); + +extern int X11_AllocHWSurface(_THIS, SDL_Surface *surface); +extern void X11_FreeHWSurface(_THIS, SDL_Surface *surface); +extern int X11_LockHWSurface(_THIS, SDL_Surface *surface); +extern void X11_UnlockHWSurface(_THIS, SDL_Surface *surface); +extern int X11_FlipHWSurface(_THIS, SDL_Surface *surface); + +extern void X11_DisableAutoRefresh(_THIS); +extern void X11_EnableAutoRefresh(_THIS); +extern void X11_RefreshDisplay(_THIS); diff --git a/3rdparty/SDL/src/video/x11/SDL_x11modes.c b/3rdparty/SDL/src/video/x11/SDL_x11modes.c new file mode 100644 index 0000000..c232e6a --- /dev/null +++ b/3rdparty/SDL/src/video/x11/SDL_x11modes.c @@ -0,0 +1,1143 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* Utilities for getting and setting the X display mode */ + +#include <stdio.h> + +#include "SDL_timer.h" +#include "SDL_events.h" +#include "../../events/SDL_events_c.h" +#include "SDL_x11video.h" +#include "SDL_x11wm_c.h" +#include "SDL_x11modes_c.h" +#include "SDL_x11image_c.h" + +/*#define X11MODES_DEBUG*/ + +#define MAX(a, b) (a > b ? a : b) + +#if SDL_VIDEO_DRIVER_X11_XRANDR +static int cmpmodelist(const void *va, const void *vb) +{ + const SDL_Rect *a = *(const SDL_Rect **)va; + const SDL_Rect *b = *(const SDL_Rect **)vb; + if ( a->w == b->w ) + return b->h - a->h; + else + return b->w - a->w; +} +#endif + +#if SDL_VIDEO_DRIVER_X11_VIDMODE +Bool SDL_NAME(XF86VidModeGetModeInfo)(Display *dpy, int scr, SDL_NAME(XF86VidModeModeInfo) *info) +{ + Bool retval; + int dotclock; + SDL_NAME(XF86VidModeModeLine) l; + SDL_memset(&l, 0, sizeof(l)); + retval = SDL_NAME(XF86VidModeGetModeLine)(dpy, scr, &dotclock, &l); + info->dotclock = dotclock; + info->hdisplay = l.hdisplay; + info->hsyncstart = l.hsyncstart; + info->hsyncend = l.hsyncend; + info->htotal = l.htotal; + info->hskew = l.hskew; + info->vdisplay = l.vdisplay; + info->vsyncstart = l.vsyncstart; + info->vsyncend = l.vsyncend; + info->vtotal = l.vtotal; + info->flags = l.flags; + info->privsize = l.privsize; + info->private = l.private; + return retval; +} +#endif /* SDL_VIDEO_DRIVER_X11_VIDMODE */ + +#if SDL_VIDEO_DRIVER_X11_VIDMODE +static void save_mode(_THIS) +{ + SDL_memset(&saved_mode, 0, sizeof(saved_mode)); + SDL_NAME(XF86VidModeGetModeInfo)(SDL_Display,SDL_Screen,&saved_mode); + SDL_NAME(XF86VidModeGetViewPort)(SDL_Display,SDL_Screen,&saved_view.x,&saved_view.y); +} +#endif + +#if SDL_VIDEO_DRIVER_X11_VIDMODE +static void restore_mode(_THIS) +{ + SDL_NAME(XF86VidModeModeLine) mode; + int unused; + + if ( SDL_NAME(XF86VidModeGetModeLine)(SDL_Display, SDL_Screen, &unused, &mode) ) { + if ( (saved_mode.hdisplay != mode.hdisplay) || + (saved_mode.vdisplay != mode.vdisplay) ) { + SDL_NAME(XF86VidModeSwitchToMode)(SDL_Display, SDL_Screen, &saved_mode); + } + } + if ( (saved_view.x != 0) || (saved_view.y != 0) ) { + SDL_NAME(XF86VidModeSetViewPort)(SDL_Display, SDL_Screen, saved_view.x, saved_view.y); + } +} +#endif + +#if SDL_VIDEO_DRIVER_X11_VIDMODE +static int cmpmodes(const void *va, const void *vb) +{ + const SDL_NAME(XF86VidModeModeInfo) *a = *(const SDL_NAME(XF86VidModeModeInfo)**)va; + const SDL_NAME(XF86VidModeModeInfo) *b = *(const SDL_NAME(XF86VidModeModeInfo)**)vb; + if ( a->hdisplay == b->hdisplay ) + return b->vdisplay - a->vdisplay; + else + return b->hdisplay - a->hdisplay; +} +#endif + +static void get_real_resolution(_THIS, int* w, int* h); + +static void set_best_resolution(_THIS, int width, int height) +{ +#if SDL_VIDEO_DRIVER_X11_VIDMODE + if ( use_vidmode ) { + SDL_NAME(XF86VidModeModeLine) mode; + SDL_NAME(XF86VidModeModeInfo) **modes; + int i; + int nmodes; + int best = -1; + + if ( SDL_NAME(XF86VidModeGetModeLine)(SDL_Display, SDL_Screen, &i, &mode) && + SDL_NAME(XF86VidModeGetAllModeLines)(SDL_Display,SDL_Screen,&nmodes,&modes) ) { + for ( i = 0; i < nmodes ; i++ ) { + if ( (modes[i]->hdisplay == width) && + (modes[i]->vdisplay == height) ) { + best = i; + break; + } + if ( modes[i]->hdisplay >= width && + modes[i]->vdisplay >= height ) { + if ( best < 0 || + (modes[i]->hdisplay < modes[best]->hdisplay && + modes[i]->vdisplay <= modes[best]->vdisplay) || + (modes[i]->vdisplay < modes[best]->vdisplay && + modes[i]->hdisplay <= modes[best]->hdisplay) ) { + best = i; + } + } + } + if ( best >= 0 && + ((modes[best]->hdisplay != mode.hdisplay) || + (modes[best]->vdisplay != mode.vdisplay)) ) { +#ifdef X11MODES_DEBUG + printf("Best Mode %d: %d x %d @ %d\n", best, + modes[best]->hdisplay, modes[best]->vdisplay, + (modes[best]->htotal && modes[best]->vtotal) ? (1000 * modes[best]->dotclock / (modes[best]->htotal * modes[best]->vtotal)) : 0 ); +#endif + SDL_NAME(XF86VidModeSwitchToMode)(SDL_Display, SDL_Screen, modes[best]); + } + XFree(modes); + } + } +#endif /* SDL_VIDEO_DRIVER_X11_VIDMODE */ + + /* XiG */ +#if SDL_VIDEO_DRIVER_X11_XME + if ( use_xme && SDL_modelist ) { + int i; + +#ifdef X11MODES_DEBUG + fprintf(stderr, "XME: set_best_resolution(): w = %d, h = %d\n", + width, height); +#endif + for ( i=0; SDL_modelist[i]; ++i ) { + if ( (SDL_modelist[i]->w >= width) && + (SDL_modelist[i]->h >= height) ) { + break; + } + } + + if ( SDL_modelist[i] ) { /* found one, lets try it */ + int w, h; + + /* check current mode so we can avoid uneccessary mode changes */ + get_real_resolution(this, &w, &h); + + if ( (SDL_modelist[i]->w != w) || (SDL_modelist[i]->h != h) ) { +#ifdef X11MODES_DEBUG + fprintf(stderr, "XME: set_best_resolution: " + "XiGMiscChangeResolution: %d %d\n", + SDL_modelist[i]->w, SDL_modelist[i]->h); +#endif + XiGMiscChangeResolution(SDL_Display, + SDL_Screen, + 0, /* view */ + SDL_modelist[i]->w, + SDL_modelist[i]->h, + 0); + XSync(SDL_Display, False); + } + } + } +#endif /* SDL_VIDEO_DRIVER_X11_XME */ + +#if SDL_VIDEO_DRIVER_X11_XRANDR + if ( use_xrandr && SDL_modelist ) { +#ifdef X11MODES_DEBUG + fprintf(stderr, "XRANDR: set_best_resolution(): w = %d, h = %d\n", + width, height); +#endif + int i, nsizes; + XRRScreenSize *sizes; + + /* find the smallest resolution that is at least as big as the user requested */ + sizes = XRRConfigSizes(screen_config, &nsizes); + for ( i = (nsizes-1); i >= 0; i-- ) { + if ( (SDL_modelist[i]->w >= width) && + (SDL_modelist[i]->h >= height) ) { + break; + } + } + + if ( i >= 0 && SDL_modelist[i] ) { /* found one, lets try it */ + int w, h; + + /* check current mode so we can avoid uneccessary mode changes */ + get_real_resolution(this, &w, &h); + + if ( (SDL_modelist[i]->w != w) || (SDL_modelist[i]->h != h) ) { + int size_id; + +#ifdef X11MODES_DEBUG + fprintf(stderr, "XRANDR: set_best_resolution: " + "XXRSetScreenConfig: %d %d\n", + SDL_modelist[i]->w, SDL_modelist[i]->h); +#endif + + /* find the matching size entry index */ + for ( size_id = 0; size_id < nsizes; ++size_id ) { + if ( (sizes[size_id].width == SDL_modelist[i]->w) && + (sizes[size_id].height == SDL_modelist[i]->h) ) + break; + } + + XRRSetScreenConfig(SDL_Display, screen_config, SDL_Root, + size_id, saved_rotation, CurrentTime); + } + } + } +#endif /* SDL_VIDEO_DRIVER_X11_XRANDR */ +} + +static void get_real_resolution(_THIS, int* w, int* h) +{ +#if SDL_VIDEO_DRIVER_X11_XME + if ( use_xme ) { + int ractive; + XiGMiscResolutionInfo *modelist; + + XiGMiscQueryResolutions(SDL_Display, SDL_Screen, + 0, /* view */ + &ractive, &modelist); + *w = modelist[ractive].width; + *h = modelist[ractive].height; +#ifdef X11MODES_DEBUG + fprintf(stderr, "XME: get_real_resolution: w = %d h = %d\n", *w, *h); +#endif + XFree(modelist); + return; + } +#endif /* SDL_VIDEO_DRIVER_X11_XME */ + +#if SDL_VIDEO_DRIVER_X11_VIDMODE + if ( use_vidmode ) { + SDL_NAME(XF86VidModeModeLine) mode; + int unused; + + if ( SDL_NAME(XF86VidModeGetModeLine)(SDL_Display, SDL_Screen, &unused, &mode) ) { + *w = mode.hdisplay; + *h = mode.vdisplay; + return; + } + } +#endif /* SDL_VIDEO_DRIVER_X11_VIDMODE */ + +#if SDL_VIDEO_DRIVER_X11_XRANDR + if ( use_xrandr ) { + int nsizes; + XRRScreenSize* sizes; + + sizes = XRRConfigSizes(screen_config, &nsizes); + if ( nsizes > 0 ) { + int cur_size; + Rotation cur_rotation; + + cur_size = XRRConfigCurrentConfiguration(screen_config, &cur_rotation); + if ( cur_size >= 0 && cur_size < nsizes ) { + *w = sizes[cur_size].width; + *h = sizes[cur_size].height; + } +#ifdef X11MODES_DEBUG + fprintf(stderr, "XRANDR: get_real_resolution: w = %d h = %d\n", *w, *h); +#endif + return; + } + } +#endif /* SDL_VIDEO_DRIVER_X11_XRANDR */ + +#if SDL_VIDEO_DRIVER_X11_XINERAMA + if ( use_xinerama ) { + *w = xinerama_info.width; + *h = xinerama_info.height; + return; + } +#endif /* SDL_VIDEO_DRIVER_X11_XINERAMA */ + + *w = DisplayWidth(SDL_Display, SDL_Screen); + *h = DisplayHeight(SDL_Display, SDL_Screen); +} + +/* Called after mapping a window - waits until the window is mapped */ +void X11_WaitMapped(_THIS, Window win) +{ + XEvent event; + do { + XMaskEvent(SDL_Display, StructureNotifyMask, &event); + } while ( (event.type != MapNotify) || (event.xmap.event != win) ); +} + +/* Called after unmapping a window - waits until the window is unmapped */ +void X11_WaitUnmapped(_THIS, Window win) +{ + XEvent event; + do { + XMaskEvent(SDL_Display, StructureNotifyMask, &event); + } while ( (event.type != UnmapNotify) || (event.xunmap.event != win) ); +} + +static void move_cursor_to(_THIS, int x, int y) +{ + XWarpPointer(SDL_Display, None, SDL_Root, 0, 0, 0, 0, x, y); +} + +static int add_default_visual(_THIS) +{ + int i; + int n = this->hidden->nvisuals; + for (i=0; i<n; i++) { + if (this->hidden->visuals[i].visual == DefaultVisual(SDL_Display, SDL_Screen)) return n; + } + this->hidden->visuals[n].depth = DefaultDepth(SDL_Display, SDL_Screen);; + this->hidden->visuals[n].visual = DefaultVisual(SDL_Display, SDL_Screen);; + this->hidden->nvisuals++; + return(this->hidden->nvisuals); +} +static int add_visual(_THIS, int depth, int class) +{ + XVisualInfo vi; + if(XMatchVisualInfo(SDL_Display, SDL_Screen, depth, class, &vi)) { + int n = this->hidden->nvisuals; + this->hidden->visuals[n].depth = vi.depth; + this->hidden->visuals[n].visual = vi.visual; + this->hidden->nvisuals++; + } + return(this->hidden->nvisuals); +} +static int add_visual_byid(_THIS, const char *visual_id) +{ + XVisualInfo *vi, template; + int nvis; + + if ( visual_id ) { + SDL_memset(&template, 0, (sizeof template)); + template.visualid = SDL_strtol(visual_id, NULL, 0); + vi = XGetVisualInfo(SDL_Display, VisualIDMask, &template, &nvis); + if ( vi ) { + int n = this->hidden->nvisuals; + this->hidden->visuals[n].depth = vi->depth; + this->hidden->visuals[n].visual = vi->visual; + this->hidden->nvisuals++; + XFree(vi); + } + } + return(this->hidden->nvisuals); +} + +/* Global for the error handler */ +int vm_event, vm_error = -1; + +#if SDL_VIDEO_DRIVER_X11_XINERAMA +static int CheckXinerama(_THIS, int *major, int *minor) +{ + const char *env; + + /* Default the extension not available */ + *major = *minor = 0; + + /* Allow environment override */ + env = getenv("SDL_VIDEO_X11_XINERAMA"); + if ( env && !SDL_atoi(env) ) { + return 0; + } + + /* Query the extension version */ + if ( !SDL_NAME(XineramaQueryExtension)(SDL_Display, major, minor) || + !SDL_NAME(XineramaIsActive)(SDL_Display) ) { + return 0; + } + return 1; +} +#endif /* SDL_VIDEO_DRIVER_X11_XINERAMA */ + +#if SDL_VIDEO_DRIVER_X11_XRANDR +static int CheckXRandR(_THIS, int *major, int *minor) +{ + const char *env; + + /* Default the extension not available */ + *major = *minor = 0; + + /* Allow environment override */ + env = getenv("SDL_VIDEO_X11_XRANDR"); + if ( env && !SDL_atoi(env) ) { + return 0; + } + + /* This defaults off now, due to KDE window maximize problems */ + if ( !env ) { + return 0; + } + + if ( !SDL_X11_HAVE_XRANDR ) { + return 0; + } + + /* Query the extension version */ + if ( !XRRQueryVersion(SDL_Display, major, minor) ) { + return 0; + } + return 1; +} +#endif /* SDL_VIDEO_DRIVER_X11_XRANDR */ + +#if SDL_VIDEO_DRIVER_X11_VIDMODE +static int CheckVidMode(_THIS, int *major, int *minor) +{ + const char *env; + + /* Default the extension not available */ + *major = *minor = 0; + + /* Allow environment override */ + env = getenv("SDL_VIDEO_X11_VIDMODE"); + if ( env && !SDL_atoi(env) ) { + return 0; + } + + /* Metro-X 4.3.0 and earlier has a broken implementation of + XF86VidModeGetAllModeLines() - it hangs the client. + */ + if ( SDL_strcmp(ServerVendor(SDL_Display), "Metro Link Incorporated") == 0 ) { + FILE *metro_fp; + + metro_fp = fopen("/usr/X11R6/lib/X11/Metro/.version", "r"); + if ( metro_fp != NULL ) { + int major, minor, patch, version, scannum; + major = 0; minor = 0; patch = 0; + scannum = fscanf(metro_fp, "%d.%d.%d", &major, &minor, &patch); + fclose(metro_fp); + if ( (scannum < 0) || (scannum > 3) ) { + return 0; /* we need _something_ useful from fscanf(). */ + } + version = major*100+minor*10+patch; + if ( version < 431 ) { + return 0; + } + } + } + + /* Query the extension version */ + vm_error = -1; + if ( !SDL_NAME(XF86VidModeQueryExtension)(SDL_Display, &vm_event, &vm_error) || + !SDL_NAME(XF86VidModeQueryVersion)(SDL_Display, major, minor) ) { + return 0; + } + return 1; +} +#endif /* SDL_VIDEO_DRIVER_X11_VIDMODE */ + +#if SDL_VIDEO_DRIVER_X11_XME +static int CheckXME(_THIS, int *major, int *minor) +{ + const char *env; + + /* Default the extension not available */ + *major = *minor = 0; + + /* Allow environment override */ + env = getenv("SDL_VIDEO_X11_VIDMODE"); + if ( env && !SDL_atoi(env) ) { + return 0; + } + + /* Query the extension version */ + if ( !XiGMiscQueryVersion(SDL_Display, major, minor) ) { + return 0; + } + return 1; +} +#endif /* SDL_VIDEO_DRIVER_X11_XME */ + +int X11_GetVideoModes(_THIS) +{ +#if SDL_VIDEO_DRIVER_X11_XINERAMA + int xinerama_major, xinerama_minor; +#endif +#if SDL_VIDEO_DRIVER_X11_XRANDR + int xrandr_major, xrandr_minor; + int nsizes; + XRRScreenSize *sizes; +#endif +#if SDL_VIDEO_DRIVER_X11_VIDMODE + int vm_major, vm_minor; + int nmodes; + SDL_NAME(XF86VidModeModeInfo) **modes; +#endif +#if SDL_VIDEO_DRIVER_X11_XME + int xme_major, xme_minor; + int ractive, nummodes; + XiGMiscResolutionInfo *modelist; +#endif + int i, n; + int screen_w; + int screen_h; + + use_xinerama = 0; + use_xrandr = 0; + use_vidmode = 0; + use_xme = 0; + screen_w = DisplayWidth(SDL_Display, SDL_Screen); + screen_h = DisplayHeight(SDL_Display, SDL_Screen); + +#if SDL_VIDEO_DRIVER_X11_XINERAMA + /* Query Xinerama extention */ + if ( CheckXinerama(this, &xinerama_major, &xinerama_minor) ) { + /* Find out which screen is the desired one */ + int desired = -1; + int screens; + int w, h; + SDL_NAME(XineramaScreenInfo) *xinerama; + + const char *variable = SDL_getenv("SDL_VIDEO_FULLSCREEN_DISPLAY"); + if ( !variable ) { + variable = SDL_getenv("SDL_VIDEO_FULLSCREEN_HEAD"); + } + if ( variable ) { + desired = SDL_atoi(variable); + } +#ifdef X11MODES_DEBUG + printf("X11 detected Xinerama:\n"); +#endif + xinerama = SDL_NAME(XineramaQueryScreens)(SDL_Display, &screens); + for ( i = 0; i < screens; i++ ) { +#ifdef X11MODES_DEBUG + printf("xinerama %d: %dx%d+%d+%d\n", + xinerama[i].screen_number, + xinerama[i].width, xinerama[i].height, + xinerama[i].x_org, xinerama[i].y_org); +#endif + if ( xinerama[i].screen_number == desired ) { + use_xinerama = 1; + xinerama_info = xinerama[i]; + } + } + XFree(xinerama); + + if ( use_xinerama ) { + SDL_modelist = (SDL_Rect **)SDL_malloc(3*sizeof(SDL_Rect *)); + if ( !SDL_modelist ) { + SDL_OutOfMemory(); + return -1; + } + + /* Add the full xinerama mode */ + n = 0; + w = xinerama_info.width; + h = xinerama_info.height; + if ( screen_w > w || screen_h > h) { + SDL_modelist[n] = (SDL_Rect *)SDL_malloc(sizeof(SDL_Rect)); + if ( SDL_modelist[n] ) { + SDL_modelist[n]->x = 0; + SDL_modelist[n]->y = 0; + SDL_modelist[n]->w = screen_w; + SDL_modelist[n]->h = screen_h; + ++n; + } + } + + /* Add the head xinerama mode */ + SDL_modelist[n] = (SDL_Rect *)SDL_malloc(sizeof(SDL_Rect)); + if ( SDL_modelist[n] ) { + SDL_modelist[n]->x = 0; + SDL_modelist[n]->y = 0; + SDL_modelist[n]->w = w; + SDL_modelist[n]->h = h; + ++n; + } + SDL_modelist[n] = NULL; + } + } +#endif /* SDL_VIDEO_DRIVER_X11_XINERAMA */ + +#if SDL_VIDEO_DRIVER_X11_XRANDR + /* XRandR */ + /* require at least XRandR v1.0 (arbitrary) */ + if ( CheckXRandR(this, &xrandr_major, &xrandr_minor) && (xrandr_major >= 1) ) + { +#ifdef X11MODES_DEBUG + fprintf(stderr, "XRANDR: XRRQueryVersion: V%d.%d\n", + xrandr_major, xrandr_minor); +#endif + + /* save the screen configuration since we must reference it + each time we toggle modes. + */ + screen_config = XRRGetScreenInfo(SDL_Display, SDL_Root); + + /* retrieve the list of resolution */ + sizes = XRRConfigSizes(screen_config, &nsizes); + if (nsizes > 0) { + if ( SDL_modelist ) { + for ( i = 0; SDL_modelist[i]; ++i ) { + SDL_free(SDL_modelist[i]); + } + SDL_free(SDL_modelist); + } + SDL_modelist = (SDL_Rect **)malloc((nsizes+1)*sizeof(SDL_Rect *)); + if ( !SDL_modelist ) { + SDL_OutOfMemory(); + return -1; + } + for ( i=0; i < nsizes; i++ ) { + if ((SDL_modelist[i] = + (SDL_Rect *)malloc(sizeof(SDL_Rect))) == NULL) + break; +#ifdef X11MODES_DEBUG + fprintf(stderr, "XRANDR: mode = %4d, w = %4d, h = %4d\n", + i, sizes[i].width, sizes[i].height); +#endif + + SDL_modelist[i]->x = 0; + SDL_modelist[i]->y = 0; + SDL_modelist[i]->w = sizes[i].width; + SDL_modelist[i]->h = sizes[i].height; + + } + /* sort the mode list descending as SDL expects */ + SDL_qsort(SDL_modelist, nsizes, sizeof *SDL_modelist, cmpmodelist); + SDL_modelist[i] = NULL; /* terminator */ + + use_xrandr = xrandr_major * 100 + xrandr_minor; + saved_size_id = XRRConfigCurrentConfiguration(screen_config, &saved_rotation); + } + } +#endif /* SDL_VIDEO_DRIVER_X11_XRANDR */ + +#if SDL_VIDEO_DRIVER_X11_VIDMODE + /* XVidMode */ + if ( !use_xrandr && +#if SDL_VIDEO_DRIVER_X11_XINERAMA + (!use_xinerama || xinerama_info.screen_number == -1) && +#endif + CheckVidMode(this, &vm_major, &vm_minor) && + SDL_NAME(XF86VidModeGetAllModeLines)(SDL_Display, SDL_Screen,&nmodes,&modes) ) + { +#ifdef X11MODES_DEBUG + printf("VidMode modes: (unsorted)\n"); + for ( i = 0; i < nmodes; ++i ) { + printf("Mode %d: %d x %d @ %d\n", i, + modes[i]->hdisplay, modes[i]->vdisplay, + (modes[i]->htotal && modes[i]->vtotal) ? (1000 * modes[i]->dotclock / (modes[i]->htotal * modes[i]->vtotal)) : 0 ); + } +#endif + if ( SDL_modelist ) { + for ( i = 0; SDL_modelist[i]; ++i ) { + SDL_free(SDL_modelist[i]); + } + SDL_free(SDL_modelist); + } + SDL_modelist = (SDL_Rect **)SDL_malloc((nmodes+2)*sizeof(SDL_Rect *)); + if ( !SDL_modelist ) { + SDL_OutOfMemory(); + return -1; + } + SDL_qsort(modes, nmodes, sizeof *modes, cmpmodes); + n = 0; + for ( i=0; i<nmodes; ++i ) { + int w, h; + + /* Eliminate duplicate modes with different refresh rates */ + if ( i > 0 && + modes[i]->hdisplay == modes[i-1]->hdisplay && + modes[i]->vdisplay == modes[i-1]->vdisplay ) { + continue; + } + + /* Check to see if we should add the screen size (Xinerama) */ + w = modes[i]->hdisplay; + h = modes[i]->vdisplay; + if ( (screen_w * screen_h) >= (w * h) ) { + if ( (screen_w != w) || (screen_h != h) ) { + SDL_modelist[n] = (SDL_Rect *)SDL_malloc(sizeof(SDL_Rect)); + if ( SDL_modelist[n] ) { + SDL_modelist[n]->x = 0; + SDL_modelist[n]->y = 0; + SDL_modelist[n]->w = screen_w; + SDL_modelist[n]->h = screen_h; + ++n; + } + } + screen_w = 0; + screen_h = 0; + } + + /* Add the size from the video mode list */ + SDL_modelist[n] = (SDL_Rect *)SDL_malloc(sizeof(SDL_Rect)); + if ( SDL_modelist[n] == NULL ) { + break; + } + SDL_modelist[n]->x = 0; + SDL_modelist[n]->y = 0; + SDL_modelist[n]->w = w; + SDL_modelist[n]->h = h; + ++n; + } + SDL_modelist[n] = NULL; + XFree(modes); + + use_vidmode = vm_major * 100 + vm_minor; + save_mode(this); + } +#endif /* SDL_VIDEO_DRIVER_X11_VIDMODE */ + +#if SDL_VIDEO_DRIVER_X11_XME + /* XiG */ + modelist = NULL; + /* first lets make sure we have the extension, and it's at least v2.0 */ + if ( CheckXME(this, &xme_major, &xme_minor) && xme_major >= 2 && + (nummodes = XiGMiscQueryResolutions(SDL_Display, SDL_Screen, + 0, /* view */ + &ractive, &modelist)) > 1 ) + { /* then we actually have some */ + int j; + + /* We get the list already sorted in descending order. + We'll copy it in reverse order so SDL is happy */ +#ifdef X11MODES_DEBUG + fprintf(stderr, "XME: nummodes = %d, active mode = %d\n", + nummodes, ractive); +#endif + if ( SDL_modelist ) { + for ( i = 0; SDL_modelist[i]; ++i ) { + SDL_free(SDL_modelist[i]); + } + SDL_free(SDL_modelist); + } + SDL_modelist = (SDL_Rect **)SDL_malloc((nummodes+1)*sizeof(SDL_Rect *)); + if ( !SDL_modelist ) { + SDL_OutOfMemory(); + return -1; + } + for ( i=0, j=nummodes-1; j>=0; i++, j-- ) { + if ((SDL_modelist[i] = + (SDL_Rect *)SDL_malloc(sizeof(SDL_Rect))) == NULL) + break; +#ifdef X11MODES_DEBUG + fprintf(stderr, "XME: mode = %4d, w = %4d, h = %4d\n", + i, modelist[i].width, modelist[i].height); +#endif + + SDL_modelist[i]->x = 0; + SDL_modelist[i]->y = 0; + SDL_modelist[i]->w = modelist[j].width; + SDL_modelist[i]->h = modelist[j].height; + + } + SDL_modelist[i] = NULL; /* terminator */ + + use_xme = xme_major * 100 + xme_minor; + saved_res = modelist[ractive]; /* save the current resolution */ + } + if ( modelist ) { + XFree(modelist); + } +#endif /* SDL_VIDEO_DRIVER_X11_XME */ + + { + /* It's interesting to note that if we allow 32 bit depths, + we get a visual with an alpha mask on composite servers. + static int depth_list[] = { 32, 24, 16, 15, 8 }; + */ + static int depth_list[] = { 24, 16, 15, 8 }; + int j, np; + int use_directcolor = 1; + XPixmapFormatValues *pf; + + /* Search for the visuals in deepest-first order, so that the first + will be the richest one */ + if ( SDL_getenv("SDL_VIDEO_X11_NODIRECTCOLOR") ) { + use_directcolor = 0; + } + this->hidden->nvisuals = 0; + if ( ! add_visual_byid(this, SDL_getenv("SDL_VIDEO_X11_VISUALID")) ) { + for ( i=0; i<SDL_arraysize(depth_list); ++i ) { + if ( depth_list[i] > 8 ) { + if ( use_directcolor ) { + add_visual(this, depth_list[i], DirectColor); + } + add_visual(this, depth_list[i], TrueColor); + } else { + add_visual(this, depth_list[i], PseudoColor); + add_visual(this, depth_list[i], StaticColor); + } + } + add_default_visual(this); + } + if ( this->hidden->nvisuals == 0 ) { + SDL_SetError("Found no sufficiently capable X11 visuals"); + return -1; + } + + /* look up the pixel quantum for each depth */ + pf = XListPixmapFormats(SDL_Display, &np); + for(i = 0; i < this->hidden->nvisuals; i++) { + int d = this->hidden->visuals[i].depth; + for(j = 0; j < np; j++) + if(pf[j].depth == d) + break; + this->hidden->visuals[i].bpp = j < np ? pf[j].bits_per_pixel : d; + } + + XFree(pf); + } + + if ( SDL_modelist == NULL ) { + SDL_modelist = (SDL_Rect **)SDL_malloc((1+1)*sizeof(SDL_Rect *)); + if ( !SDL_modelist ) { + SDL_OutOfMemory(); + return -1; + } + n = 0; + SDL_modelist[n] = (SDL_Rect *)SDL_malloc(sizeof(SDL_Rect)); + if ( SDL_modelist[n] ) { + SDL_modelist[n]->x = 0; + SDL_modelist[n]->y = 0; + SDL_modelist[n]->w = screen_w; + SDL_modelist[n]->h = screen_h; + ++n; + } + SDL_modelist[n] = NULL; + } + +#ifdef X11MODES_DEBUG + if ( use_xinerama ) { + printf("Xinerama is enabled\n"); + } + + if ( use_xrandr ) { + printf("XRandR is enabled\n"); + } + + if ( use_vidmode ) { + printf("VidMode is enabled\n"); + } + + if ( use_xme ) { + printf("Xi Graphics XME fullscreen is enabled\n"); + } + + if ( SDL_modelist ) { + printf("X11 video mode list:\n"); + for ( i=0; SDL_modelist[i]; ++i ) { + printf("\t%dx%d\n", SDL_modelist[i]->w, SDL_modelist[i]->h); + } + } +#endif /* X11MODES_DEBUG */ + + return 0; +} + +int X11_SupportedVisual(_THIS, SDL_PixelFormat *format) +{ + int i; + for(i = 0; i < this->hidden->nvisuals; i++) + if(this->hidden->visuals[i].bpp == format->BitsPerPixel) + return 1; + return 0; +} + +SDL_Rect **X11_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags) +{ + if ( X11_SupportedVisual(this, format) ) { + if ( flags & SDL_FULLSCREEN ) { + return(SDL_modelist); + } else { + return((SDL_Rect **)-1); + } + } else { + return((SDL_Rect **)0); + } +} + +void X11_FreeVideoModes(_THIS) +{ + int i; + + if ( SDL_modelist ) { + for ( i=0; SDL_modelist[i]; ++i ) { + SDL_free(SDL_modelist[i]); + } + SDL_free(SDL_modelist); + SDL_modelist = NULL; + } + +#if SDL_VIDEO_DRIVER_X11_XRANDR + /* Free the Xrandr screen configuration */ + if ( screen_config ) { + XRRFreeScreenConfigInfo(screen_config); + screen_config = NULL; + } +#endif /* SDL_VIDEO_DRIVER_X11_XRANDR */ +} + +int X11_ResizeFullScreen(_THIS) +{ + int x = 0, y = 0; + int real_w, real_h; + int screen_w; + int screen_h; + + screen_w = DisplayWidth(SDL_Display, SDL_Screen); + screen_h = DisplayHeight(SDL_Display, SDL_Screen); + +#if SDL_VIDEO_DRIVER_X11_XINERAMA + if ( use_xinerama && + window_w <= xinerama_info.width && + window_h <= xinerama_info.height ) { + x = xinerama_info.x_org; + y = xinerama_info.y_org; + } +#endif /* SDL_VIDEO_DRIVER_X11_XINERAMA */ + + if ( currently_fullscreen ) { + /* Switch resolution and cover it with the FSwindow */ + move_cursor_to(this, x, y); + set_best_resolution(this, window_w, window_h); + move_cursor_to(this, x, y); + get_real_resolution(this, &real_w, &real_h); + if ( window_w > real_w ) { + real_w = MAX(real_w, screen_w); + } + if ( window_h > real_h ) { + real_h = MAX(real_h, screen_h); + } + XMoveResizeWindow(SDL_Display, FSwindow, x, y, real_w, real_h); + move_cursor_to(this, real_w/2, real_h/2); + + /* Center and reparent the drawing window */ + x = (real_w - window_w)/2; + y = (real_h - window_h)/2; + XReparentWindow(SDL_Display, SDL_Window, FSwindow, x, y); + /* FIXME: move the mouse to the old relative location */ + XSync(SDL_Display, True); /* Flush spurious mode change events */ + } + return(1); +} + +void X11_QueueEnterFullScreen(_THIS) +{ + switch_waiting = 0x01 | SDL_FULLSCREEN; + switch_time = SDL_GetTicks() + 1500; +#if 0 /* This causes a BadMatch error if the window is iconified (not needed) */ + XSetInputFocus(SDL_Display, WMwindow, RevertToNone, CurrentTime); +#endif +} + +int X11_EnterFullScreen(_THIS) +{ + int okay; +#if 0 + Window tmpwin, *windows; + int i, nwindows; +#endif + int x = 0, y = 0; + int real_w, real_h; + int screen_w; + int screen_h; + + okay = 1; + if ( currently_fullscreen ) { + return(okay); + } + + /* Ungrab the input so that we can move the mouse around */ + X11_GrabInputNoLock(this, SDL_GRAB_OFF); + +#if SDL_VIDEO_DRIVER_X11_XINERAMA + if ( use_xinerama && + window_w <= xinerama_info.width && + window_h <= xinerama_info.height ) { + x = xinerama_info.x_org; + y = xinerama_info.y_org; + } +#endif /* SDL_VIDEO_DRIVER_X11_XINERAMA */ + + /* Map the fullscreen window to blank the screen */ + screen_w = DisplayWidth(SDL_Display, SDL_Screen); + screen_h = DisplayHeight(SDL_Display, SDL_Screen); + get_real_resolution(this, &real_w, &real_h); + real_w = MAX(window_w, MAX(real_w, screen_w)); + real_h = MAX(window_h, MAX(real_h, screen_h)); + XMoveResizeWindow(SDL_Display, FSwindow, + x, y, real_w, real_h); + XMapRaised(SDL_Display, FSwindow); + X11_WaitMapped(this, FSwindow); + +#if 0 /* This seems to break WindowMaker in focus-follows-mouse mode */ + /* Make sure we got to the top of the window stack */ + if ( XQueryTree(SDL_Display, SDL_Root, &tmpwin, &tmpwin, + &windows, &nwindows) && windows ) { + /* If not, try to put us there - if fail... oh well */ + if ( windows[nwindows-1] != FSwindow ) { + tmpwin = windows[nwindows-1]; + for ( i=0; i<nwindows; ++i ) { + if ( windows[i] == FSwindow ) { + SDL_memcpy(&windows[i], &windows[i+1], + (nwindows-i-1)*sizeof(windows[i])); + break; + } + } + windows[nwindows-1] = FSwindow; + XRestackWindows(SDL_Display, windows, nwindows); + XSync(SDL_Display, False); + } + XFree(windows); + } +#else + XRaiseWindow(SDL_Display, FSwindow); +#endif + +#if SDL_VIDEO_DRIVER_X11_VIDMODE + /* Save the current video mode */ + if ( use_vidmode ) { + SDL_NAME(XF86VidModeLockModeSwitch)(SDL_Display, SDL_Screen, True); + save_mode(this); + } +#endif + currently_fullscreen = 1; + + /* Set the new resolution */ + okay = X11_ResizeFullScreen(this); + if ( ! okay ) { + X11_LeaveFullScreen(this); + } + /* Set the colormap */ + if ( SDL_XColorMap ) { + XInstallColormap(SDL_Display, SDL_XColorMap); + } + if ( okay ) { + X11_GrabInputNoLock(this, this->input_grab | SDL_GRAB_FULLSCREEN); + } + + /* We may need to refresh the screen at this point (no backing store) + We also don't get an event, which is why we explicitly refresh. */ + if ( this->screen ) { + if ( this->screen->flags & SDL_OPENGL ) { + SDL_PrivateExpose(); + } else { + X11_RefreshDisplay(this); + } + } + + return(okay); +} + +int X11_LeaveFullScreen(_THIS) +{ + if ( currently_fullscreen ) { + XReparentWindow(SDL_Display, SDL_Window, WMwindow, 0, 0); +#if SDL_VIDEO_DRIVER_X11_VIDMODE + if ( use_vidmode ) { + restore_mode(this); + SDL_NAME(XF86VidModeLockModeSwitch)(SDL_Display, SDL_Screen, False); + } +#endif + +#if SDL_VIDEO_DRIVER_X11_XME + if ( use_xme ) { + int rw, rh; + + /* check current mode so we can avoid uneccessary mode changes */ + get_real_resolution(this, &rw, &rh); + + if (rw != saved_res.width || rh != saved_res.height) { + XiGMiscChangeResolution(SDL_Display, + SDL_Screen, + 0, /* view */ + saved_res.width, + saved_res.height, + 0); + XSync(SDL_Display, False); + } + } +#endif + +#if SDL_VIDEO_DRIVER_X11_XRANDR + if ( use_xrandr ) { + XRRSetScreenConfig(SDL_Display, screen_config, SDL_Root, + saved_size_id, saved_rotation, CurrentTime); + } +#endif + + XUnmapWindow(SDL_Display, FSwindow); + X11_WaitUnmapped(this, FSwindow); + XSync(SDL_Display, True); /* Flush spurious mode change events */ + currently_fullscreen = 0; + } + /* If we get popped out of fullscreen mode for some reason, input_grab + will still have the SDL_GRAB_FULLSCREEN flag set, since this is only + temporary. In this case, release the grab unless the input has been + explicitly grabbed. + */ + X11_GrabInputNoLock(this, this->input_grab & ~SDL_GRAB_FULLSCREEN); + + /* We may need to refresh the screen at this point (no backing store) + We also don't get an event, which is why we explicitly refresh. */ + if ( this->screen ) { + if ( this->screen->flags & SDL_OPENGL ) { + SDL_PrivateExpose(); + } else { + X11_RefreshDisplay(this); + } + } + + return(0); +} diff --git a/3rdparty/SDL/src/video/x11/SDL_x11modes_c.h b/3rdparty/SDL/src/video/x11/SDL_x11modes_c.h new file mode 100644 index 0000000..f7780bf --- /dev/null +++ b/3rdparty/SDL/src/video/x11/SDL_x11modes_c.h @@ -0,0 +1,43 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* Utilities for getting and setting the X display mode */ + +#include "SDL_x11video.h" + +/* Define this if you want to grab the keyboard in fullscreen mode. + If you do not define this, SDL will return from SDL_SetVideoMode() + immediately, but will not actually go fullscreen until the window + manager is idle. +*/ +#define GRAB_FULLSCREEN + +extern int X11_GetVideoModes(_THIS); +extern SDL_Rect **X11_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags); +extern void X11_FreeVideoModes(_THIS); +extern int X11_ResizeFullScreen(_THIS); +extern void X11_WaitMapped(_THIS, Window win); +extern void X11_WaitUnmapped(_THIS, Window win); +extern void X11_QueueEnterFullScreen(_THIS); +extern int X11_EnterFullScreen(_THIS); +extern int X11_LeaveFullScreen(_THIS); diff --git a/3rdparty/SDL/src/video/x11/SDL_x11mouse.c b/3rdparty/SDL/src/video/x11/SDL_x11mouse.c new file mode 100644 index 0000000..16ad739 --- /dev/null +++ b/3rdparty/SDL/src/video/x11/SDL_x11mouse.c @@ -0,0 +1,288 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#include <X11/Xlib.h> +#include <X11/Xutil.h> + +#include "SDL_mouse.h" +#include "../../events/SDL_events_c.h" +#include "../SDL_cursor_c.h" +#include "SDL_x11dga_c.h" +#include "SDL_x11mouse_c.h" + + +/* The implementation dependent data for the window manager cursor */ +struct WMcursor { + Cursor x_cursor; +}; + + +void X11_FreeWMCursor(_THIS, WMcursor *cursor) +{ + if ( SDL_Display != NULL ) { + SDL_Lock_EventThread(); + XFreeCursor(SDL_Display, cursor->x_cursor); + XSync(SDL_Display, False); + SDL_Unlock_EventThread(); + } + SDL_free(cursor); +} + +WMcursor *X11_CreateWMCursor(_THIS, + Uint8 *data, Uint8 *mask, int w, int h, int hot_x, int hot_y) +{ + WMcursor *cursor; + XGCValues GCvalues; + GC GCcursor; + XImage *data_image, *mask_image; + Pixmap data_pixmap, mask_pixmap; + int clen, i; + char *x_data, *x_mask; + static XColor black = { 0, 0, 0, 0 }; + static XColor white = { 0xffff, 0xffff, 0xffff, 0xffff }; + + /* Allocate the cursor memory */ + cursor = (WMcursor *)SDL_malloc(sizeof(WMcursor)); + if ( cursor == NULL ) { + SDL_OutOfMemory(); + return(NULL); + } + + /* Mix the mask and the data */ + clen = (w/8)*h; + x_data = (char *)SDL_malloc(clen); + if ( x_data == NULL ) { + SDL_free(cursor); + SDL_OutOfMemory(); + return(NULL); + } + x_mask = (char *)SDL_malloc(clen); + if ( x_mask == NULL ) { + SDL_free(cursor); + SDL_free(x_data); + SDL_OutOfMemory(); + return(NULL); + } + for ( i=0; i<clen; ++i ) { + /* The mask is OR'd with the data to turn inverted color + pixels black since inverted color cursors aren't supported + under X11. + */ + x_mask[i] = data[i] | mask[i]; + x_data[i] = data[i]; + } + + /* Prevent the event thread from running while we use the X server */ + SDL_Lock_EventThread(); + + /* Create the data image */ + data_image = XCreateImage(SDL_Display, + DefaultVisual(SDL_Display, SDL_Screen), + 1, XYBitmap, 0, x_data, w, h, 8, w/8); + data_image->byte_order = MSBFirst; + data_image->bitmap_bit_order = MSBFirst; + data_pixmap = XCreatePixmap(SDL_Display, SDL_Root, w, h, 1); + + /* Create the data mask */ + mask_image = XCreateImage(SDL_Display, + DefaultVisual(SDL_Display, SDL_Screen), + 1, XYBitmap, 0, x_mask, w, h, 8, w/8); + mask_image->byte_order = MSBFirst; + mask_image->bitmap_bit_order = MSBFirst; + mask_pixmap = XCreatePixmap(SDL_Display, SDL_Root, w, h, 1); + + /* Create the graphics context */ + GCvalues.function = GXcopy; + GCvalues.foreground = ~0; + GCvalues.background = 0; + GCvalues.plane_mask = AllPlanes; + GCcursor = XCreateGC(SDL_Display, data_pixmap, + (GCFunction|GCForeground|GCBackground|GCPlaneMask), + &GCvalues); + + /* Blit the images to the pixmaps */ + XPutImage(SDL_Display, data_pixmap, GCcursor, data_image, + 0, 0, 0, 0, w, h); + XPutImage(SDL_Display, mask_pixmap, GCcursor, mask_image, + 0, 0, 0, 0, w, h); + XFreeGC(SDL_Display, GCcursor); + /* These free the x_data and x_mask memory pointers */ + XDestroyImage(data_image); + XDestroyImage(mask_image); + + /* Create the cursor */ + cursor->x_cursor = XCreatePixmapCursor(SDL_Display, data_pixmap, + mask_pixmap, &black, &white, hot_x, hot_y); + XFreePixmap(SDL_Display, data_pixmap); + XFreePixmap(SDL_Display, mask_pixmap); + + /* Release the event thread */ + XSync(SDL_Display, False); + SDL_Unlock_EventThread(); + + return(cursor); +} + +int X11_ShowWMCursor(_THIS, WMcursor *cursor) +{ + /* Don't do anything if the display is gone */ + if ( SDL_Display == NULL ) { + return(0); + } + + /* Set the X11 cursor cursor, or blank if cursor is NULL */ + if ( SDL_Window ) { + SDL_Lock_EventThread(); + if ( cursor == NULL ) { + if ( SDL_BlankCursor != NULL ) { + XDefineCursor(SDL_Display, SDL_Window, + SDL_BlankCursor->x_cursor); + } + } else { + XDefineCursor(SDL_Display, SDL_Window, cursor->x_cursor); + } + XSync(SDL_Display, False); + SDL_Unlock_EventThread(); + } + return(1); +} + +void X11_WarpWMCursor(_THIS, Uint16 x, Uint16 y) +{ + if ( using_dga & DGA_MOUSE ) { + SDL_PrivateMouseMotion(0, 0, x, y); + } else if ( mouse_relative) { + /* RJR: March 28, 2000 + leave physical cursor at center of screen if + mouse hidden and grabbed */ + SDL_PrivateMouseMotion(0, 0, x, y); + } else { + SDL_Lock_EventThread(); + XWarpPointer(SDL_Display, None, SDL_Window, 0, 0, 0, 0, x, y); + XSync(SDL_Display, False); + SDL_Unlock_EventThread(); + } +} + +/* Sets the mouse acceleration from a string of the form: + 2/1/0 + The first number is the numerator, followed by the acceleration + denumenator and threshold. +*/ +static void SetMouseAccel(_THIS, const char *accel_param) +{ + int i; + size_t len; + int accel_value[3]; + char *mouse_param, *mouse_param_buf, *pin; + + len = SDL_strlen(accel_param)+1; + mouse_param_buf = SDL_stack_alloc(char, len); + if ( ! mouse_param_buf ) { + return; + } + SDL_strlcpy(mouse_param_buf, accel_param, len); + mouse_param = mouse_param_buf; + + for ( i=0; (i < 3) && mouse_param; ++i ) { + pin = SDL_strchr(mouse_param, '/'); + if ( pin ) { + *pin = '\0'; + } + accel_value[i] = atoi(mouse_param); + if ( pin ) { + mouse_param = pin+1; + } else { + mouse_param = NULL; + } + } + if ( i == 3 ) { + XChangePointerControl(SDL_Display, True, True, + accel_value[0], accel_value[1], accel_value[2]); + } + SDL_stack_free(mouse_param_buf); +} + +/* Check to see if we need to enter or leave mouse relative mode */ +void X11_CheckMouseModeNoLock(_THIS) +{ + const Uint8 full_focus = (SDL_APPACTIVE|SDL_APPINPUTFOCUS|SDL_APPMOUSEFOCUS); + char *env_override; + int enable_relative = 1; + + /* This happens when quiting after an xio error */ + if ( SDL_Display == NULL ) + return; + + /* Allow the user to override the relative mouse mode. + They almost never want to do this, as it seriously affects + applications that rely on continuous relative mouse motion. + */ + env_override = SDL_getenv("SDL_MOUSE_RELATIVE"); + if ( env_override ) { + enable_relative = atoi(env_override); + } + + /* If the mouse is hidden and input is grabbed, we use relative mode */ + if ( enable_relative && + !(SDL_cursorstate & CURSOR_VISIBLE) && + (this->input_grab != SDL_GRAB_OFF) && + (SDL_GetAppState() & full_focus) == full_focus ) { + if ( ! mouse_relative ) { + X11_EnableDGAMouse(this); + if ( ! (using_dga & DGA_MOUSE) ) { + char *xmouse_accel; + + SDL_GetMouseState(&mouse_last.x, &mouse_last.y); + /* Use as raw mouse mickeys as possible */ + XGetPointerControl(SDL_Display, + &mouse_accel.numerator, + &mouse_accel.denominator, + &mouse_accel.threshold); + xmouse_accel=SDL_getenv("SDL_VIDEO_X11_MOUSEACCEL"); + if ( xmouse_accel ) { + SetMouseAccel(this, xmouse_accel); + } + } + mouse_relative = 1; + } + } else { + if ( mouse_relative ) { + if ( using_dga & DGA_MOUSE ) { + X11_DisableDGAMouse(this); + } else { + XChangePointerControl(SDL_Display, True, True, + mouse_accel.numerator, + mouse_accel.denominator, + mouse_accel.threshold); + } + mouse_relative = 0; + } + } +} +void X11_CheckMouseMode(_THIS) +{ + SDL_Lock_EventThread(); + X11_CheckMouseModeNoLock(this); + SDL_Unlock_EventThread(); +} diff --git a/3rdparty/SDL/src/video/x11/SDL_x11mouse_c.h b/3rdparty/SDL/src/video/x11/SDL_x11mouse_c.h new file mode 100644 index 0000000..03d97d8 --- /dev/null +++ b/3rdparty/SDL/src/video/x11/SDL_x11mouse_c.h @@ -0,0 +1,33 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#include "SDL_x11video.h" + +/* Functions to be exported */ +extern void X11_FreeWMCursor(_THIS, WMcursor *cursor); +extern WMcursor *X11_CreateWMCursor(_THIS, + Uint8 *data, Uint8 *mask, int w, int h, int hot_x, int hot_y); +extern int X11_ShowWMCursor(_THIS, WMcursor *cursor); +extern void X11_WarpWMCursor(_THIS, Uint16 x, Uint16 y); +extern void X11_CheckMouseModeNoLock(_THIS); +extern void X11_CheckMouseMode(_THIS); diff --git a/3rdparty/SDL/src/video/x11/SDL_x11sym.h b/3rdparty/SDL/src/video/x11/SDL_x11sym.h new file mode 100644 index 0000000..4875b98 --- /dev/null +++ b/3rdparty/SDL/src/video/x11/SDL_x11sym.h @@ -0,0 +1,201 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Sam Lantinga + slouken@libsdl.org +*/ + +SDL_X11_MODULE(BASEXLIB) +SDL_X11_SYM(XClassHint*,XAllocClassHint,(void),(),return) +SDL_X11_SYM(Status,XAllocColor,(Display* a,Colormap b,XColor* c),(a,b,c),return) +SDL_X11_SYM(XSizeHints*,XAllocSizeHints,(void),(),return) +SDL_X11_SYM(XWMHints*,XAllocWMHints,(void),(),return) +SDL_X11_SYM(int,XChangePointerControl,(Display* a,Bool b,Bool c,int d,int e,int f),(a,b,c,d,e,f),return) +SDL_X11_SYM(int,XChangeProperty,(Display* a,Window b,Atom c,Atom d,int e,int f,_Xconst unsigned char* g,int h),(a,b,c,d,e,f,g,h),return) +SDL_X11_SYM(int,XChangeWindowAttributes,(Display* a,Window b,unsigned long c,XSetWindowAttributes* d),(a,b,c,d),return) +SDL_X11_SYM(Bool,XCheckTypedEvent,(Display* a,int b,XEvent* c),(a,b,c),return) +SDL_X11_SYM(int,XClearWindow,(Display* a,Window b),(a,b),return) +SDL_X11_SYM(int,XCloseDisplay,(Display* a),(a),return) +SDL_X11_SYM(Colormap,XCreateColormap,(Display* a,Window b,Visual* c,int d),(a,b,c,d),return) +SDL_X11_SYM(Cursor,XCreatePixmapCursor,(Display* a,Pixmap b,Pixmap c,XColor* d,XColor* e,unsigned int f,unsigned int g),(a,b,c,d,e,f,g),return) +SDL_X11_SYM(GC,XCreateGC,(Display* a,Drawable b,unsigned long c,XGCValues* d),(a,b,c,d),return) +SDL_X11_SYM(XImage*,XCreateImage,(Display* a,Visual* b,unsigned int c,int d,int e,char* f,unsigned int g,unsigned int h,int i,int j),(a,b,c,d,e,f,g,h,i,j),return) +SDL_X11_SYM(Pixmap,XCreatePixmap,(Display* a,Drawable b,unsigned int c,unsigned int d,unsigned int e),(a,b,c,d,e),return) +SDL_X11_SYM(Pixmap,XCreatePixmapFromBitmapData,(Display* a,Drawable b,char* c,unsigned int d,unsigned int e,unsigned long f,unsigned long g,unsigned int h),(a,b,c,d,e,f,g,h),return) +SDL_X11_SYM(Window,XCreateSimpleWindow,(Display* a,Window b,int c,int d,unsigned int e,unsigned int f,unsigned int g,unsigned long h,unsigned long i),(a,b,c,d,e,f,g,h,i),return) +SDL_X11_SYM(Window,XCreateWindow,(Display* a,Window b,int c,int d,unsigned int e,unsigned int f,unsigned int g,int h,unsigned int i,Visual* j,unsigned long k,XSetWindowAttributes* l),(a,b,c,d,e,f,g,h,i,j,k,l),return) +SDL_X11_SYM(int,XDefineCursor,(Display* a,Window b,Cursor c),(a,b,c),return) +SDL_X11_SYM(int,XDeleteProperty,(Display* a,Window b,Atom c),(a,b,c),return) +SDL_X11_SYM(int,XDestroyWindow,(Display* a,Window b),(a,b),return) +SDL_X11_SYM(char*,XDisplayName,(_Xconst char* a),(a),return) +SDL_X11_SYM(int,XEventsQueued,(Display* a,int b),(a,b),return) +SDL_X11_SYM(Bool,XFilterEvent,(XEvent *event, Window w),(event,w),return) +SDL_X11_SYM(int,XFlush,(Display* a),(a),return) +SDL_X11_SYM(int,XFree,(void*a),(a),return) +SDL_X11_SYM(int,XFreeColormap,(Display* a,Colormap b),(a,b),return) +SDL_X11_SYM(int,XFreeColors,(Display* a,Colormap b,unsigned long* c,int d,unsigned long e),(a,b,c,d,e),return) +SDL_X11_SYM(int,XFreeCursor,(Display* a,Cursor b),(a,b),return) +SDL_X11_SYM(int,XFreeGC,(Display* a,GC b),(a,b),return) +SDL_X11_SYM(int,XFreeModifiermap,(XModifierKeymap* a),(a),return) +SDL_X11_SYM(int,XFreePixmap,(Display* a,Pixmap b),(a,b),return) +SDL_X11_SYM(int,XGetErrorDatabaseText,(Display* a,_Xconst char* b,_Xconst char* c,_Xconst char* d,char* e,int f),(a,b,c,d,e,f),return) +SDL_X11_SYM(XModifierKeymap*,XGetModifierMapping,(Display* a),(a),return) +SDL_X11_SYM(int,XGetPointerControl,(Display* a,int* b,int* c,int* d),(a,b,c,d),return) +SDL_X11_SYM(XVisualInfo*,XGetVisualInfo,(Display* a,long b,XVisualInfo* c,int* d),(a,b,c,d),return) +SDL_X11_SYM(XWMHints*,XGetWMHints,(Display* a,Window b),(a,b),return) +SDL_X11_SYM(Status,XGetWindowAttributes,(Display* a,Window b,XWindowAttributes* c),(a,b,c),return) +SDL_X11_SYM(int,XGrabKeyboard,(Display* a,Window b,Bool c,int d,int e,Time f),(a,b,c,d,e,f),return) +SDL_X11_SYM(int,XGrabPointer,(Display* a,Window b,Bool c,unsigned int d,int e,int f,Window g,Cursor h,Time i),(a,b,c,d,e,f,g,h,i),return) +SDL_X11_SYM(Status,XIconifyWindow,(Display* a,Window b,int c),(a,b,c),return) +SDL_X11_SYM(int,XInstallColormap,(Display* a,Colormap b),(a,b),return) +SDL_X11_SYM(KeyCode,XKeysymToKeycode,(Display* a,KeySym b),(a,b),return) +SDL_X11_SYM(Atom,XInternAtom,(Display* a,_Xconst char* b,Bool c),(a,b,c),return) +SDL_X11_SYM(XPixmapFormatValues*,XListPixmapFormats,(Display* a,int* b),(a,b),return) +SDL_X11_SYM(int,XLookupString,(XKeyEvent* a,char* b,int c,KeySym* d,XComposeStatus* e),(a,b,c,d,e),return) +SDL_X11_SYM(int,XMapRaised,(Display* a,Window b),(a,b),return) +SDL_X11_SYM(int,XMapWindow,(Display* a,Window b),(a,b),return) +SDL_X11_SYM(int,XMaskEvent,(Display* a,long b,XEvent* c),(a,b,c),return) +SDL_X11_SYM(Status,XMatchVisualInfo,(Display* a,int b,int c,int d,XVisualInfo* e),(a,b,c,d,e),return) +SDL_X11_SYM(int,XMissingExtension,(Display* a,_Xconst char* b),(a,b),return) +SDL_X11_SYM(int,XMoveResizeWindow,(Display* a,Window b,int c,int d,unsigned int e,unsigned int f),(a,b,c,d,e,f),return) +SDL_X11_SYM(int,XMoveWindow,(Display* a,Window b,int c,int d),(a,b,c,d),return) +SDL_X11_SYM(int,XNextEvent,(Display* a,XEvent* b),(a,b),return) +SDL_X11_SYM(Display*,XOpenDisplay,(_Xconst char* a),(a),return) +SDL_X11_SYM(int,XPeekEvent,(Display* a,XEvent* b),(a,b),return) +SDL_X11_SYM(int,XPending,(Display* a),(a),return) +SDL_X11_SYM(int,XPutImage,(Display* a,Drawable b,GC c,XImage* d,int e,int f,int g,int h,unsigned int i,unsigned int j),(a,b,c,d,e,f,g,h,i,j),return) +SDL_X11_SYM(int,XQueryColors,(Display* a,Colormap b,XColor* c,int d),(a,b,c,d),return) +SDL_X11_SYM(int,XQueryKeymap,(Display* a,char *b),(a,b),return) +SDL_X11_SYM(Bool,XQueryPointer,(Display* a,Window b,Window* c,Window* d,int* e,int* f,int* g,int* h,unsigned int* i),(a,b,c,d,e,f,g,h,i),return) +SDL_X11_SYM(int,XRaiseWindow,(Display* a,Window b),(a,b),return) +SDL_X11_SYM(int,XReparentWindow,(Display* a,Window b,Window c,int d,int e),(a,b,c,d,e),return) +SDL_X11_SYM(int,XResetScreenSaver,(Display* a),(a),return) +SDL_X11_SYM(int,XResizeWindow,(Display* a,Window b,unsigned int c,unsigned int d),(a,b,c,d),return) +SDL_X11_SYM(int,XSelectInput,(Display* a,Window b,long c),(a,b,c),return) +SDL_X11_SYM(Status,XSendEvent,(Display* a,Window b,Bool c,long d,XEvent* e),(a,b,c,d,e),return) +SDL_X11_SYM(int,XSetClassHint,(Display* a,Window b,XClassHint* c),(a,b,c),return) +SDL_X11_SYM(XErrorHandler,XSetErrorHandler,(XErrorHandler a),(a),return) +SDL_X11_SYM(XIOErrorHandler,XSetIOErrorHandler,(XIOErrorHandler a),(a),return) +SDL_X11_SYM(int,XSetTransientForHint,(Display* a,Window b,Window c),(a,b,c),return) +SDL_X11_SYM(int,XSetWMHints,(Display* a,Window b,XWMHints* c),(a,b,c),return) +SDL_X11_SYM(void,XSetTextProperty,(Display* a,Window b,XTextProperty* c,Atom d),(a,b,c,d),) +SDL_X11_SYM(void,XSetWMNormalHints,(Display* a,Window b,XSizeHints* c),(a,b,c),) +SDL_X11_SYM(Status,XSetWMProtocols,(Display* a,Window b,Atom* c,int d),(a,b,c,d),return) +SDL_X11_SYM(int,XSetWindowBackground,(Display* a,Window b,unsigned long c),(a,b,c),return) +SDL_X11_SYM(int,XSetWindowBackgroundPixmap,(Display* a,Window b,Pixmap c),(a,b,c),return) +SDL_X11_SYM(int,XSetWindowColormap,(Display* a,Window b,Colormap c),(a,b,c),return) +SDL_X11_SYM(int,XStoreColors,(Display* a,Colormap b,XColor* c,int d),(a,b,c,d),return) +SDL_X11_SYM(Status,XStringListToTextProperty,(char** a,int b,XTextProperty* c),(a,b,c),return) +SDL_X11_SYM(int,XSync,(Display* a,Bool b),(a,b),return) +SDL_X11_SYM(int,XUngrabKeyboard,(Display* a,Time b),(a,b),return) +SDL_X11_SYM(int,XUngrabPointer,(Display* a,Time b),(a,b),return) +SDL_X11_SYM(int,XUnmapWindow,(Display* a,Window b),(a,b),return) +SDL_X11_SYM(int,XWarpPointer,(Display* a,Window b,Window c,int d,int e,unsigned int f,unsigned int g,int h, int i),(a,b,c,d,e,f,g,h,i),return) +SDL_X11_SYM(VisualID,XVisualIDFromVisual,(Visual* a),(a),return) +SDL_X11_SYM(XExtDisplayInfo*,XextAddDisplay,(XExtensionInfo* a,Display* b,char* c,XExtensionHooks* d,int e,XPointer f),(a,b,c,d,e,f),return) +SDL_X11_SYM(XExtensionInfo*,XextCreateExtension,(void),(),return) +SDL_X11_SYM(void,XextDestroyExtension,(XExtensionInfo* a),(a),) +SDL_X11_SYM(XExtDisplayInfo*,XextFindDisplay,(XExtensionInfo* a,Display* b),(a,b),return) +SDL_X11_SYM(int,XextRemoveDisplay,(XExtensionInfo* a,Display* b),(a,b),return) +SDL_X11_SYM(Bool,XQueryExtension,(Display* a,_Xconst char* b,int* c,int* d,int* e),(a,b,c,d,e),return) +SDL_X11_SYM(char *,XDisplayString,(Display* a),(a),return) +SDL_X11_SYM(int,XGetErrorText,(Display* a,int b,char* c,int d),(a,b,c,d),return) +SDL_X11_SYM(void,_XEatData,(Display* a,unsigned long b),(a,b),) +SDL_X11_SYM(void,_XFlush,(Display* a),(a),) +SDL_X11_SYM(void,_XFlushGCCache,(Display* a,GC b),(a,b),) +SDL_X11_SYM(int,_XRead,(Display* a,char* b,long c),(a,b,c),return) +SDL_X11_SYM(void,_XReadPad,(Display* a,char* b,long c),(a,b,c),) +SDL_X11_SYM(void,_XSend,(Display* a,_Xconst char* b,long c),(a,b,c),) +SDL_X11_SYM(Status,_XReply,(Display* a,xReply* b,int c,Bool d),(a,b,c,d),return) +SDL_X11_SYM(unsigned long,_XSetLastRequestRead,(Display* a,xGenericReply* b),(a,b),return) +SDL_X11_SYM(SDL_X11_XSynchronizeRetType,XSynchronize,(Display* a,Bool b),(a,b),return) +SDL_X11_SYM(SDL_X11_XESetWireToEventRetType,XESetWireToEvent,(Display* a,int b,SDL_X11_XESetWireToEventRetType c),(a,b,c),return) +SDL_X11_SYM(SDL_X11_XESetEventToWireRetType,XESetEventToWire,(Display* a,int b,SDL_X11_XESetEventToWireRetType c),(a,b,c),return) +SDL_X11_SYM(XExtensionErrorHandler,XSetExtensionErrorHandler,(XExtensionErrorHandler a),(a),return) + +#if NeedWidePrototypes +SDL_X11_SYM(KeySym,XKeycodeToKeysym,(Display* a,unsigned int b,int c),(a,b,c),return) +#else +SDL_X11_SYM(KeySym,XKeycodeToKeysym,(Display* a,KeyCode b,int c),(a,b,c),return) +#endif + +#ifdef X_HAVE_UTF8_STRING +SDL_X11_MODULE(UTF8) +SDL_X11_SYM(int,Xutf8TextListToTextProperty,(Display* a,char** b,int c,XICCEncodingStyle d,XTextProperty* e),(a,b,c,d,e),return) +SDL_X11_SYM(int,Xutf8LookupString,(XIC a,XKeyPressedEvent* b,char* c,int d,KeySym* e,Status* f),(a,b,c,d,e,f),return) +/*SDL_X11_SYM(XIC,XCreateIC,(XIM, ...),return) !!! ARGH! */ +SDL_X11_SYM(void,XDestroyIC,(XIC a),(a),) +SDL_X11_SYM(void,XSetICFocus,(XIC a),(a),) +SDL_X11_SYM(void,XUnsetICFocus,(XIC a),(a),) +/*SDL_X11_SYM(char*,XGetICValues,(XIC a, ...),return)*/ +SDL_X11_SYM(XIM,XOpenIM,(Display* a,struct _XrmHashBucketRec* b,char* c,char* d),(a,b,c,d),return) +SDL_X11_SYM(Status,XCloseIM,(XIM a),(a),return) +SDL_X11_SYM(char*,XSetLocaleModifiers,(_Xconst char* a),(a),return) +SDL_X11_SYM(int,XRefreshKeyboardMapping,(XMappingEvent* a),(a),return) +SDL_X11_SYM(Display*,XDisplayOfIM,(XIM a),(a),return) +#endif + +#ifndef NO_SHARED_MEMORY +SDL_X11_MODULE(SHM) +SDL_X11_SYM(Status,XShmAttach,(Display* a,XShmSegmentInfo* b),(a,b),return) +SDL_X11_SYM(Status,XShmDetach,(Display* a,XShmSegmentInfo* b),(a,b),return) +SDL_X11_SYM(Status,XShmPutImage,(Display* a,Drawable b,GC c,XImage* d,int e,int f,int g,int h,unsigned int i,unsigned int j,Bool k),(a,b,c,d,e,f,g,h,i,j,k),return) +SDL_X11_SYM(XImage*,XShmCreateImage,(Display* a,Visual* b,unsigned int c,int d,char* e,XShmSegmentInfo* f,unsigned int g,unsigned int h),(a,b,c,d,e,f,g,h),return) +SDL_X11_SYM(Bool,XShmQueryExtension,(Display* a),(a),return) +#endif + +/* + * Not required...these only exist in code in headers on some 64-bit platforms, + * and are removed via macros elsewhere, so it's safe for them to be missing. + */ +#ifdef LONG64 +SDL_X11_MODULE(IO_32BIT) +SDL_X11_SYM(int,_XData32,(Display *dpy,register long *data,unsigned len),(dpy,data,len),return) +SDL_X11_SYM(void,_XRead32,(Display *dpy,register long *data,long len),(dpy,data,len),) +#endif + +/* + * libX11 1.4.99.1 added _XGetRequest, and macros use it behind the scenes. + */ +SDL_X11_MODULE(XGETREQUEST) +SDL_X11_SYM(void *,_XGetRequest,(Display* a,CARD8 b,size_t c),(a,b,c),return) + +/* + * These only show up on some variants of Unix. + */ +#if defined(__osf__) +SDL_X11_MODULE(OSF_ENTRY_POINTS) +SDL_X11_SYM(void,_SmtBufferOverflow,(Display *dpy,register smtDisplayPtr p),(dpy,p),) +SDL_X11_SYM(void,_SmtIpError,(Display *dpy,register smtDisplayPtr p, int i),(dpy,p,i),) +SDL_X11_SYM(int,ipAllocateData,(ChannelPtr a, IPCard b, IPDataPtr * c),(a,b,c),return) +SDL_X11_SYM(int,ipUnallocateAndSendData,(ChannelPtr a, IPCard b),(a,b),return) +#endif + +/* Xrandr support. */ +#if SDL_VIDEO_DRIVER_X11_XRANDR +SDL_X11_MODULE(XRANDR) +SDL_X11_SYM(Status,XRRQueryVersion,(Display *dpy,int *major_versionp,int *minor_versionp),(dpy,major_versionp,minor_versionp),return) +SDL_X11_SYM(XRRScreenConfiguration *,XRRGetScreenInfo,(Display *dpy,Drawable draw),(dpy,draw),return) +SDL_X11_SYM(SizeID,XRRConfigCurrentConfiguration,(XRRScreenConfiguration *config,Rotation *rotation),(config,rotation),return) +SDL_X11_SYM(XRRScreenSize *,XRRConfigSizes,(XRRScreenConfiguration *config, int *nsizes),(config,nsizes),return) +SDL_X11_SYM(Status,XRRSetScreenConfig,(Display *dpy, XRRScreenConfiguration *config, Drawable draw, int size_index, Rotation rotation, Time timestamp),(dpy,config,draw,size_index,rotation,timestamp),return) +SDL_X11_SYM(void,XRRFreeScreenConfigInfo,(XRRScreenConfiguration *config),(config),) +#endif + +/* end of SDL_x11sym.h ... */ + diff --git a/3rdparty/SDL/src/video/x11/SDL_x11video.c b/3rdparty/SDL/src/video/x11/SDL_x11video.c new file mode 100644 index 0000000..f7d8073 --- /dev/null +++ b/3rdparty/SDL/src/video/x11/SDL_x11video.c @@ -0,0 +1,1571 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* X11 based SDL video driver implementation. + Note: This implementation does not currently need X11 thread locking, + since the event thread uses a separate X connection and any + additional locking necessary is handled internally. However, + if full locking is neccessary, take a look at XInitThreads(). +*/ + +#include <unistd.h> +#include <sys/ioctl.h> +#ifdef MTRR_SUPPORT +#include <asm/mtrr.h> +#include <sys/fcntl.h> +#endif + +#include "SDL_endian.h" +#include "SDL_timer.h" +#include "SDL_thread.h" +#include "SDL_video.h" +#include "SDL_mouse.h" +#include "../SDL_sysvideo.h" +#include "../SDL_pixels_c.h" +#include "../../events/SDL_events_c.h" +#include "SDL_x11video.h" +#include "SDL_x11wm_c.h" +#include "SDL_x11mouse_c.h" +#include "SDL_x11events_c.h" +#include "SDL_x11modes_c.h" +#include "SDL_x11image_c.h" +#include "SDL_x11yuv_c.h" +#include "SDL_x11gl_c.h" +#include "SDL_x11gamma_c.h" +#include "../blank_cursor.h" + +#ifdef X_HAVE_UTF8_STRING +#include <locale.h> +#endif + +/* Initialization/Query functions */ +static int X11_VideoInit(_THIS, SDL_PixelFormat *vformat); +static SDL_Surface *X11_SetVideoMode(_THIS, SDL_Surface *current, int width, int height, int bpp, Uint32 flags); +static int X11_ToggleFullScreen(_THIS, int on); +static void X11_UpdateMouse(_THIS); +static int X11_SetColors(_THIS, int firstcolor, int ncolors, + SDL_Color *colors); +static int X11_SetGammaRamp(_THIS, Uint16 *ramp); +static void X11_VideoQuit(_THIS); + + +/* X11 driver bootstrap functions */ + +static int X11_Available(void) +{ + Display *display = NULL; + if ( SDL_X11_LoadSymbols() ) { + display = XOpenDisplay(NULL); + if ( display != NULL ) { + XCloseDisplay(display); + } + SDL_X11_UnloadSymbols(); + } + return(display != NULL); +} + +static void X11_DeleteDevice(SDL_VideoDevice *device) +{ + if ( device ) { + if ( device->hidden ) { + SDL_free(device->hidden); + } + if ( device->gl_data ) { + SDL_free(device->gl_data); + } + SDL_free(device); + SDL_X11_UnloadSymbols(); + } +} + +static SDL_VideoDevice *X11_CreateDevice(int devindex) +{ + SDL_VideoDevice *device = NULL; + + if ( SDL_X11_LoadSymbols() ) { + /* Initialize all variables that we clean on shutdown */ + device = (SDL_VideoDevice *)SDL_malloc(sizeof(SDL_VideoDevice)); + if ( device ) { + SDL_memset(device, 0, (sizeof *device)); + device->hidden = (struct SDL_PrivateVideoData *) + SDL_malloc((sizeof *device->hidden)); + device->gl_data = (struct SDL_PrivateGLData *) + SDL_malloc((sizeof *device->gl_data)); + } + if ( (device == NULL) || (device->hidden == NULL) || + (device->gl_data == NULL) ) { + SDL_OutOfMemory(); + X11_DeleteDevice(device); /* calls SDL_X11_UnloadSymbols(). */ + return(0); + } + SDL_memset(device->hidden, 0, (sizeof *device->hidden)); + SDL_memset(device->gl_data, 0, (sizeof *device->gl_data)); + +#if SDL_VIDEO_OPENGL_GLX + device->gl_data->swap_interval = -1; +#endif + + /* Set the driver flags */ + device->handles_any_size = 1; + + /* Set the function pointers */ + device->VideoInit = X11_VideoInit; + device->ListModes = X11_ListModes; + device->SetVideoMode = X11_SetVideoMode; + device->ToggleFullScreen = X11_ToggleFullScreen; + device->UpdateMouse = X11_UpdateMouse; +#if SDL_VIDEO_DRIVER_X11_XV + device->CreateYUVOverlay = X11_CreateYUVOverlay; +#endif + device->SetColors = X11_SetColors; + device->UpdateRects = NULL; + device->VideoQuit = X11_VideoQuit; + device->AllocHWSurface = X11_AllocHWSurface; + device->CheckHWBlit = NULL; + device->FillHWRect = NULL; + device->SetHWColorKey = NULL; + device->SetHWAlpha = NULL; + device->LockHWSurface = X11_LockHWSurface; + device->UnlockHWSurface = X11_UnlockHWSurface; + device->FlipHWSurface = X11_FlipHWSurface; + device->FreeHWSurface = X11_FreeHWSurface; + device->SetGamma = X11_SetVidModeGamma; + device->GetGamma = X11_GetVidModeGamma; + device->SetGammaRamp = X11_SetGammaRamp; + device->GetGammaRamp = NULL; +#if SDL_VIDEO_OPENGL_GLX + device->GL_LoadLibrary = X11_GL_LoadLibrary; + device->GL_GetProcAddress = X11_GL_GetProcAddress; + device->GL_GetAttribute = X11_GL_GetAttribute; + device->GL_MakeCurrent = X11_GL_MakeCurrent; + device->GL_SwapBuffers = X11_GL_SwapBuffers; +#endif + device->SetCaption = X11_SetCaption; + device->SetIcon = X11_SetIcon; + device->IconifyWindow = X11_IconifyWindow; + device->GrabInput = X11_GrabInput; + device->GetWMInfo = X11_GetWMInfo; + device->FreeWMCursor = X11_FreeWMCursor; + device->CreateWMCursor = X11_CreateWMCursor; + device->ShowWMCursor = X11_ShowWMCursor; + device->WarpWMCursor = X11_WarpWMCursor; + device->CheckMouseMode = X11_CheckMouseMode; + device->InitOSKeymap = X11_InitOSKeymap; + device->PumpEvents = X11_PumpEvents; + + device->free = X11_DeleteDevice; + } + + return device; +} + +VideoBootStrap X11_bootstrap = { + "x11", "X Window System", + X11_Available, X11_CreateDevice +}; + +/* Normal X11 error handler routine */ +static int (*X_handler)(Display *, XErrorEvent *) = NULL; +static int x_errhandler(Display *d, XErrorEvent *e) +{ +#if SDL_VIDEO_DRIVER_X11_VIDMODE + extern int vm_error; +#endif +#if SDL_VIDEO_DRIVER_X11_DGAMOUSE + extern int dga_error; +#endif + +#if SDL_VIDEO_DRIVER_X11_VIDMODE + /* VidMode errors are non-fatal. :) */ + /* Are the errors offset by one from the error base? + e.g. the error base is 143, the code is 148, and the + actual error is XF86VidModeExtensionDisabled (4) ? + */ + if ( (vm_error >= 0) && + (((e->error_code == BadRequest)&&(e->request_code == vm_error)) || + ((e->error_code > vm_error) && + (e->error_code <= (vm_error+XF86VidModeNumberErrors)))) ) { +#ifdef X11_DEBUG +{ char errmsg[1024]; + XGetErrorText(d, e->error_code, errmsg, sizeof(errmsg)); +printf("VidMode error: %s\n", errmsg); +} +#endif + return(0); + } +#endif /* SDL_VIDEO_DRIVER_X11_VIDMODE */ + +#if SDL_VIDEO_DRIVER_X11_DGAMOUSE + /* DGA errors can be non-fatal. :) */ + if ( (dga_error >= 0) && + ((e->error_code > dga_error) && + (e->error_code <= (dga_error+XF86DGANumberErrors))) ) { +#ifdef X11_DEBUG +{ char errmsg[1024]; + XGetErrorText(d, e->error_code, errmsg, sizeof(errmsg)); +printf("DGA error: %s\n", errmsg); +} +#endif + return(0); + } +#endif /* SDL_VIDEO_DRIVER_X11_DGAMOUSE */ + + return(X_handler(d,e)); +} + +/* X11 I/O error handler routine */ +static int (*XIO_handler)(Display *) = NULL; +static int xio_errhandler(Display *d) +{ + /* Ack! Lost X11 connection! */ + + /* We will crash if we try to clean up our display */ + if ( SDL_VideoSurface && current_video->hidden->Ximage ) { + SDL_VideoSurface->pixels = NULL; + } + current_video->hidden->X11_Display = NULL; + + /* Continue with the standard X11 error handler */ + return(XIO_handler(d)); +} + +static int (*Xext_handler)(Display *, _Xconst char *, _Xconst char *) = NULL; +static int xext_errhandler(Display *d, _Xconst char *ext, _Xconst char *reason) +{ +#ifdef X11_DEBUG + printf("Xext error inside SDL (may be harmless):\n"); + printf(" Extension \"%s\" %s on display \"%s\".\n", + ext, reason, XDisplayString(d)); +#endif + + if (SDL_strcmp(reason, "missing") == 0) { + /* + * Since the query itself, elsewhere, can handle a missing extension + * and the default behaviour in Xlib is to write to stderr, which + * generates unnecessary bug reports, we just ignore these. + */ + return 0; + } + + /* Everything else goes to the default handler... */ + return Xext_handler(d, ext, reason); +} + +/* Find out what class name we should use */ +static char *get_classname(char *classname, int maxlen) +{ + char *spot; +#if defined(__LINUX__) || defined(__FREEBSD__) + char procfile[1024]; + char linkfile[1024]; + int linksize; +#endif + + /* First allow environment variable override */ + spot = SDL_getenv("SDL_VIDEO_X11_WMCLASS"); + if ( spot ) { + SDL_strlcpy(classname, spot, maxlen); + return classname; + } + + /* Next look at the application's executable name */ +#if defined(__LINUX__) || defined(__FREEBSD__) +#if defined(__LINUX__) + SDL_snprintf(procfile, SDL_arraysize(procfile), "/proc/%d/exe", getpid()); +#elif defined(__FREEBSD__) + SDL_snprintf(procfile, SDL_arraysize(procfile), "/proc/%d/file", getpid()); +#else +#error Where can we find the executable name? +#endif + linksize = readlink(procfile, linkfile, sizeof(linkfile)-1); + if ( linksize > 0 ) { + linkfile[linksize] = '\0'; + spot = SDL_strrchr(linkfile, '/'); + if ( spot ) { + SDL_strlcpy(classname, spot+1, maxlen); + } else { + SDL_strlcpy(classname, linkfile, maxlen); + } + return classname; + } +#endif /* __LINUX__ */ + + /* Finally use the default we've used forever */ + SDL_strlcpy(classname, "SDL_App", maxlen); + return classname; +} + +/* Create auxiliary (toplevel) windows with the current visual */ +static void create_aux_windows(_THIS) +{ + int x = 0, y = 0; + char classname[1024]; + XSetWindowAttributes xattr; + XWMHints *hints; + unsigned long app_event_mask; + int def_vis = (SDL_Visual == DefaultVisual(SDL_Display, SDL_Screen)); + + /* Look up some useful Atoms */ + WM_DELETE_WINDOW = XInternAtom(SDL_Display, "WM_DELETE_WINDOW", False); + + /* Don't create any extra windows if we are being managed */ + if ( SDL_windowid ) { + FSwindow = 0; + WMwindow = SDL_strtol(SDL_windowid, NULL, 0); + return; + } + + if(FSwindow) + XDestroyWindow(SDL_Display, FSwindow); + +#if SDL_VIDEO_DRIVER_X11_XINERAMA + if ( use_xinerama ) { + x = xinerama_info.x_org; + y = xinerama_info.y_org; + } +#endif + xattr.override_redirect = True; + xattr.background_pixel = def_vis ? BlackPixel(SDL_Display, SDL_Screen) : 0; + xattr.border_pixel = 0; + xattr.colormap = SDL_XColorMap; + + FSwindow = XCreateWindow(SDL_Display, SDL_Root, + x, y, 32, 32, 0, + this->hidden->depth, InputOutput, SDL_Visual, + CWOverrideRedirect | CWBackPixel | CWBorderPixel + | CWColormap, + &xattr); + + XSelectInput(SDL_Display, FSwindow, StructureNotifyMask); + + /* Tell KDE to keep the fullscreen window on top */ + { + XEvent ev; + long mask; + + SDL_memset(&ev, 0, sizeof(ev)); + ev.xclient.type = ClientMessage; + ev.xclient.window = SDL_Root; + ev.xclient.message_type = XInternAtom(SDL_Display, + "KWM_KEEP_ON_TOP", False); + ev.xclient.format = 32; + ev.xclient.data.l[0] = FSwindow; + ev.xclient.data.l[1] = CurrentTime; + mask = SubstructureRedirectMask; + XSendEvent(SDL_Display, SDL_Root, False, mask, &ev); + } + + hints = NULL; + if(WMwindow) { + /* All window attributes must survive the recreation */ + hints = XGetWMHints(SDL_Display, WMwindow); + XDestroyWindow(SDL_Display, WMwindow); + } + + /* Create the window for windowed management */ + /* (reusing the xattr structure above) */ + WMwindow = XCreateWindow(SDL_Display, SDL_Root, + x, y, 32, 32, 0, + this->hidden->depth, InputOutput, SDL_Visual, + CWBackPixel | CWBorderPixel | CWColormap, + &xattr); + + /* Set the input hints so we get keyboard input */ + if(!hints) { + hints = XAllocWMHints(); + hints->input = True; + hints->flags = InputHint; + } + XSetWMHints(SDL_Display, WMwindow, hints); + XFree(hints); + X11_SetCaptionNoLock(this, this->wm_title, this->wm_icon); + + app_event_mask = FocusChangeMask | KeyPressMask | KeyReleaseMask + | PropertyChangeMask | StructureNotifyMask | KeymapStateMask; + XSelectInput(SDL_Display, WMwindow, app_event_mask); + + /* Set the class hints so we can get an icon (AfterStep) */ + get_classname(classname, sizeof(classname)); + { + XClassHint *classhints; + classhints = XAllocClassHint(); + if(classhints != NULL) { + classhints->res_name = classname; + classhints->res_class = classname; + XSetClassHint(SDL_Display, WMwindow, classhints); + XFree(classhints); + } + } + + { + pid_t pid = getpid(); + char hostname[256]; + + if (pid > 0 && gethostname(hostname, sizeof(hostname)) > -1) { + Atom _NET_WM_PID = XInternAtom(SDL_Display, "_NET_WM_PID", False); + Atom WM_CLIENT_MACHINE = XInternAtom(SDL_Display, "WM_CLIENT_MACHINE", False); + + hostname[sizeof(hostname)-1] = '\0'; + XChangeProperty(SDL_Display, WMwindow, _NET_WM_PID, XA_CARDINAL, 32, + PropModeReplace, (unsigned char *)&pid, 1); + XChangeProperty(SDL_Display, WMwindow, WM_CLIENT_MACHINE, XA_STRING, 8, + PropModeReplace, (unsigned char *)hostname, SDL_strlen(hostname)); + } + } + + /* Setup the communication with the IM server */ + /* create_aux_windows may be called several times against the same + Display. We should reuse the SDL_IM if one has been opened for + the Display, so we should not simply reset SDL_IM here. */ + + #ifdef X_HAVE_UTF8_STRING + if (SDL_X11_HAVE_UTF8) { + /* Discard obsolete resources if any. */ + if (SDL_IM != NULL && SDL_Display != XDisplayOfIM(SDL_IM)) { + /* Just a double check. I don't think this + code is ever executed. */ + SDL_SetError("display has changed while an IM is kept"); + if (SDL_IC) { + XUnsetICFocus(SDL_IC); + XDestroyIC(SDL_IC); + SDL_IC = NULL; + } + XCloseIM(SDL_IM); + SDL_IM = NULL; + } + + /* Open an input method. */ + if (SDL_IM == NULL) { + char *old_locale = NULL, *old_modifiers = NULL; + const char *p; + size_t n; + /* I'm not comfortable to do locale setup + here. However, we need C library locale + (and xlib modifiers) to be set based on the + user's preference to use XIM, and many + existing game programs doesn't take care of + users' locale preferences, so someone other + than the game program should do it. + Moreover, ones say that some game programs + heavily rely on the C locale behaviour, + e.g., strcol()'s, and we can't change the C + library locale. Given the situation, I + couldn't find better place to do the + job... */ + + /* Save the current (application program's) + locale settings. */ + p = setlocale(LC_ALL, NULL); + if ( p ) { + n = SDL_strlen(p)+1; + old_locale = SDL_stack_alloc(char, n); + if ( old_locale ) { + SDL_strlcpy(old_locale, p, n); + } + } + p = XSetLocaleModifiers(NULL); + if ( p ) { + n = SDL_strlen(p)+1; + old_modifiers = SDL_stack_alloc(char, n); + if ( old_modifiers ) { + SDL_strlcpy(old_modifiers, p, n); + } + } + + /* Fetch the user's preferences and open the + input method with them. */ + setlocale(LC_ALL, ""); + XSetLocaleModifiers(""); + SDL_IM = XOpenIM(SDL_Display, NULL, classname, classname); + + /* Restore the application's locale settings + so that we don't break the application's + expected behaviour. */ + if ( old_locale ) { + /* We need to restore the C library + locale first, since the + interpretation of the X modifier + may depend on it. */ + setlocale(LC_ALL, old_locale); + SDL_stack_free(old_locale); + } + if ( old_modifiers ) { + XSetLocaleModifiers(old_modifiers); + SDL_stack_free(old_modifiers); + } + } + + /* Create a new input context for the new window just created. */ + if (SDL_IM == NULL) { + SDL_SetError("no input method could be opened"); + } else { + if (SDL_IC != NULL) { + /* Discard the old IC before creating new one. */ + XUnsetICFocus(SDL_IC); + XDestroyIC(SDL_IC); + } + /* Theoretically we should check the current IM supports + PreeditNothing+StatusNothing style (i.e., root window method) + before creating the IC. However, it is the bottom line method, + and we supports any other options. If the IM didn't support + root window method, the following call fails, and SDL falls + back to pre-XIM keyboard handling. */ + SDL_IC = pXCreateIC(SDL_IM, + XNClientWindow, WMwindow, + XNFocusWindow, WMwindow, + XNInputStyle, XIMPreeditNothing | XIMStatusNothing, + XNResourceName, classname, + XNResourceClass, classname, + NULL); + + if (SDL_IC == NULL) { + SDL_SetError("no input context could be created"); + XCloseIM(SDL_IM); + SDL_IM = NULL; + } else { + /* We need to receive X events that an IM wants and to pass + them to the IM through XFilterEvent. The set of events may + vary depending on the IM implementation and the options + specified through various routes. Although unlikely, the + xlib specification allows IM to change the event requirement + with its own circumstances, it is safe to call SelectInput + whenever we re-create an IC. */ + unsigned long mask = 0; + char *ret = pXGetICValues(SDL_IC, XNFilterEvents, &mask, NULL); + if (ret != NULL) { + XUnsetICFocus(SDL_IC); + XDestroyIC(SDL_IC); + SDL_IC = NULL; + SDL_SetError("no input context could be created"); + XCloseIM(SDL_IM); + SDL_IM = NULL; + } else { + XSelectInput(SDL_Display, WMwindow, app_event_mask | mask); + XSetICFocus(SDL_IC); + } + } + } + } + #endif + + /* Allow the window to be deleted by the window manager */ + XSetWMProtocols(SDL_Display, WMwindow, &WM_DELETE_WINDOW, 1); +} + +static int X11_VideoInit(_THIS, SDL_PixelFormat *vformat) +{ + const char *env; + char *display; + int i; + + /* Open the X11 display */ + display = NULL; /* Get it from DISPLAY environment variable */ + + if ( (SDL_strncmp(XDisplayName(display), ":", 1) == 0) || + (SDL_strncmp(XDisplayName(display), "unix:", 5) == 0) ) { + local_X11 = 1; + } else { + local_X11 = 0; + } + SDL_Display = XOpenDisplay(display); +#if defined(__osf__) && defined(SDL_VIDEO_DRIVER_X11_DYNAMIC) + /* On Tru64 if linking without -lX11, it fails and you get following message. + * Xlib: connection to ":0.0" refused by server + * Xlib: XDM authorization key matches an existing client! + * + * It succeeds if retrying 1 second later + * or if running xhost +localhost on shell. + * + */ + if ( SDL_Display == NULL ) { + SDL_Delay(1000); + SDL_Display = XOpenDisplay(display); + } +#endif + if ( SDL_Display == NULL ) { + SDL_SetError("Couldn't open X11 display"); + return(-1); + } +#ifdef X11_DEBUG + XSynchronize(SDL_Display, True); +#endif + + /* Create an alternate X display for graphics updates -- allows us + to do graphics updates in a separate thread from event handling. + Thread-safe X11 doesn't seem to exist. + */ + GFX_Display = XOpenDisplay(display); + if ( GFX_Display == NULL ) { + XCloseDisplay(SDL_Display); + SDL_Display = NULL; + SDL_SetError("Couldn't open X11 display"); + return(-1); + } + + /* Set the normal X error handler */ + X_handler = XSetErrorHandler(x_errhandler); + + /* Set the error handler if we lose the X display */ + XIO_handler = XSetIOErrorHandler(xio_errhandler); + + /* Set the X extension error handler */ + Xext_handler = XSetExtensionErrorHandler(xext_errhandler); + + /* use default screen (from $DISPLAY) */ + SDL_Screen = DefaultScreen(SDL_Display); + +#ifndef NO_SHARED_MEMORY + /* Check for MIT shared memory extension */ + use_mitshm = 0; + if ( local_X11 ) { + use_mitshm = XShmQueryExtension(SDL_Display); + } +#endif /* NO_SHARED_MEMORY */ + + /* Get the available video modes */ + if(X11_GetVideoModes(this) < 0) { + XCloseDisplay(GFX_Display); + GFX_Display = NULL; + XCloseDisplay(SDL_Display); + SDL_Display = NULL; + return -1; + } + + /* Determine the current screen size */ + this->info.current_w = DisplayWidth(SDL_Display, SDL_Screen); + this->info.current_h = DisplayHeight(SDL_Display, SDL_Screen); + + /* Determine the default screen depth: + Use the default visual (or at least one with the same depth) */ + SDL_DisplayColormap = DefaultColormap(SDL_Display, SDL_Screen); + for(i = 0; i < this->hidden->nvisuals; i++) + if(this->hidden->visuals[i].depth == DefaultDepth(SDL_Display, + SDL_Screen)) + break; + if(i == this->hidden->nvisuals) { + /* default visual was useless, take the deepest one instead */ + i = 0; + } + SDL_Visual = this->hidden->visuals[i].visual; + if ( SDL_Visual == DefaultVisual(SDL_Display, SDL_Screen) ) { + SDL_XColorMap = SDL_DisplayColormap; + } else { + SDL_XColorMap = XCreateColormap(SDL_Display, SDL_Root, + SDL_Visual, AllocNone); + } + this->hidden->depth = this->hidden->visuals[i].depth; + vformat->BitsPerPixel = this->hidden->visuals[i].bpp; + if ( vformat->BitsPerPixel > 8 ) { + vformat->Rmask = SDL_Visual->red_mask; + vformat->Gmask = SDL_Visual->green_mask; + vformat->Bmask = SDL_Visual->blue_mask; + } + if ( this->hidden->depth == 32 ) { + vformat->Amask = (0xFFFFFFFF & ~(vformat->Rmask|vformat->Gmask|vformat->Bmask)); + } + X11_SaveVidModeGamma(this); + + /* Allow environment override of screensaver disable. */ + env = SDL_getenv("SDL_VIDEO_ALLOW_SCREENSAVER"); + if ( env ) { + allow_screensaver = SDL_atoi(env); + } else { +#ifdef SDL_VIDEO_DISABLE_SCREENSAVER + allow_screensaver = 0; +#else + allow_screensaver = 1; +#endif + } + + /* See if we have been passed a window to use */ + SDL_windowid = SDL_getenv("SDL_WINDOWID"); + + /* Create the fullscreen and managed windows */ + create_aux_windows(this); + + /* Create the blank cursor */ + SDL_BlankCursor = this->CreateWMCursor(this, blank_cdata, blank_cmask, + BLANK_CWIDTH, BLANK_CHEIGHT, + BLANK_CHOTX, BLANK_CHOTY); + + /* Fill in some window manager capabilities */ + this->info.wm_available = 1; + + /* We're done! */ + XFlush(SDL_Display); + return(0); +} + +static void X11_DestroyWindow(_THIS, SDL_Surface *screen) +{ + /* Clean up OpenGL */ + if ( screen ) { + screen->flags &= ~(SDL_OPENGL|SDL_OPENGLBLIT); + } + X11_GL_Shutdown(this); + + if ( ! SDL_windowid ) { + /* Hide the managed window */ + if ( WMwindow ) { + XUnmapWindow(SDL_Display, WMwindow); + } + if ( screen && (screen->flags & SDL_FULLSCREEN) ) { + screen->flags &= ~SDL_FULLSCREEN; + X11_LeaveFullScreen(this); + } + + /* Destroy the output window */ + if ( SDL_Window ) { + XDestroyWindow(SDL_Display, SDL_Window); + } + + /* Free the colormap entries */ + if ( SDL_XPixels ) { + int numcolors; + unsigned long pixel; + numcolors = SDL_Visual->map_entries; + for ( pixel=0; pixel<numcolors; ++pixel ) { + while ( SDL_XPixels[pixel] > 0 ) { + XFreeColors(GFX_Display, + SDL_DisplayColormap,&pixel,1,0); + --SDL_XPixels[pixel]; + } + } + SDL_free(SDL_XPixels); + SDL_XPixels = NULL; + } + + /* Free the graphics context */ + if ( SDL_GC ) { + XFreeGC(SDL_Display, SDL_GC); + SDL_GC = 0; + } + } +} + +static SDL_bool X11_WindowPosition(_THIS, int *x, int *y, int w, int h) +{ + const char *window = SDL_getenv("SDL_VIDEO_WINDOW_POS"); + const char *center = SDL_getenv("SDL_VIDEO_CENTERED"); + if ( window ) { + if ( SDL_sscanf(window, "%d,%d", x, y) == 2 ) { + return SDL_TRUE; + } + if ( SDL_strcmp(window, "center") == 0 ) { + center = window; + } + } + if ( center ) { + *x = (DisplayWidth(SDL_Display, SDL_Screen) - w)/2; + *y = (DisplayHeight(SDL_Display, SDL_Screen) - h)/2; + return SDL_TRUE; + } + return SDL_FALSE; +} + +static void X11_SetSizeHints(_THIS, int w, int h, Uint32 flags) +{ + XSizeHints *hints; + + hints = XAllocSizeHints(); + if ( hints ) { + if (!(flags & SDL_RESIZABLE)) { + hints->min_width = hints->max_width = w; + hints->min_height = hints->max_height = h; + hints->flags = PMaxSize | PMinSize; + } + if ( flags & SDL_FULLSCREEN ) { + hints->x = 0; + hints->y = 0; + hints->flags |= USPosition; + } else + /* Center it, if desired */ + if ( X11_WindowPosition(this, &hints->x, &hints->y, w, h) ) { + hints->flags |= USPosition; + + /* Hints must be set before moving the window, otherwise an + unwanted ConfigureNotify event will be issued */ + XSetWMNormalHints(SDL_Display, WMwindow, hints); + + XMoveWindow(SDL_Display, WMwindow, hints->x, hints->y); + + /* Flush the resize event so we don't catch it later */ + XSync(SDL_Display, True); + } + XSetWMNormalHints(SDL_Display, WMwindow, hints); + XFree(hints); + } + + /* Respect the window caption style */ + if ( flags & SDL_NOFRAME ) { + SDL_bool set; + Atom WM_HINTS; + + /* We haven't modified the window manager hints yet */ + set = SDL_FALSE; + + /* First try to set MWM hints */ + WM_HINTS = XInternAtom(SDL_Display, "_MOTIF_WM_HINTS", True); + if ( WM_HINTS != None ) { + /* Hints used by Motif compliant window managers */ + struct { + unsigned long flags; + unsigned long functions; + unsigned long decorations; + long input_mode; + unsigned long status; + } MWMHints = { (1L << 1), 0, 0, 0, 0 }; + + XChangeProperty(SDL_Display, WMwindow, + WM_HINTS, WM_HINTS, 32, + PropModeReplace, + (unsigned char *)&MWMHints, + sizeof(MWMHints)/sizeof(long)); + set = SDL_TRUE; + } + /* Now try to set KWM hints */ + WM_HINTS = XInternAtom(SDL_Display, "KWM_WIN_DECORATION", True); + if ( WM_HINTS != None ) { + long KWMHints = 0; + + XChangeProperty(SDL_Display, WMwindow, + WM_HINTS, WM_HINTS, 32, + PropModeReplace, + (unsigned char *)&KWMHints, + sizeof(KWMHints)/sizeof(long)); + set = SDL_TRUE; + } + /* Now try to set GNOME hints */ + WM_HINTS = XInternAtom(SDL_Display, "_WIN_HINTS", True); + if ( WM_HINTS != None ) { + long GNOMEHints = 0; + + XChangeProperty(SDL_Display, WMwindow, + WM_HINTS, WM_HINTS, 32, + PropModeReplace, + (unsigned char *)&GNOMEHints, + sizeof(GNOMEHints)/sizeof(long)); + set = SDL_TRUE; + } + /* Finally set the transient hints if necessary */ + if ( ! set ) { + XSetTransientForHint(SDL_Display, WMwindow, SDL_Root); + } + } else { + SDL_bool set; + Atom WM_HINTS; + + /* We haven't modified the window manager hints yet */ + set = SDL_FALSE; + + /* First try to unset MWM hints */ + WM_HINTS = XInternAtom(SDL_Display, "_MOTIF_WM_HINTS", True); + if ( WM_HINTS != None ) { + XDeleteProperty(SDL_Display, WMwindow, WM_HINTS); + set = SDL_TRUE; + } + /* Now try to unset KWM hints */ + WM_HINTS = XInternAtom(SDL_Display, "KWM_WIN_DECORATION", True); + if ( WM_HINTS != None ) { + XDeleteProperty(SDL_Display, WMwindow, WM_HINTS); + set = SDL_TRUE; + } + /* Now try to unset GNOME hints */ + WM_HINTS = XInternAtom(SDL_Display, "_WIN_HINTS", True); + if ( WM_HINTS != None ) { + XDeleteProperty(SDL_Display, WMwindow, WM_HINTS); + set = SDL_TRUE; + } + /* Finally unset the transient hints if necessary */ + if ( ! set ) { + XDeleteProperty(SDL_Display, WMwindow, XA_WM_TRANSIENT_FOR); + } + } +} + +static int X11_CreateWindow(_THIS, SDL_Surface *screen, + int w, int h, int bpp, Uint32 flags) +{ + int i, depth; + Visual *vis; + int vis_change; + Uint32 Amask; + + /* If a window is already present, destroy it and start fresh */ + if ( SDL_Window ) { + X11_DestroyWindow(this, screen); + switch_waiting = 0; /* Prevent jump back to now-meaningless state. */ + } + + /* See if we have been given a window id */ + if ( SDL_windowid ) { + SDL_Window = SDL_strtol(SDL_windowid, NULL, 0); + } else { + SDL_Window = 0; + } + + /* find out which visual we are going to use */ + if ( flags & SDL_OPENGL ) { + XVisualInfo *vi; + + vi = X11_GL_GetVisual(this); + if( !vi ) { + return -1; + } + vis = vi->visual; + depth = vi->depth; + } else if ( SDL_windowid ) { + XWindowAttributes a; + + XGetWindowAttributes(SDL_Display, SDL_Window, &a); + vis = a.visual; + depth = a.depth; + } else { + for ( i = 0; i < this->hidden->nvisuals; i++ ) { + if ( this->hidden->visuals[i].bpp == bpp ) + break; + } + if ( i == this->hidden->nvisuals ) { + SDL_SetError("No matching visual for requested depth"); + return -1; /* should never happen */ + } + vis = this->hidden->visuals[i].visual; + depth = this->hidden->visuals[i].depth; + } +#ifdef X11_DEBUG + printf("Choosing %s visual at %d bpp - %d colormap entries\n", vis->class == PseudoColor ? "PseudoColor" : (vis->class == TrueColor ? "TrueColor" : (vis->class == DirectColor ? "DirectColor" : "Unknown")), depth, vis->map_entries); +#endif + vis_change = (vis != SDL_Visual); + SDL_Visual = vis; + this->hidden->depth = depth; + + /* Allocate the new pixel format for this video mode */ + if ( this->hidden->depth == 32 ) { + Amask = (0xFFFFFFFF & ~(vis->red_mask|vis->green_mask|vis->blue_mask)); + } else { + Amask = 0; + } + if ( ! SDL_ReallocFormat(screen, bpp, + vis->red_mask, vis->green_mask, vis->blue_mask, Amask) ) { + return -1; + } + + /* Create the appropriate colormap */ + if ( SDL_XColorMap != SDL_DisplayColormap ) { + XFreeColormap(SDL_Display, SDL_XColorMap); + } + if ( SDL_Visual->class == PseudoColor ) { + int ncolors; + + /* Allocate the pixel flags */ + ncolors = SDL_Visual->map_entries; + SDL_XPixels = SDL_malloc(ncolors * sizeof(int)); + if(SDL_XPixels == NULL) { + SDL_OutOfMemory(); + return -1; + } + SDL_memset(SDL_XPixels, 0, ncolors * sizeof(*SDL_XPixels)); + + /* always allocate a private colormap on non-default visuals */ + if ( SDL_Visual != DefaultVisual(SDL_Display, SDL_Screen) ) { + flags |= SDL_HWPALETTE; + } + if ( flags & SDL_HWPALETTE ) { + screen->flags |= SDL_HWPALETTE; + SDL_XColorMap = XCreateColormap(SDL_Display, SDL_Root, + SDL_Visual, AllocAll); + } else { + SDL_XColorMap = SDL_DisplayColormap; + } + } else if ( SDL_Visual->class == DirectColor ) { + + /* Create a colormap which we can manipulate for gamma */ + SDL_XColorMap = XCreateColormap(SDL_Display, SDL_Root, + SDL_Visual, AllocAll); + XSync(SDL_Display, False); + + /* Initialize the colormap to the identity mapping */ + SDL_GetGammaRamp(0, 0, 0); + this->screen = screen; + X11_SetGammaRamp(this, this->gamma); + this->screen = NULL; + } else { + /* Create a read-only colormap for our window */ + SDL_XColorMap = XCreateColormap(SDL_Display, SDL_Root, + SDL_Visual, AllocNone); + } + + /* Recreate the auxiliary windows, if needed (required for GL) */ + if ( vis_change ) + create_aux_windows(this); + + if(screen->flags & SDL_HWPALETTE) { + /* Since the full-screen window might have got a nonzero background + colour (0 is white on some displays), we should reset the + background to 0 here since that is what the user expects + with a private colormap */ + XSetWindowBackground(SDL_Display, FSwindow, 0); + XClearWindow(SDL_Display, FSwindow); + } + + /* resize the (possibly new) window manager window */ + if( !SDL_windowid ) { + X11_SetSizeHints(this, w, h, flags); + window_w = w; + window_h = h; + XResizeWindow(SDL_Display, WMwindow, w, h); + } + + /* Create (or use) the X11 display window */ + if ( !SDL_windowid ) { + if ( flags & SDL_OPENGL ) { + if ( X11_GL_CreateWindow(this, w, h) < 0 ) { + return(-1); + } + } else { + XSetWindowAttributes swa; + + swa.background_pixel = 0; + swa.border_pixel = 0; + swa.colormap = SDL_XColorMap; + SDL_Window = XCreateWindow(SDL_Display, WMwindow, + 0, 0, w, h, 0, depth, + InputOutput, SDL_Visual, + CWBackPixel | CWBorderPixel + | CWColormap, &swa); + } + /* Only manage our input if we own the window */ + XSelectInput(SDL_Display, SDL_Window, + ( EnterWindowMask | LeaveWindowMask + | ButtonPressMask | ButtonReleaseMask + | PointerMotionMask | ExposureMask )); + } + /* Create the graphics context here, once we have a window */ + if ( flags & SDL_OPENGL ) { + if ( X11_GL_CreateContext(this) < 0 ) { + return(-1); + } else { + screen->flags |= SDL_OPENGL; + } + } else { + XGCValues gcv; + + gcv.graphics_exposures = False; + SDL_GC = XCreateGC(SDL_Display, SDL_Window, + GCGraphicsExposures, &gcv); + if ( ! SDL_GC ) { + SDL_SetError("Couldn't create graphics context"); + return(-1); + } + } + + /* Set our colormaps when not setting a GL mode */ + if ( ! (flags & SDL_OPENGL) ) { + XSetWindowColormap(SDL_Display, SDL_Window, SDL_XColorMap); + if( !SDL_windowid ) { + XSetWindowColormap(SDL_Display, FSwindow, SDL_XColorMap); + XSetWindowColormap(SDL_Display, WMwindow, SDL_XColorMap); + } + } + +#if 0 /* This is an experiment - are the graphics faster now? - nope. */ + if ( SDL_getenv("SDL_VIDEO_X11_BACKINGSTORE") ) +#endif + /* Cache the window in the server, when possible */ + { + Screen *xscreen; + XSetWindowAttributes a; + + xscreen = ScreenOfDisplay(SDL_Display, SDL_Screen); + a.backing_store = DoesBackingStore(xscreen); + if ( a.backing_store != NotUseful ) { + XChangeWindowAttributes(SDL_Display, SDL_Window, + CWBackingStore, &a); + } + } + + /* Map them both and go fullscreen, if requested */ + if ( ! SDL_windowid ) { + XMapWindow(SDL_Display, SDL_Window); + XMapWindow(SDL_Display, WMwindow); + X11_WaitMapped(this, WMwindow); + if ( flags & SDL_FULLSCREEN ) { + screen->flags |= SDL_FULLSCREEN; + X11_EnterFullScreen(this); + } else { + screen->flags &= ~SDL_FULLSCREEN; + } + } + + return(0); +} + +static int X11_ResizeWindow(_THIS, + SDL_Surface *screen, int w, int h, Uint32 flags) +{ + if ( ! SDL_windowid ) { + /* Resize the window manager window */ + X11_SetSizeHints(this, w, h, flags); + window_w = w; + window_h = h; + XResizeWindow(SDL_Display, WMwindow, w, h); + + /* Resize the fullscreen and display windows */ + if ( flags & SDL_FULLSCREEN ) { + if ( screen->flags & SDL_FULLSCREEN ) { + X11_ResizeFullScreen(this); + } else { + screen->flags |= SDL_FULLSCREEN; + X11_EnterFullScreen(this); + } + } else { + if ( screen->flags & SDL_FULLSCREEN ) { + screen->flags &= ~SDL_FULLSCREEN; + X11_LeaveFullScreen(this); + } + } + XResizeWindow(SDL_Display, SDL_Window, w, h); + } + return(0); +} + +SDL_Surface *X11_SetVideoMode(_THIS, SDL_Surface *current, + int width, int height, int bpp, Uint32 flags) +{ + Uint32 saved_flags; + + /* Lock the event thread, in multi-threading environments */ + SDL_Lock_EventThread(); + + /* Check the combination of flags we were passed */ + if ( flags & SDL_FULLSCREEN ) { + /* Clear fullscreen flag if not supported */ + if ( SDL_windowid ) { + flags &= ~SDL_FULLSCREEN; + } + } + + /* Flush any delayed updates */ + XSync(GFX_Display, False); + + /* Set up the X11 window */ + saved_flags = current->flags; + if ( (SDL_Window) && ((saved_flags&SDL_OPENGL) == (flags&SDL_OPENGL)) + && (bpp == current->format->BitsPerPixel) + && ((saved_flags&SDL_NOFRAME) == (flags&SDL_NOFRAME)) ) { + if (X11_ResizeWindow(this, current, width, height, flags) < 0) { + current = NULL; + goto done; + } + X11_PendingConfigureNotifyWidth = width; + X11_PendingConfigureNotifyHeight = height; + } else { + if (X11_CreateWindow(this,current,width,height,bpp,flags) < 0) { + current = NULL; + goto done; + } + } + + /* Update the internal keyboard state */ + X11_SetKeyboardState(SDL_Display, NULL); + + /* When the window is first mapped, ignore non-modifier keys */ + if ( !current->w && !current->h ) { + Uint8 *keys = SDL_GetKeyState(NULL); + int i; + for ( i = 0; i < SDLK_LAST; ++i ) { + switch (i) { + case SDLK_NUMLOCK: + case SDLK_CAPSLOCK: + case SDLK_LCTRL: + case SDLK_RCTRL: + case SDLK_LSHIFT: + case SDLK_RSHIFT: + case SDLK_LALT: + case SDLK_RALT: + case SDLK_LMETA: + case SDLK_RMETA: + case SDLK_MODE: + break; + default: + keys[i] = SDL_RELEASED; + break; + } + } + } + + /* Set up the new mode framebuffer */ + if ( ((current->w != width) || (current->h != height)) || + ((saved_flags&SDL_OPENGL) != (flags&SDL_OPENGL)) ) { + current->w = width; + current->h = height; + current->pitch = SDL_CalculatePitch(current); + if (X11_ResizeImage(this, current, flags) < 0) { + current = NULL; + goto done; + } + } + + /* Clear these flags and set them only if they are in the new set. */ + current->flags &= ~(SDL_RESIZABLE|SDL_NOFRAME); + current->flags |= (flags&(SDL_RESIZABLE|SDL_NOFRAME)); + + done: + /* Release the event thread */ + XSync(SDL_Display, False); + SDL_Unlock_EventThread(); + + /* We're done! */ + return(current); +} + +static int X11_ToggleFullScreen(_THIS, int on) +{ + Uint32 event_thread; + + /* Don't switch if we don't own the window */ + if ( SDL_windowid ) { + return(0); + } + + /* Don't lock if we are the event thread */ + event_thread = SDL_EventThreadID(); + if ( event_thread && (SDL_ThreadID() == event_thread) ) { + event_thread = 0; + } + if ( event_thread ) { + SDL_Lock_EventThread(); + } + if ( on ) { + this->screen->flags |= SDL_FULLSCREEN; + X11_EnterFullScreen(this); + } else { + this->screen->flags &= ~SDL_FULLSCREEN; + X11_LeaveFullScreen(this); + } + X11_RefreshDisplay(this); + if ( event_thread ) { + SDL_Unlock_EventThread(); + } + SDL_ResetKeyboard(); + return(1); +} + +/* Update the current mouse state and position */ +static void X11_UpdateMouse(_THIS) +{ + Window u1; int u2; + Window current_win; + int x, y; + unsigned int mask; + + /* Lock the event thread, in multi-threading environments */ + SDL_Lock_EventThread(); + if ( XQueryPointer(SDL_Display, SDL_Window, &u1, ¤t_win, + &u2, &u2, &x, &y, &mask) ) { + if ( (x >= 0) && (x < SDL_VideoSurface->w) && + (y >= 0) && (y < SDL_VideoSurface->h) ) { + SDL_PrivateAppActive(1, SDL_APPMOUSEFOCUS); + SDL_PrivateMouseMotion(0, 0, x, y); + } else { + SDL_PrivateAppActive(0, SDL_APPMOUSEFOCUS); + } + } + SDL_Unlock_EventThread(); +} + +/* simple colour distance metric. Supposed to be better than a plain + Euclidian distance anyway. */ +#define COLOUR_FACTOR 3 +#define LIGHT_FACTOR 1 +#define COLOUR_DIST(r1, g1, b1, r2, g2, b2) \ + (COLOUR_FACTOR * (abs(r1 - r2) + abs(g1 - g2) + abs(b1 - b2)) \ + + LIGHT_FACTOR * abs(r1 + g1 + b1 - (r2 + g2 + b2))) + +static void allocate_nearest(_THIS, SDL_Color *colors, + SDL_Color *want, int nwant) +{ + /* + * There is no way to know which ones to choose from, so we retrieve + * the entire colormap and try the nearest possible, until we find one + * that is shared. + */ + XColor all[256]; + int i; + for(i = 0; i < 256; i++) + all[i].pixel = i; + /* + * XQueryColors sets the flags in the XColor struct, so we use + * that to keep track of which colours are available + */ + XQueryColors(GFX_Display, SDL_XColorMap, all, 256); + + for(i = 0; i < nwant; i++) { + XColor *c; + int j; + int best = 0; + int mindist = 0x7fffffff; + int ri = want[i].r; + int gi = want[i].g; + int bi = want[i].b; + for(j = 0; j < 256; j++) { + int rj, gj, bj, d2; + if(!all[j].flags) + continue; /* unavailable colour cell */ + rj = all[j].red >> 8; + gj = all[j].green >> 8; + bj = all[j].blue >> 8; + d2 = COLOUR_DIST(ri, gi, bi, rj, gj, bj); + if(d2 < mindist) { + mindist = d2; + best = j; + } + } + if(SDL_XPixels[best]) + continue; /* already allocated, waste no more time */ + c = all + best; + if(XAllocColor(GFX_Display, SDL_XColorMap, c)) { + /* got it */ + colors[c->pixel].r = c->red >> 8; + colors[c->pixel].g = c->green >> 8; + colors[c->pixel].b = c->blue >> 8; + ++SDL_XPixels[c->pixel]; + } else { + /* + * The colour couldn't be allocated, probably being + * owned as a r/w cell by another client. Flag it as + * unavailable and try again. The termination of the + * loop is guaranteed since at least black and white + * are always there. + */ + c->flags = 0; + i--; + } + } +} + +int X11_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors) +{ + int nrej = 0; + + /* Check to make sure we have a colormap allocated */ + if ( SDL_XPixels == NULL ) { + return(0); + } + if ( (this->screen->flags & SDL_HWPALETTE) == SDL_HWPALETTE ) { + /* private writable colormap: just set the colours we need */ + XColor *xcmap; + int i; + xcmap = SDL_stack_alloc(XColor, ncolors); + if(xcmap == NULL) + return 0; + for ( i=0; i<ncolors; ++i ) { + xcmap[i].pixel = i + firstcolor; + xcmap[i].red = (colors[i].r<<8)|colors[i].r; + xcmap[i].green = (colors[i].g<<8)|colors[i].g; + xcmap[i].blue = (colors[i].b<<8)|colors[i].b; + xcmap[i].flags = (DoRed|DoGreen|DoBlue); + } + XStoreColors(GFX_Display, SDL_XColorMap, xcmap, ncolors); + XSync(GFX_Display, False); + SDL_stack_free(xcmap); + } else { + /* + * Shared colormap: We only allocate read-only cells, which + * increases the likelyhood of colour sharing with other + * clients. The pixel values will almost certainly be + * different from the requested ones, so the user has to + * walk the colormap and see which index got what colour. + * + * We can work directly with the logical palette since it + * has already been set when we get here. + */ + SDL_Color *want, *reject; + unsigned long *freelist; + int i; + int nfree = 0; + int nc = this->screen->format->palette->ncolors; + colors = this->screen->format->palette->colors; + freelist = SDL_stack_alloc(unsigned long, nc); + /* make sure multiple allocations of the same cell are freed */ + for(i = 0; i < ncolors; i++) { + int pixel = firstcolor + i; + while(SDL_XPixels[pixel]) { + freelist[nfree++] = pixel; + --SDL_XPixels[pixel]; + } + } + XFreeColors(GFX_Display, SDL_XColorMap, freelist, nfree, 0); + SDL_stack_free(freelist); + + want = SDL_stack_alloc(SDL_Color, ncolors); + reject = SDL_stack_alloc(SDL_Color, ncolors); + SDL_memcpy(want, colors + firstcolor, ncolors * sizeof(SDL_Color)); + /* make sure the user isn't fooled by her own wishes + (black is safe, always available in the default colormap) */ + SDL_memset(colors + firstcolor, 0, ncolors * sizeof(SDL_Color)); + + /* now try to allocate the colours */ + for(i = 0; i < ncolors; i++) { + XColor col; + col.red = want[i].r << 8; + col.green = want[i].g << 8; + col.blue = want[i].b << 8; + col.flags = DoRed | DoGreen | DoBlue; + if(XAllocColor(GFX_Display, SDL_XColorMap, &col)) { + /* We got the colour, or at least the nearest + the hardware could get. */ + colors[col.pixel].r = col.red >> 8; + colors[col.pixel].g = col.green >> 8; + colors[col.pixel].b = col.blue >> 8; + ++SDL_XPixels[col.pixel]; + } else { + /* + * no more free cells, add it to the list + * of rejected colours + */ + reject[nrej++] = want[i]; + } + } + if(nrej) + allocate_nearest(this, colors, reject, nrej); + SDL_stack_free(reject); + SDL_stack_free(want); + } + return nrej == 0; +} + +int X11_SetGammaRamp(_THIS, Uint16 *ramp) +{ + int i, ncolors; + XColor xcmap[256]; + + /* See if actually setting the gamma is supported */ + if ( SDL_Visual->class != DirectColor ) { + SDL_SetError("Gamma correction not supported on this visual"); + return(-1); + } + + /* Calculate the appropriate palette for the given gamma ramp */ + ncolors = SDL_Visual->map_entries; + for ( i=0; i<ncolors; ++i ) { + Uint8 c = (256 * i / ncolors); + xcmap[i].pixel = SDL_MapRGB(this->screen->format, c, c, c); + xcmap[i].red = ramp[0*256+c]; + xcmap[i].green = ramp[1*256+c]; + xcmap[i].blue = ramp[2*256+c]; + xcmap[i].flags = (DoRed|DoGreen|DoBlue); + } + XStoreColors(GFX_Display, SDL_XColorMap, xcmap, ncolors); + XSync(GFX_Display, False); + return(0); +} + +/* Note: If we are terminated, this could be called in the middle of + another SDL video routine -- notably UpdateRects. +*/ +void X11_VideoQuit(_THIS) +{ + /* Shutdown everything that's still up */ + /* The event thread should be done, so we can touch SDL_Display */ + if ( SDL_Display != NULL ) { + /* Flush any delayed updates */ + XSync(GFX_Display, False); + + /* Close the connection with the IM server */ + #ifdef X_HAVE_UTF8_STRING + if (SDL_IC != NULL) { + XUnsetICFocus(SDL_IC); + XDestroyIC(SDL_IC); + SDL_IC = NULL; + } + if (SDL_IM != NULL) { + XCloseIM(SDL_IM); + SDL_IM = NULL; + } + #endif + + /* Start shutting down the windows */ + X11_DestroyImage(this, this->screen); + X11_DestroyWindow(this, this->screen); + X11_FreeVideoModes(this); + if ( SDL_XColorMap != SDL_DisplayColormap ) { + XFreeColormap(SDL_Display, SDL_XColorMap); + } + if ( SDL_iconcolors ) { + unsigned long pixel; + Colormap dcmap = DefaultColormap(SDL_Display, + SDL_Screen); + for(pixel = 0; pixel < 256; ++pixel) { + while(SDL_iconcolors[pixel] > 0) { + XFreeColors(GFX_Display, + dcmap, &pixel, 1, 0); + --SDL_iconcolors[pixel]; + } + } + SDL_free(SDL_iconcolors); + SDL_iconcolors = NULL; + } + + /* Restore gamma settings if they've changed */ + if ( SDL_GetAppState() & SDL_APPACTIVE ) { + X11_SwapVidModeGamma(this); + } + + /* Free that blank cursor */ + if ( SDL_BlankCursor != NULL ) { + this->FreeWMCursor(this, SDL_BlankCursor); + SDL_BlankCursor = NULL; + } + + /* Close the X11 graphics connection */ + if ( GFX_Display != NULL ) { + XCloseDisplay(GFX_Display); + GFX_Display = NULL; + } + + /* Close the X11 display connection */ + XCloseDisplay(SDL_Display); + SDL_Display = NULL; + + /* Reset the X11 error handlers */ + if ( XIO_handler ) { + XSetIOErrorHandler(XIO_handler); + } + if ( X_handler ) { + XSetErrorHandler(X_handler); + } + + /* Unload GL library after X11 shuts down */ + X11_GL_UnloadLibrary(this); + } + if ( this->screen && (this->screen->flags & SDL_HWSURFACE) ) { + /* Direct screen access, no memory buffer */ + this->screen->pixels = NULL; + } + +#if SDL_VIDEO_DRIVER_X11_XME + XiGMiscDestroy(); +#endif +} + diff --git a/3rdparty/SDL/src/video/x11/SDL_x11video.h b/3rdparty/SDL/src/video/x11/SDL_x11video.h new file mode 100644 index 0000000..f347560 --- /dev/null +++ b/3rdparty/SDL/src/video/x11/SDL_x11video.h @@ -0,0 +1,214 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#ifndef _SDL_x11video_h +#define _SDL_x11video_h + +#include <X11/Xlib.h> +#include <X11/Xutil.h> +#include <X11/Xatom.h> + +#include "SDL_mouse.h" +#include "../SDL_sysvideo.h" + +#if SDL_VIDEO_DRIVER_X11_DGAMOUSE +#include "../Xext/extensions/xf86dga.h" +#endif +#if SDL_VIDEO_DRIVER_X11_XINERAMA +#include "../Xext/extensions/Xinerama.h" +#endif +#if SDL_VIDEO_DRIVER_X11_XRANDR +#include <X11/extensions/Xrandr.h> +#endif +#if SDL_VIDEO_DRIVER_X11_VIDMODE +#include "../Xext/extensions/xf86vmode.h" +#endif +#if SDL_VIDEO_DRIVER_X11_XME +#include "../Xext/extensions/xme.h" +#endif + +#include "SDL_x11dyn.h" + +/* Hidden "this" pointer for the video functions */ +#define _THIS SDL_VideoDevice *this + +/* Private display data */ +struct SDL_PrivateVideoData { + int local_X11; /* Flag: true if local display */ + Display *X11_Display; /* Used for events and window management */ + Display *GFX_Display; /* Used for graphics and colormap stuff */ + Visual *SDL_Visual; /* The visual used by our window */ + Window WMwindow; /* Input window, managed by window manager */ + Window FSwindow; /* Fullscreen window, completely unmanaged */ + Window SDL_Window; /* Shared by both displays (no X security?) */ + Atom WM_DELETE_WINDOW; /* "close-window" protocol atom */ + WMcursor *BlankCursor; /* The invisible cursor */ + XIM X11_IM; /* Used to communicate with the input method (IM) server */ + XIC X11_IC; /* Used for retaining the state, properties, and semantics of communication with the input method (IM) server */ + + char *SDL_windowid; /* Flag: true if we have been passed a window */ + + /* Direct Graphics Access extension information */ + int using_dga; + +#ifndef NO_SHARED_MEMORY + /* MIT shared memory extension information */ + int use_mitshm; + XShmSegmentInfo shminfo; +#endif + + /* The variables used for displaying graphics */ + XImage *Ximage; /* The X image for our window */ + GC gc; /* The graphic context for drawing */ + + /* The current width and height of the fullscreen mode */ + int window_w; + int window_h; + + /* Support for internal mouse warping */ + struct { + int x; + int y; + } mouse_last; + struct { + int numerator; + int denominator; + int threshold; + } mouse_accel; + int mouse_relative; + + /* The current list of available video modes */ + SDL_Rect **modelist; + + /* available visuals of interest to us, sorted deepest first */ + struct { + Visual *visual; + int depth; /* number of significant bits/pixel */ + int bpp; /* pixel quantum in bits */ + } visuals[2*5]; /* at most 2 entries for 8, 15, 16, 24, 32 */ + int nvisuals; + + Visual *vis; /* current visual in use */ + int depth; /* current visual depth (not bpp) */ + + /* Variables used by the X11 video mode code */ +#if SDL_VIDEO_DRIVER_X11_XINERAMA + SDL_NAME(XineramaScreenInfo) xinerama_info; +#endif +#if SDL_VIDEO_DRIVER_X11_XRANDR + XRRScreenConfiguration* screen_config; + int saved_size_id; + Rotation saved_rotation; +#endif +#if SDL_VIDEO_DRIVER_X11_VIDMODE + SDL_NAME(XF86VidModeModeInfo) saved_mode; + struct { + int x, y; + } saved_view; +#endif +#if SDL_VIDEO_DRIVER_X11_XME /* XiG XME fullscreen */ + XiGMiscResolutionInfo saved_res; +#endif + + int use_xinerama; + int use_xrandr; + int use_vidmode; + int use_xme; + int currently_fullscreen; + + /* Automatic mode switching support (entering/leaving fullscreen) */ + Uint32 switch_waiting; + Uint32 switch_time; + + /* Prevent too many XSync() calls */ + int blit_queued; + + /* Colormap handling */ + Colormap DisplayColormap; /* The default display colormap */ + Colormap XColorMap; /* The current window colormap */ + int *XPixels; /* pixels value allocation counts */ + float gamma_saved[3]; /* Saved gamma values for VidMode gamma */ + int gamma_changed; /* flag: has VidMode gamma been modified? */ + + short *iconcolors; /* List of colors used by the icon */ + + /* Screensaver settings */ + int allow_screensaver; +}; + +/* Old variable names */ +#define local_X11 (this->hidden->local_X11) +#define SDL_Display (this->hidden->X11_Display) +#define GFX_Display (this->hidden->GFX_Display) +#define SDL_Screen DefaultScreen(this->hidden->X11_Display) +#define SDL_Visual (this->hidden->vis) +#define SDL_Root RootWindow(SDL_Display, SDL_Screen) +#define WMwindow (this->hidden->WMwindow) +#define FSwindow (this->hidden->FSwindow) +#define SDL_Window (this->hidden->SDL_Window) +#define WM_DELETE_WINDOW (this->hidden->WM_DELETE_WINDOW) +#define SDL_BlankCursor (this->hidden->BlankCursor) +#define SDL_IM (this->hidden->X11_IM) +#define SDL_IC (this->hidden->X11_IC) +#define SDL_windowid (this->hidden->SDL_windowid) +#define using_dga (this->hidden->using_dga) +#define use_mitshm (this->hidden->use_mitshm) +#define shminfo (this->hidden->shminfo) +#define SDL_Ximage (this->hidden->Ximage) +#define SDL_GC (this->hidden->gc) +#define window_w (this->hidden->window_w) +#define window_h (this->hidden->window_h) +#define mouse_last (this->hidden->mouse_last) +#define mouse_accel (this->hidden->mouse_accel) +#define mouse_relative (this->hidden->mouse_relative) +#define SDL_modelist (this->hidden->modelist) +#define xinerama_info (this->hidden->xinerama_info) +#define saved_mode (this->hidden->saved_mode) +#define saved_view (this->hidden->saved_view) +#define saved_res (this->hidden->saved_res) +#define screen_config (this->hidden->screen_config) +#define saved_size_id (this->hidden->saved_size_id) +#define saved_rotation (this->hidden->saved_rotation) +#define use_xinerama (this->hidden->use_xinerama) +#define use_vidmode (this->hidden->use_vidmode) +#define use_xrandr (this->hidden->use_xrandr) +#define use_xme (this->hidden->use_xme) +#define currently_fullscreen (this->hidden->currently_fullscreen) +#define switch_waiting (this->hidden->switch_waiting) +#define switch_time (this->hidden->switch_time) +#define blit_queued (this->hidden->blit_queued) +#define SDL_DisplayColormap (this->hidden->DisplayColormap) +#define SDL_PrivateColormap (this->hidden->PrivateColormap) +#define SDL_XColorMap (this->hidden->XColorMap) +#define SDL_XPixels (this->hidden->XPixels) +#define gamma_saved (this->hidden->gamma_saved) +#define gamma_changed (this->hidden->gamma_changed) +#define SDL_iconcolors (this->hidden->iconcolors) +#define allow_screensaver (this->hidden->allow_screensaver) + +/* Some versions of XFree86 have bugs - detect if this is one of them */ +#define BUGGY_XFREE86(condition, buggy_version) \ +((SDL_strcmp(ServerVendor(SDL_Display), "The XFree86 Project, Inc") == 0) && \ + (VendorRelease(SDL_Display) condition buggy_version)) + +#endif /* _SDL_x11video_h */ diff --git a/3rdparty/SDL/src/video/x11/SDL_x11wm.c b/3rdparty/SDL/src/video/x11/SDL_x11wm.c new file mode 100644 index 0000000..14c816b --- /dev/null +++ b/3rdparty/SDL/src/video/x11/SDL_x11wm.c @@ -0,0 +1,434 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#include <X11/Xlib.h> +#include <X11/Xutil.h> + +#include "SDL_version.h" +#include "SDL_timer.h" +#include "SDL_video.h" +#include "SDL_syswm.h" +#include "../SDL_pixels_c.h" +#include "../../events/SDL_events_c.h" +#include "SDL_x11modes_c.h" +#include "SDL_x11wm_c.h" + +static Uint8 reverse_byte(Uint8 x) +{ + x = (x & 0xaa) >> 1 | (x & 0x55) << 1; + x = (x & 0xcc) >> 2 | (x & 0x33) << 2; + x = (x & 0xf0) >> 4 | (x & 0x0f) << 4; + return x; +} + +void X11_SetIcon(_THIS, SDL_Surface *icon, Uint8 *mask) +{ + SDL_Surface *sicon; + XWMHints *wmhints; + XImage *icon_image; + Pixmap icon_pixmap; + Pixmap mask_pixmap; + Window icon_window = None; + GC gc; + XGCValues GCvalues; + int i, dbpp; + SDL_Rect bounds; + Uint8 *LSBmask; + Visual *dvis; + char *p; + int masksize; + + SDL_Lock_EventThread(); + + /* The icon must use the default visual, depth and colormap of the + screen, so it might need a conversion */ + dvis = DefaultVisual(SDL_Display, SDL_Screen); + dbpp = DefaultDepth(SDL_Display, SDL_Screen); + for(i = 0; i < this->hidden->nvisuals; i++) { + if(this->hidden->visuals[i].visual == dvis) { + dbpp = this->hidden->visuals[i].bpp; + break; + } + } + + /* The Visual struct is supposed to be opaque but we cheat a little */ + sicon = SDL_CreateRGBSurface(SDL_SWSURFACE, icon->w, icon->h, + dbpp, + dvis->red_mask, dvis->green_mask, + dvis->blue_mask, 0); + if ( sicon == NULL ) + goto done; + + if(dbpp == 8) { + /* Default visual is 8bit; we need to allocate colours from + the default colormap */ + SDL_Color want[256], got[256]; + int nwant; + Colormap dcmap; + int missing; + dcmap = DefaultColormap(SDL_Display, SDL_Screen); + if(icon->format->palette) { + /* The icon has a palette as well - we just have to + find those colours */ + nwant = icon->format->palette->ncolors; + SDL_memcpy(want, icon->format->palette->colors, + nwant * sizeof want[0]); + } else { + /* try the standard 6x6x6 cube for lack of better + ideas */ + int r, g, b, i; + for(r = i = 0; r < 256; r += 0x33) + for(g = 0; g < 256; g += 0x33) + for(b = 0; b < 256; b += 0x33, i++) { + want[i].r = r; + want[i].g = g; + want[i].b = b; + } + nwant = 216; + } + if(SDL_iconcolors) { + /* free already allocated colours first */ + unsigned long freelist[512]; + int nfree = 0; + for(i = 0; i < 256; i++) { + while(SDL_iconcolors[i]) { + freelist[nfree++] = i; + SDL_iconcolors[i]--; + } + } + XFreeColors(GFX_Display, dcmap, freelist, nfree, 0); + } + if(!SDL_iconcolors) + SDL_iconcolors = SDL_malloc(256 * sizeof *SDL_iconcolors); + SDL_memset(SDL_iconcolors, 0, 256 * sizeof *SDL_iconcolors); + + /* try to allocate the colours */ + SDL_memset(got, 0, sizeof got); + missing = 0; + for(i = 0; i < nwant; i++) { + XColor c; + c.red = want[i].r << 8; + c.green = want[i].g << 8; + c.blue = want[i].b << 8; + c.flags = DoRed | DoGreen | DoBlue; + if(XAllocColor(GFX_Display, dcmap, &c)) { + /* got the colour */ + SDL_iconcolors[c.pixel]++; + got[c.pixel] = want[i]; + } else { + missing = 1; + } + } + if(missing) { + /* Some colours were apparently missing, so we just + allocate all the rest as well */ + XColor cols[256]; + for(i = 0; i < 256; i++) + cols[i].pixel = i; + XQueryColors(GFX_Display, dcmap, cols, 256); + for(i = 0; i < 256; i++) { + got[i].r = cols[i].red >> 8; + got[i].g = cols[i].green >> 8; + got[i].b = cols[i].blue >> 8; + if(!SDL_iconcolors[i]) { + if(XAllocColor(GFX_Display, dcmap, + cols + i)) { + SDL_iconcolors[i] = 1; + } else { + /* index not available */ + got[i].r = 0; + got[i].g = 0; + got[i].b = 0; + } + } + } + } + + SDL_SetColors(sicon, got, 0, 256); + } + + bounds.x = 0; + bounds.y = 0; + bounds.w = icon->w; + bounds.h = icon->h; + if ( SDL_LowerBlit(icon, &bounds, sicon, &bounds) < 0 ) + goto done; + + /* We need the mask as given, except in LSBfirst format instead of + MSBfirst. Reverse the bits in each byte. */ + masksize = ((sicon->w + 7) >> 3) * sicon->h; + LSBmask = SDL_malloc(masksize); + if ( LSBmask == NULL ) { + goto done; + } + SDL_memset(LSBmask, 0, masksize); + for(i = 0; i < masksize; i++) + LSBmask[i] = reverse_byte(mask[i]); + mask_pixmap = XCreatePixmapFromBitmapData(SDL_Display, WMwindow, + (char *)LSBmask, + sicon->w, sicon->h, + 1L, 0L, 1); + + /* Transfer the image to an X11 pixmap */ + icon_image = XCreateImage(SDL_Display, + DefaultVisual(SDL_Display, SDL_Screen), + DefaultDepth(SDL_Display, SDL_Screen), + ZPixmap, 0, sicon->pixels, + sicon->w, sicon->h, + 32, 0); + icon_image->byte_order = (SDL_BYTEORDER == SDL_BIG_ENDIAN) + ? MSBFirst : LSBFirst; + icon_pixmap = XCreatePixmap(SDL_Display, SDL_Root, sicon->w, sicon->h, + DefaultDepth(SDL_Display, SDL_Screen)); + gc = XCreateGC(SDL_Display, icon_pixmap, 0, &GCvalues); + XPutImage(SDL_Display, icon_pixmap, gc, icon_image, + 0, 0, 0, 0, sicon->w, sicon->h); + XFreeGC(SDL_Display, gc); + XDestroyImage(icon_image); + SDL_free(LSBmask); + sicon->pixels = NULL; + + /* Some buggy window managers (some versions of Enlightenment, it + seems) need an icon window *and* icon pixmap to work properly, while + it screws up others. The default is only to use a pixmap. */ + p = SDL_getenv("SDL_VIDEO_X11_ICONWIN"); + if(p && *p) { + icon_window = XCreateSimpleWindow(SDL_Display, SDL_Root, + 0, 0, sicon->w, sicon->h, 0, + CopyFromParent, + CopyFromParent); + XSetWindowBackgroundPixmap(SDL_Display, icon_window, + icon_pixmap); + XClearWindow(SDL_Display, icon_window); + } + + /* Set the window icon to the icon pixmap (and icon window) */ + wmhints = XAllocWMHints(); + wmhints->flags = (IconPixmapHint | IconMaskHint | InputHint); + wmhints->icon_pixmap = icon_pixmap; + wmhints->icon_mask = mask_pixmap; + wmhints->input = True; + if(icon_window != None) { + wmhints->flags |= IconWindowHint; + wmhints->icon_window = icon_window; + } + XSetWMHints(SDL_Display, WMwindow, wmhints); + XFree(wmhints); + XSync(SDL_Display, False); + + done: + SDL_Unlock_EventThread(); + SDL_FreeSurface(sicon); +} + +void X11_SetCaptionNoLock(_THIS, const char *title, const char *icon) +{ + XTextProperty titleprop, iconprop; + Status status; + +#ifdef X_HAVE_UTF8_STRING + Atom _NET_WM_NAME = 0; + Atom _NET_WM_ICON_NAME = 0; + + /* Look up some useful Atoms */ + if (SDL_X11_HAVE_UTF8) { + _NET_WM_NAME = XInternAtom(SDL_Display, "_NET_WM_NAME", False); + _NET_WM_ICON_NAME = XInternAtom(SDL_Display, "_NET_WM_ICON_NAME", False); + } +#endif + + if ( title != NULL ) { + char *title_locale = SDL_iconv_utf8_locale(title); + if ( !title_locale ) { + SDL_OutOfMemory(); + return; + } + status = XStringListToTextProperty(&title_locale, 1, &titleprop); + SDL_free(title_locale); + if ( status ) { + XSetTextProperty(SDL_Display, WMwindow, &titleprop, XA_WM_NAME); + XFree(titleprop.value); + } +#ifdef X_HAVE_UTF8_STRING + if (SDL_X11_HAVE_UTF8) { + status = Xutf8TextListToTextProperty(SDL_Display, + (char **)&title, 1, XUTF8StringStyle, &titleprop); + if ( status == Success ) { + XSetTextProperty(SDL_Display, WMwindow, &titleprop, _NET_WM_NAME); + XFree(titleprop.value); + } + } +#endif + } + if ( icon != NULL ) { + char *icon_locale = SDL_iconv_utf8_locale(icon); + if ( !icon_locale ) { + SDL_OutOfMemory(); + return; + } + status = XStringListToTextProperty(&icon_locale, 1, &iconprop); + SDL_free(icon_locale); + if ( status ) { + XSetTextProperty(SDL_Display, WMwindow, &iconprop, XA_WM_ICON_NAME); + XFree(iconprop.value); + } +#ifdef X_HAVE_UTF8_STRING + if (SDL_X11_HAVE_UTF8) { + status = Xutf8TextListToTextProperty(SDL_Display, + (char **)&icon, 1, XUTF8StringStyle, &iconprop); + if ( status == Success ) { + XSetTextProperty(SDL_Display, WMwindow, &iconprop, _NET_WM_ICON_NAME); + XFree(iconprop.value); + } + } +#endif + } + XSync(SDL_Display, False); +} + +void X11_SetCaption(_THIS, const char *title, const char *icon) +{ + SDL_Lock_EventThread(); + X11_SetCaptionNoLock(this, title, icon); + SDL_Unlock_EventThread(); +} + +/* Iconify the window */ +int X11_IconifyWindow(_THIS) +{ + int result; + + SDL_Lock_EventThread(); + result = XIconifyWindow(SDL_Display, WMwindow, SDL_Screen); + XSync(SDL_Display, False); + SDL_Unlock_EventThread(); + return(result); +} + +SDL_GrabMode X11_GrabInputNoLock(_THIS, SDL_GrabMode mode) +{ + int result; + + if ( this->screen == NULL || SDL_Display == NULL ) { + return(SDL_GRAB_OFF); + } + if ( ! SDL_Window ) { + return(mode); /* Will be set later on mode switch */ + } + if ( mode == SDL_GRAB_OFF ) { + XUngrabPointer(SDL_Display, CurrentTime); + XUngrabKeyboard(SDL_Display, CurrentTime); + } else { + if ( this->screen->flags & SDL_FULLSCREEN ) { + /* Unbind the mouse from the fullscreen window */ + XUngrabPointer(SDL_Display, CurrentTime); + } + /* Try to grab the mouse */ +#if 0 /* We'll wait here until we actually grab, otherwise behavior undefined */ + for ( numtries = 0; numtries < 10; ++numtries ) { +#else + for ( ; ; ) { +#endif + result = XGrabPointer(SDL_Display, SDL_Window, True, 0, + GrabModeAsync, GrabModeAsync, + SDL_Window, None, CurrentTime); + if ( result == GrabSuccess ) { + break; + } + SDL_Delay(100); + } + if ( result != GrabSuccess ) { + /* Uh, oh, what do we do here? */ ; + } + /* Now grab the keyboard */ + XGrabKeyboard(SDL_Display, WMwindow, True, + GrabModeAsync, GrabModeAsync, CurrentTime); + + /* Raise the window if we grab the mouse */ + if ( !(this->screen->flags & SDL_FULLSCREEN) ) + XRaiseWindow(SDL_Display, WMwindow); + + /* Make sure we register input focus */ + SDL_PrivateAppActive(1, SDL_APPINPUTFOCUS); + /* Since we grabbed the pointer, we have mouse focus, too. */ + SDL_PrivateAppActive(1, SDL_APPMOUSEFOCUS); + } + XSync(SDL_Display, False); + + return(mode); +} + +SDL_GrabMode X11_GrabInput(_THIS, SDL_GrabMode mode) +{ + SDL_Lock_EventThread(); + mode = X11_GrabInputNoLock(this, mode); + SDL_Unlock_EventThread(); + + return(mode); +} + +/* If 'info' is the right version, this function fills it and returns 1. + Otherwise, in case of a version mismatch, it returns -1. +*/ +static void lock_display(void) +{ + SDL_Lock_EventThread(); +} +static void unlock_display(void) +{ + /* Make sure any X11 transactions are completed */ + SDL_VideoDevice *this = current_video; + XSync(SDL_Display, False); + SDL_Unlock_EventThread(); +} + +#include <stdio.h> +int X11_GetWMInfo(_THIS, SDL_SysWMinfo *info) +{ + if ( info->version.major <= SDL_MAJOR_VERSION ) { + info->subsystem = SDL_SYSWM_X11; + info->info.x11.display = SDL_Display; + info->info.x11.window = SDL_Window; + if ( SDL_VERSIONNUM(info->version.major, + info->version.minor, + info->version.patch) >= 1002 ) { + info->info.x11.fswindow = FSwindow; + info->info.x11.wmwindow = WMwindow; + } + + + if ( SDL_VERSIONNUM(info->version.major, + info->version.minor, + info->version.patch) >= 1212 ) { + info->info.x11.gfxdisplay = GFX_Display; + } + + info->info.x11.lock_func = lock_display; + info->info.x11.unlock_func = unlock_display; + return(1); + } else { + SDL_SetError("Application not compiled with SDL %d.%d\n", + SDL_MAJOR_VERSION, SDL_MINOR_VERSION); + return(-1); + } +} diff --git a/3rdparty/SDL/src/video/x11/SDL_x11wm_c.h b/3rdparty/SDL/src/video/x11/SDL_x11wm_c.h new file mode 100644 index 0000000..f85477b --- /dev/null +++ b/3rdparty/SDL/src/video/x11/SDL_x11wm_c.h @@ -0,0 +1,34 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#include "SDL_x11video.h" + +/* Functions to be exported */ +extern void X11_SetCaptionNoLock(_THIS, const char *title, const char *icon); +extern void X11_SetCaption(_THIS, const char *title, const char *icon); +extern void X11_SetIcon(_THIS, SDL_Surface *icon, Uint8 *mask); +extern int X11_IconifyWindow(_THIS); +extern SDL_GrabMode X11_GrabInputNoLock(_THIS, SDL_GrabMode mode); +extern SDL_GrabMode X11_GrabInput(_THIS, SDL_GrabMode mode); +extern int X11_GetWMInfo(_THIS, SDL_SysWMinfo *info); + diff --git a/3rdparty/SDL/src/video/x11/SDL_x11yuv.c b/3rdparty/SDL/src/video/x11/SDL_x11yuv.c new file mode 100644 index 0000000..62698df --- /dev/null +++ b/3rdparty/SDL/src/video/x11/SDL_x11yuv.c @@ -0,0 +1,538 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* This is the XFree86 Xv extension implementation of YUV video overlays */ + +#if SDL_VIDEO_DRIVER_X11_XV + +#include <X11/Xlib.h> +#ifndef NO_SHARED_MEMORY +#include <sys/ipc.h> +#include <sys/shm.h> +#include <X11/extensions/XShm.h> +#endif +#include "../Xext/extensions/Xvlib.h" + +#include "SDL_x11yuv_c.h" +#include "../SDL_yuvfuncs.h" + +#define XFREE86_REFRESH_HACK +#ifdef XFREE86_REFRESH_HACK +#include "SDL_x11image_c.h" +#endif + +/* Workaround when pitch != width */ +#define PITCH_WORKAROUND + +/* Workaround intel i810 video overlay waiting with failing until the + first Xv[Shm]PutImage call <sigh> */ +#define INTEL_XV_BADALLOC_WORKAROUND + +/* Fix for the NVidia GeForce 2 - use the last available adaptor */ +/*#define USE_LAST_ADAPTOR*/ /* Apparently the NVidia drivers are fixed */ + +/* The functions used to manipulate software video overlays */ +static struct private_yuvhwfuncs x11_yuvfuncs = { + X11_LockYUVOverlay, + X11_UnlockYUVOverlay, + X11_DisplayYUVOverlay, + X11_FreeYUVOverlay +}; + +struct private_yuvhwdata { + int port; +#ifndef NO_SHARED_MEMORY + int yuv_use_mitshm; + XShmSegmentInfo yuvshm; +#endif + SDL_NAME(XvImage) *image; +}; + + +static int (*X_handler)(Display *, XErrorEvent *) = NULL; + +#ifndef NO_SHARED_MEMORY +/* Shared memory error handler routine */ +static int shm_error; +static int shm_errhandler(Display *d, XErrorEvent *e) +{ + if ( e->error_code == BadAccess ) { + shm_error = True; + return(0); + } else + return(X_handler(d,e)); +} +#endif /* !NO_SHARED_MEMORY */ + +static int xv_error; +static int xv_errhandler(Display *d, XErrorEvent *e) +{ + if ( e->error_code == BadMatch ) { + xv_error = True; + return(0); + } else + return(X_handler(d,e)); +} + +#ifdef INTEL_XV_BADALLOC_WORKAROUND +static int intel_errhandler(Display *d, XErrorEvent *e) +{ + if ( e->error_code == BadAlloc ) { + xv_error = True; + return(0); + } else + return(X_handler(d,e)); +} + +static void X11_ClearYUVOverlay(SDL_Overlay *overlay) +{ + int x,y; + + switch (overlay->format) + { + case SDL_YV12_OVERLAY: + case SDL_IYUV_OVERLAY: + for (y = 0; y < overlay->h; y++) + memset(overlay->pixels[0] + y * overlay->pitches[0], + 0, overlay->w); + + for (y = 0; y < (overlay->h / 2); y++) + { + memset(overlay->pixels[1] + y * overlay->pitches[1], + -128, overlay->w / 2); + memset(overlay->pixels[2] + y * overlay->pitches[2], + -128, overlay->w / 2); + } + break; + case SDL_YUY2_OVERLAY: + case SDL_YVYU_OVERLAY: + for (y = 0; y < overlay->h; y++) + { + for (x = 0; x < overlay->w; x += 2) + { + Uint8 *pixel_pair = overlay->pixels[0] + + y * overlay->pitches[0] + x * 2; + pixel_pair[0] = 0; + pixel_pair[1] = -128; + pixel_pair[2] = 0; + pixel_pair[3] = -128; + } + } + break; + case SDL_UYVY_OVERLAY: + for (y = 0; y < overlay->h; y++) + { + for (x = 0; x < overlay->w; x += 2) + { + Uint8 *pixel_pair = overlay->pixels[0] + + y * overlay->pitches[0] + x * 2; + pixel_pair[0] = -128; + pixel_pair[1] = 0; + pixel_pair[2] = -128; + pixel_pair[3] = 0; + } + } + break; + } +} +#endif + +SDL_Overlay *X11_CreateYUVOverlay(_THIS, int width, int height, Uint32 format, SDL_Surface *display) +{ + SDL_Overlay *overlay; + struct private_yuvhwdata *hwdata; + int xv_port; + unsigned int i, j, k; + unsigned int adaptors; + SDL_NAME(XvAdaptorInfo) *ainfo; + int bpp; +#ifndef NO_SHARED_MEMORY + XShmSegmentInfo *yuvshm; +#endif +#ifdef INTEL_XV_BADALLOC_WORKAROUND + int intel_adapter = False; +#endif + + /* Look for the XVideo extension with a valid port for this format */ + xv_port = -1; + if ( (Success == SDL_NAME(XvQueryExtension)(GFX_Display, &j, &j, &j, &j, &j)) && + (Success == SDL_NAME(XvQueryAdaptors)(GFX_Display, + RootWindow(GFX_Display, SDL_Screen), + &adaptors, &ainfo)) ) { +#ifdef USE_LAST_ADAPTOR + for ( i=0; i < adaptors; ++i ) +#else + for ( i=0; (i < adaptors) && (xv_port == -1); ++i ) +#endif /* USE_LAST_ADAPTOR */ + { + /* Check to see if the visual can be used */ + if ( BUGGY_XFREE86(<=, 4001) ) { + int visual_ok = 0; + for ( j=0; j<ainfo[i].num_formats; ++j ) { + if ( ainfo[i].formats[j].visual_id == + SDL_Visual->visualid ) { + visual_ok = 1; + break; + } + } + if ( ! visual_ok ) { + continue; + } + } +#ifdef INTEL_XV_BADALLOC_WORKAROUND + if ( !strcmp(ainfo[i].name, "Intel(R) Video Overla")) + intel_adapter = True; + else + intel_adapter = False; +#endif + if ( (ainfo[i].type & XvInputMask) && + (ainfo[i].type & XvImageMask) ) { + int num_formats; + SDL_NAME(XvImageFormatValues) *formats; + formats = SDL_NAME(XvListImageFormats)(GFX_Display, + ainfo[i].base_id, &num_formats); +#ifdef USE_LAST_ADAPTOR + for ( j=0; j < num_formats; ++j ) +#else + for ( j=0; (j < num_formats) && (xv_port == -1); ++j ) +#endif /* USE_LAST_ADAPTOR */ + { + if ( (Uint32)formats[j].id == format ) { + for ( k=0; k < ainfo[i].num_ports; ++k ) { + if ( Success == SDL_NAME(XvGrabPort)(GFX_Display, ainfo[i].base_id+k, CurrentTime) ) { + xv_port = ainfo[i].base_id+k; + break; + } + } + } + } + if ( formats ) { + XFree(formats); + } + } + } + SDL_NAME(XvFreeAdaptorInfo)(ainfo); + } + + /* Precalculate the bpp for the pitch workaround below */ + switch (format) { + /* Add any other cases we need to support... */ + case SDL_YUY2_OVERLAY: + case SDL_UYVY_OVERLAY: + case SDL_YVYU_OVERLAY: + bpp = 2; + break; + default: + bpp = 1; + break; + } + +#if 0 + /* + * !!! FIXME: + * "Here are some diffs for X11 and yuv. Note that the last part 2nd + * diff should probably be a new call to XvQueryAdaptorFree with ainfo + * and the number of adaptors, instead of the loop through like I did." + * + * ACHTUNG: This is broken! It looks like XvFreeAdaptorInfo does this + * for you, so we end up with a double-free. I need to look at this + * more closely... --ryan. + */ + for ( i=0; i < adaptors; ++i ) { + if (ainfo[i].name != NULL) Xfree(ainfo[i].name); + if (ainfo[i].formats != NULL) Xfree(ainfo[i].formats); + } + Xfree(ainfo); +#endif + + if ( xv_port == -1 ) { + SDL_SetError("No available video ports for requested format"); + return(NULL); + } + + /* Enable auto-painting of the overlay colorkey */ + { + static const char *attr[] = { "XV_AUTOPAINT_COLORKEY", "XV_AUTOPAINT_COLOURKEY" }; + unsigned int i; + + SDL_NAME(XvSelectPortNotify)(GFX_Display, xv_port, True); + X_handler = XSetErrorHandler(xv_errhandler); + for ( i=0; i < sizeof(attr)/(sizeof attr[0]); ++i ) { + Atom a; + + xv_error = False; + a = XInternAtom(GFX_Display, attr[i], True); + if ( a != None ) { + SDL_NAME(XvSetPortAttribute)(GFX_Display, xv_port, a, 1); + XSync(GFX_Display, True); + if ( ! xv_error ) { + break; + } + } + } + XSetErrorHandler(X_handler); + SDL_NAME(XvSelectPortNotify)(GFX_Display, xv_port, False); + } + + /* Create the overlay structure */ + overlay = (SDL_Overlay *)SDL_malloc(sizeof *overlay); + if ( overlay == NULL ) { + SDL_NAME(XvUngrabPort)(GFX_Display, xv_port, CurrentTime); + SDL_OutOfMemory(); + return(NULL); + } + SDL_memset(overlay, 0, (sizeof *overlay)); + + /* Fill in the basic members */ + overlay->format = format; + overlay->w = width; + overlay->h = height; + + /* Set up the YUV surface function structure */ + overlay->hwfuncs = &x11_yuvfuncs; + overlay->hw_overlay = 1; + + /* Create the pixel data and lookup tables */ + hwdata = (struct private_yuvhwdata *)SDL_malloc(sizeof *hwdata); + overlay->hwdata = hwdata; + if ( hwdata == NULL ) { + SDL_NAME(XvUngrabPort)(GFX_Display, xv_port, CurrentTime); + SDL_OutOfMemory(); + SDL_FreeYUVOverlay(overlay); + return(NULL); + } + hwdata->port = xv_port; +#ifndef NO_SHARED_MEMORY + yuvshm = &hwdata->yuvshm; + SDL_memset(yuvshm, 0, sizeof(*yuvshm)); + hwdata->image = SDL_NAME(XvShmCreateImage)(GFX_Display, xv_port, format, + 0, width, height, yuvshm); +#ifdef PITCH_WORKAROUND + if ( hwdata->image != NULL && hwdata->image->pitches[0] != (width*bpp) ) { + /* Ajust overlay width according to pitch */ + width = hwdata->image->pitches[0] / bpp; + XFree(hwdata->image); + hwdata->image = SDL_NAME(XvShmCreateImage)(GFX_Display, xv_port, format, + 0, width, height, yuvshm); + } +#endif /* PITCH_WORKAROUND */ + hwdata->yuv_use_mitshm = (hwdata->image != NULL); + if ( hwdata->yuv_use_mitshm ) { + yuvshm->shmid = shmget(IPC_PRIVATE, hwdata->image->data_size, + IPC_CREAT | 0777); + if ( yuvshm->shmid >= 0 ) { + yuvshm->shmaddr = (char *)shmat(yuvshm->shmid, 0, 0); + yuvshm->readOnly = False; + if ( yuvshm->shmaddr != (char *)-1 ) { + shm_error = False; + X_handler = XSetErrorHandler(shm_errhandler); + XShmAttach(GFX_Display, yuvshm); + XSync(GFX_Display, True); + XSetErrorHandler(X_handler); + if ( shm_error ) + shmdt(yuvshm->shmaddr); + } else { + shm_error = True; + } + shmctl(yuvshm->shmid, IPC_RMID, NULL); + } else { + shm_error = True; + } + if ( shm_error ) { + XFree(hwdata->image); + hwdata->yuv_use_mitshm = 0; + } else { + hwdata->image->data = yuvshm->shmaddr; + } + } + if ( !hwdata->yuv_use_mitshm ) +#endif /* NO_SHARED_MEMORY */ + { + hwdata->image = SDL_NAME(XvCreateImage)(GFX_Display, xv_port, format, + 0, width, height); + +#ifdef PITCH_WORKAROUND + if ( hwdata->image != NULL && hwdata->image->pitches[0] != (width*bpp) ) { + /* Ajust overlay width according to pitch */ + XFree(hwdata->image); + width = hwdata->image->pitches[0] / bpp; + hwdata->image = SDL_NAME(XvCreateImage)(GFX_Display, xv_port, format, + 0, width, height); + } +#endif /* PITCH_WORKAROUND */ + if ( hwdata->image == NULL ) { + SDL_SetError("Couldn't create XVideo image"); + SDL_FreeYUVOverlay(overlay); + return(NULL); + } + hwdata->image->data = SDL_malloc(hwdata->image->data_size); + if ( hwdata->image->data == NULL ) { + SDL_OutOfMemory(); + SDL_FreeYUVOverlay(overlay); + return(NULL); + } + } + + /* Find the pitch and offset values for the overlay */ + overlay->planes = hwdata->image->num_planes; + overlay->pitches = (Uint16 *)SDL_malloc(overlay->planes * sizeof(Uint16)); + overlay->pixels = (Uint8 **)SDL_malloc(overlay->planes * sizeof(Uint8 *)); + if ( !overlay->pitches || !overlay->pixels ) { + SDL_OutOfMemory(); + SDL_FreeYUVOverlay(overlay); + return(NULL); + } + for ( i=0; i<overlay->planes; ++i ) { + overlay->pitches[i] = hwdata->image->pitches[i]; + overlay->pixels[i] = (Uint8 *)hwdata->image->data + + hwdata->image->offsets[i]; + } + +#ifdef XFREE86_REFRESH_HACK + /* Work around an XFree86 X server bug (?) + We can't perform normal updates in windows that have video + being output to them. See SDL_x11image.c for more details. + */ + X11_DisableAutoRefresh(this); +#endif + +#ifdef INTEL_XV_BADALLOC_WORKAROUND + /* HACK, GRRR sometimes (i810) creating the overlay succeeds, but the + first call to XvShm[Put]Image to a mapped window fails with: + "BadAlloc (insufficient resources for operation)". This happens with + certain formats when the XvImage is too large to the i810's liking. + + We work around this by doing a test XvShm[Put]Image with a black + Xv image, this may cause some flashing, so only do this check if we + are running on an intel Xv-adapter. */ + if (intel_adapter) + { + xv_error = False; + X_handler = XSetErrorHandler(intel_errhandler); + + X11_ClearYUVOverlay(overlay); + + /* We set the destination height and width to 1 pixel to avoid + putting a large black rectangle over the screen, thus + strongly reducing possible flashing. */ +#ifndef NO_SHARED_MEMORY + if ( hwdata->yuv_use_mitshm ) { + SDL_NAME(XvShmPutImage)(GFX_Display, hwdata->port, + SDL_Window, SDL_GC, + hwdata->image, + 0, 0, overlay->w, overlay->h, + 0, 0, 1, 1, False); + } + else +#endif + { + SDL_NAME(XvPutImage)(GFX_Display, hwdata->port, + SDL_Window, SDL_GC, + hwdata->image, + 0, 0, overlay->w, overlay->h, + 0, 0, 1, 1); + } + XSync(GFX_Display, False); + XSetErrorHandler(X_handler); + + if (xv_error) + { + X11_FreeYUVOverlay(this, overlay); + return NULL; + } + /* Repair the (1 pixel worth of) damage we've just done */ + X11_RefreshDisplay(this); + } +#endif + + /* We're all done.. */ + return(overlay); +} + +int X11_LockYUVOverlay(_THIS, SDL_Overlay *overlay) +{ + return(0); +} + +void X11_UnlockYUVOverlay(_THIS, SDL_Overlay *overlay) +{ + return; +} + +int X11_DisplayYUVOverlay(_THIS, SDL_Overlay *overlay, SDL_Rect *src, SDL_Rect *dst) +{ + struct private_yuvhwdata *hwdata; + + hwdata = overlay->hwdata; + +#ifndef NO_SHARED_MEMORY + if ( hwdata->yuv_use_mitshm ) { + SDL_NAME(XvShmPutImage)(GFX_Display, hwdata->port, SDL_Window, SDL_GC, + hwdata->image, + src->x, src->y, src->w, src->h, + dst->x, dst->y, dst->w, dst->h, False); + } + else +#endif + { + SDL_NAME(XvPutImage)(GFX_Display, hwdata->port, SDL_Window, SDL_GC, + hwdata->image, + src->x, src->y, src->w, src->h, + dst->x, dst->y, dst->w, dst->h); + } + XSync(GFX_Display, False); + return(0); +} + +void X11_FreeYUVOverlay(_THIS, SDL_Overlay *overlay) +{ + struct private_yuvhwdata *hwdata; + + hwdata = overlay->hwdata; + if ( hwdata ) { + SDL_NAME(XvUngrabPort)(GFX_Display, hwdata->port, CurrentTime); +#ifndef NO_SHARED_MEMORY + if ( hwdata->yuv_use_mitshm ) { + XShmDetach(GFX_Display, &hwdata->yuvshm); + shmdt(hwdata->yuvshm.shmaddr); + } +#endif + if ( hwdata->image ) { + XFree(hwdata->image); + } + SDL_free(hwdata); + } + if ( overlay->pitches ) { + SDL_free(overlay->pitches); + overlay->pitches = NULL; + } + if ( overlay->pixels ) { + SDL_free(overlay->pixels); + overlay->pixels = NULL; + } +#ifdef XFREE86_REFRESH_HACK + X11_EnableAutoRefresh(this); +#endif +} + +#endif /* SDL_VIDEO_DRIVER_X11_XV */ diff --git a/3rdparty/SDL/src/video/x11/SDL_x11yuv_c.h b/3rdparty/SDL/src/video/x11/SDL_x11yuv_c.h new file mode 100644 index 0000000..d297683 --- /dev/null +++ b/3rdparty/SDL/src/video/x11/SDL_x11yuv_c.h @@ -0,0 +1,41 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* This is the XFree86 Xv extension implementation of YUV video overlays */ + +#include "SDL_video.h" +#include "SDL_x11video.h" + +#if SDL_VIDEO_DRIVER_X11_XV + +extern SDL_Overlay *X11_CreateYUVOverlay(_THIS, int width, int height, Uint32 format, SDL_Surface *display); + +extern int X11_LockYUVOverlay(_THIS, SDL_Overlay *overlay); + +extern void X11_UnlockYUVOverlay(_THIS, SDL_Overlay *overlay); + +extern int X11_DisplayYUVOverlay(_THIS, SDL_Overlay *overlay, SDL_Rect *src, SDL_Rect *dst); + +extern void X11_FreeYUVOverlay(_THIS, SDL_Overlay *overlay); + +#endif /* SDL_VIDEO_DRIVER_X11_XV */ diff --git a/3rdparty/SDL/src/video/xbios/SDL_xbios.c b/3rdparty/SDL/src/video/xbios/SDL_xbios.c new file mode 100644 index 0000000..56bf6ab --- /dev/null +++ b/3rdparty/SDL/src/video/xbios/SDL_xbios.c @@ -0,0 +1,1116 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* + * Xbios SDL video driver + * + * Patrice Mandin + */ + +#include <sys/stat.h> +#include <unistd.h> + +/* Mint includes */ +#include <mint/cookie.h> +#include <mint/osbind.h> +#include <mint/falcon.h> + +#include "SDL_video.h" +#include "SDL_mouse.h" +#include "../SDL_sysvideo.h" +#include "../SDL_pixels_c.h" +#include "../../events/SDL_events_c.h" + +#include "../ataricommon/SDL_ataric2p_s.h" +#include "../ataricommon/SDL_atarievents_c.h" +#include "../ataricommon/SDL_atarimxalloc_c.h" +#include "../ataricommon/SDL_atarigl_c.h" +#include "SDL_xbios.h" +#include "SDL_xbios_blowup.h" +#include "SDL_xbios_centscreen.h" +#include "SDL_xbios_sb3.h" +#include "SDL_xbios_tveille.h" +#include "SDL_xbios_milan.h" + +#define XBIOS_VID_DRIVER_NAME "xbios" + +#ifndef C_fVDI +#define C_fVDI 0x66564449L +#endif + +/* Debug print info */ +#if 0 +#define DEBUG_PRINT(what) \ + { \ + printf what; \ + } +#define DEBUG_VIDEO_XBIOS 1 +#else +#define DEBUG_PRINT(what) +#undef DEBUG_VIDEO_XBIOS +#endif + +/* Initialization/Query functions */ +static int XBIOS_VideoInit(_THIS, SDL_PixelFormat *vformat); +static SDL_Rect **XBIOS_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags); +static SDL_Surface *XBIOS_SetVideoMode(_THIS, SDL_Surface *current, int width, int height, int bpp, Uint32 flags); +static int XBIOS_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors); +static void XBIOS_VideoQuit(_THIS); + +/* Hardware surface functions */ +static int XBIOS_AllocHWSurface(_THIS, SDL_Surface *surface); +static int XBIOS_LockHWSurface(_THIS, SDL_Surface *surface); +static int XBIOS_FlipHWSurface(_THIS, SDL_Surface *surface); +static void XBIOS_UnlockHWSurface(_THIS, SDL_Surface *surface); +static void XBIOS_FreeHWSurface(_THIS, SDL_Surface *surface); +static void XBIOS_UpdateRects(_THIS, int numrects, SDL_Rect *rects); + +#if SDL_VIDEO_OPENGL +/* OpenGL functions */ +static void XBIOS_GL_SwapBuffers(_THIS); +#endif + +/* To setup palette */ + +static unsigned short TT_palette[256]; +static unsigned long F30_palette[256]; + +/* Default list of video modes */ + +static const xbiosmode_t stmodes[1]={ + {ST_LOW>>8,320,200,4, XBIOSMODE_C2P} +}; + +static const xbiosmode_t ttmodes[2]={ + {TT_LOW,320,480,8, XBIOSMODE_C2P}, + {TT_LOW,320,240,8, XBIOSMODE_C2P|XBIOSMODE_DOUBLELINE} +}; + +static const xbiosmode_t falconrgbmodes[16]={ + {BPS16|COL80|OVERSCAN|VERTFLAG,768,480,16,0}, + {BPS16|COL80|OVERSCAN,768,240,16,0}, + {BPS16|COL80|VERTFLAG,640,400,16,0}, + {BPS16|COL80,640,200,16,0}, + {BPS16|OVERSCAN|VERTFLAG,384,480,16,0}, + {BPS16|OVERSCAN,384,240,16,0}, + {BPS16|VERTFLAG,320,400,16,0}, + {BPS16,320,200,16,0}, + {BPS8|COL80|OVERSCAN|VERTFLAG,768,480,8,XBIOSMODE_C2P}, + {BPS8|COL80|OVERSCAN,768,240,8,XBIOSMODE_C2P}, + {BPS8|COL80|VERTFLAG,640,400,8,XBIOSMODE_C2P}, + {BPS8|COL80,640,200,8,XBIOSMODE_C2P}, + {BPS8|OVERSCAN|VERTFLAG,384,480,8,XBIOSMODE_C2P}, + {BPS8|OVERSCAN,384,240,8,XBIOSMODE_C2P}, + {BPS8|VERTFLAG,320,400,8,XBIOSMODE_C2P}, + {BPS8,320,200,8,XBIOSMODE_C2P} +}; + +static const xbiosmode_t falconvgamodes[6]={ + {BPS16,320,480,16,0}, + {BPS16|VERTFLAG,320,240,16,0}, + {BPS8|COL80,640,480,8,XBIOSMODE_C2P}, + {BPS8|COL80|VERTFLAG,640,240,8,XBIOSMODE_C2P}, + {BPS8,320,480,8,XBIOSMODE_C2P}, + {BPS8|VERTFLAG,320,240,8,XBIOSMODE_C2P} +}; + +/* Xbios driver bootstrap functions */ + +static int XBIOS_Available(void) +{ + long cookie_vdo, /*cookie_mil,*/ cookie_hade, cookie_scpn; + long cookie_fvdi; + const char *envr = SDL_getenv("SDL_VIDEODRIVER"); + + /* Milan/Hades Atari clones do not have an Atari video chip */ + if ( /*(Getcookie(C__MIL, &cookie_mil) == C_FOUND) ||*/ + (Getcookie(C_hade, &cookie_hade) == C_FOUND) ) { + return 0; + } + + /* fVDI means graphic card, so no Xbios with it */ + if (Getcookie(C_fVDI, &cookie_fvdi) == C_FOUND) { + if (!envr) { + return 0; + } + if (SDL_strcmp(envr, XBIOS_VID_DRIVER_NAME)!=0) { + return 0; + } + /* Except if we force Xbios usage, through env var */ + } + + /* Cookie _VDO present ? if not, assume ST machine */ + if (Getcookie(C__VDO, &cookie_vdo) != C_FOUND) { + cookie_vdo = VDO_ST << 16; + } + + /* Test if we have a monochrome monitor plugged in */ + switch( cookie_vdo >>16) { + case VDO_ST: + case VDO_STE: + if ( Getrez() == (ST_HIGH>>8) ) + return 0; + break; + case VDO_TT: + if ( (EgetShift() & ES_MODE) == TT_HIGH) + return 0; + break; + case VDO_F30: + if ( VgetMonitor() == MONITOR_MONO) + return 0; + if (Getcookie(C_SCPN, &cookie_scpn) == C_FOUND) { + if (!SDL_XBIOS_SB3Usable((scpn_cookie_t *)cookie_scpn)) { + return 0; + } + } + break; + case VDO_MILAN: + break; + default: + return 0; + } + + return 1; +} + +static void XBIOS_DeleteDevice(SDL_VideoDevice *device) +{ + SDL_free(device->hidden); + SDL_free(device); +} + +static SDL_VideoDevice *XBIOS_CreateDevice(int devindex) +{ + SDL_VideoDevice *device; + + /* Initialize all variables that we clean on shutdown */ + device = (SDL_VideoDevice *)SDL_malloc(sizeof(SDL_VideoDevice)); + if ( device ) { + SDL_memset(device, 0, (sizeof *device)); + device->hidden = (struct SDL_PrivateVideoData *) + SDL_malloc((sizeof *device->hidden)); + device->gl_data = (struct SDL_PrivateGLData *) + SDL_malloc((sizeof *device->gl_data)); + } + if ( (device == NULL) || (device->hidden == NULL) ) { + SDL_OutOfMemory(); + if ( device ) { + SDL_free(device); + } + return(0); + } + SDL_memset(device->hidden, 0, (sizeof *device->hidden)); + SDL_memset(device->gl_data, 0, sizeof(*device->gl_data)); + + /* Video functions */ + device->VideoInit = XBIOS_VideoInit; + device->ListModes = XBIOS_ListModes; + device->SetVideoMode = XBIOS_SetVideoMode; + device->SetColors = XBIOS_SetColors; + device->UpdateRects = NULL; + device->VideoQuit = XBIOS_VideoQuit; + device->AllocHWSurface = XBIOS_AllocHWSurface; + device->LockHWSurface = XBIOS_LockHWSurface; + device->UnlockHWSurface = XBIOS_UnlockHWSurface; + device->FlipHWSurface = XBIOS_FlipHWSurface; + device->FreeHWSurface = XBIOS_FreeHWSurface; + +#if SDL_VIDEO_OPENGL + /* OpenGL functions */ + device->GL_LoadLibrary = SDL_AtariGL_LoadLibrary; + device->GL_GetProcAddress = SDL_AtariGL_GetProcAddress; + device->GL_GetAttribute = SDL_AtariGL_GetAttribute; + device->GL_MakeCurrent = SDL_AtariGL_MakeCurrent; + device->GL_SwapBuffers = XBIOS_GL_SwapBuffers; +#endif + + /* Events */ + device->InitOSKeymap = Atari_InitOSKeymap; + device->PumpEvents = Atari_PumpEvents; + + device->free = XBIOS_DeleteDevice; + + return device; +} + +VideoBootStrap XBIOS_bootstrap = { + XBIOS_VID_DRIVER_NAME, "Atari Xbios driver", + XBIOS_Available, XBIOS_CreateDevice +}; + +void SDL_XBIOS_AddMode(_THIS, int actually_add, const xbiosmode_t *modeinfo) +{ + int i = 0; + + switch(modeinfo->depth) { + case 15: + case 16: + i = 1; + break; + case 24: + i = 2; + break; + case 32: + i = 3; + break; + } + + if ( actually_add ) { + SDL_Rect saved_rect[2]; + xbiosmode_t saved_mode[2]; + int b, j; + + /* Add the mode, sorted largest to smallest */ + b = 0; + j = 0; + while ( (SDL_modelist[i][j]->w > modeinfo->width) || + (SDL_modelist[i][j]->h > modeinfo->height) ) { + ++j; + } + /* Skip modes that are already in our list */ + if ( (SDL_modelist[i][j]->w == modeinfo->width) && + (SDL_modelist[i][j]->h == modeinfo->height) ) { + return; + } + /* Insert the new mode */ + saved_rect[b] = *SDL_modelist[i][j]; + SDL_memcpy(&saved_mode[b], SDL_xbiosmode[i][j], sizeof(xbiosmode_t)); + SDL_modelist[i][j]->w = modeinfo->width; + SDL_modelist[i][j]->h = modeinfo->height; + SDL_memcpy(SDL_xbiosmode[i][j], modeinfo, sizeof(xbiosmode_t)); + /* Everybody scoot down! */ + if ( saved_rect[b].w && saved_rect[b].h ) { + for ( ++j; SDL_modelist[i][j]->w; ++j ) { + saved_rect[!b] = *SDL_modelist[i][j]; + memcpy(&saved_mode[!b], SDL_xbiosmode[i][j], sizeof(xbiosmode_t)); + *SDL_modelist[i][j] = saved_rect[b]; + SDL_memcpy(SDL_xbiosmode[i][j], &saved_mode[b], sizeof(xbiosmode_t)); + b = !b; + } + *SDL_modelist[i][j] = saved_rect[b]; + SDL_memcpy(SDL_xbiosmode[i][j], &saved_mode[b], sizeof(xbiosmode_t)); + } + } else { + ++SDL_nummodes[i]; + } +} + +static void XBIOS_ListSTModes(_THIS, int actually_add) +{ + SDL_XBIOS_AddMode(this, actually_add, &stmodes[0]); +} + +static void XBIOS_ListTTModes(_THIS, int actually_add) +{ + int i; + + for (i=0; i<2; i++) { + SDL_XBIOS_AddMode(this, actually_add, &ttmodes[i]); + } +} + +static void XBIOS_ListFalconRgbModes(_THIS, int actually_add) +{ + int i; + + for (i=0; i<16; i++) { + xbiosmode_t modeinfo; + + SDL_memcpy(&modeinfo, &falconrgbmodes[i], sizeof(xbiosmode_t)); + modeinfo.number &= ~(VGA|PAL); + modeinfo.number |= XBIOS_oldvmode & (VGA|PAL); + + SDL_XBIOS_AddMode(this, actually_add, &modeinfo); + } +} + +static void XBIOS_ListFalconVgaModes(_THIS, int actually_add) +{ + int i; + + for (i=0; i<6; i++) { + xbiosmode_t modeinfo; + + SDL_memcpy(&modeinfo, &falconvgamodes[i], sizeof(xbiosmode_t)); + modeinfo.number &= ~(VGA|PAL); + modeinfo.number |= XBIOS_oldvmode & (VGA|PAL); + + SDL_XBIOS_AddMode(this, actually_add, &modeinfo); + } +} + +static int XBIOS_VideoInit(_THIS, SDL_PixelFormat *vformat) +{ + int i; + long cookie_blow, cookie_scpn, cookie_cnts; + + /* Initialize all variables that we clean on shutdown */ + for ( i=0; i<NUM_MODELISTS; ++i ) { + SDL_nummodes[i] = 0; + SDL_modelist[i] = NULL; + SDL_xbiosmode[i] = NULL; + } + + /* Cookie _VDO present ? if not, assume ST machine */ + if (Getcookie(C__VDO, &XBIOS_cvdo) != C_FOUND) { + XBIOS_cvdo = VDO_ST << 16; + } + + /* Allocate memory for old palette */ + XBIOS_oldpalette = (void *)SDL_malloc(256*sizeof(long)); + if ( !XBIOS_oldpalette ) { + SDL_SetError("Unable to allocate memory for old palette\n"); + return(-1); + } + + /* Initialize video mode list */ + /* and save current screen status (palette, screen address, video mode) */ + XBIOS_centscreen = SDL_FALSE; + XBIOS_oldvbase = Physbase(); + + /* Determine the current screen size */ + this->info.current_w = 0; + this->info.current_h = 0; + + /* Determine the screen depth (use default 8-bit depth) */ + vformat->BitsPerPixel = 8; + + /* First allocate room for needed video modes */ + switch (XBIOS_cvdo >>16) { + case VDO_ST: + case VDO_STE: + { + short *oldpalette; + + XBIOS_oldvmode=Getrez(); + switch(XBIOS_oldvmode << 8) { + case ST_LOW: + XBIOS_oldnumcol=16; + break; + case ST_MED: + XBIOS_oldnumcol=4; + break; + case ST_HIGH: + XBIOS_oldnumcol=2; + break; + } + + oldpalette= (short *) XBIOS_oldpalette; + for (i=0;i<XBIOS_oldnumcol;i++) { + *oldpalette++=Setcolor(i,-1); + } + + XBIOS_ListSTModes(this, 0); + } + break; + case VDO_TT: + XBIOS_oldvmode=EgetShift(); + + switch(XBIOS_oldvmode & ES_MODE) { + case TT_LOW: + XBIOS_oldnumcol=256; + break; + case ST_LOW: + case TT_MED: + XBIOS_oldnumcol=16; + break; + case ST_MED: + XBIOS_oldnumcol=4; + break; + case ST_HIGH: + case TT_HIGH: + XBIOS_oldnumcol=2; + break; + } + if (XBIOS_oldnumcol) { + EgetPalette(0, XBIOS_oldnumcol, XBIOS_oldpalette); + } + + XBIOS_ListTTModes(this, 0); + break; + case VDO_F30: + XBIOS_oldvmode=VsetMode(-1); + + XBIOS_oldnumcol= 1<< (1 << (XBIOS_oldvmode & NUMCOLS)); + if (XBIOS_oldnumcol > 256) { + XBIOS_oldnumcol = 0; + } + if (XBIOS_oldnumcol) { + VgetRGB(0, XBIOS_oldnumcol, XBIOS_oldpalette); + } + + vformat->BitsPerPixel = 16; + + /* ScreenBlaster 3 ? */ + if (Getcookie(C_SCPN, &cookie_scpn) == C_FOUND) { + SDL_XBIOS_ListSB3Modes(this, 0, (scpn_cookie_t *)cookie_scpn); + } else + /* Centscreen ? */ + if (Getcookie(C_CNTS, &cookie_cnts) == C_FOUND) { + XBIOS_oldvmode = SDL_XBIOS_ListCentscreenModes(this, 0); + XBIOS_centscreen = SDL_TRUE; + } else + /* Standard, with or without Blowup */ + { + switch (VgetMonitor()) + { + case MONITOR_RGB: + case MONITOR_TV: + XBIOS_ListFalconRgbModes(this, 0); + break; + case MONITOR_VGA: + XBIOS_ListFalconVgaModes(this, 0); + break; + } + + if (Getcookie(C_BLOW, &cookie_blow) == C_FOUND) { + SDL_XBIOS_ListBlowupModes(this, 0, (blow_cookie_t *)cookie_blow); + } + } + break; + case VDO_MILAN: + { + SCREENINFO si; + + /* Read infos about current mode */ + VsetScreen(-1, &XBIOS_oldvmode, MI_MAGIC, CMD_GETMODE); + + si.size = sizeof(SCREENINFO); + si.devID = XBIOS_oldvmode; + si.scrFlags = 0; + VsetScreen(-1, &si, MI_MAGIC, CMD_GETINFO); + + this->info.current_w = si.scrWidth; + this->info.current_h = si.scrHeight; + + XBIOS_oldnumcol = 0; + if (si.scrFlags & SCRINFO_OK) { + if (si.scrPlanes <= 8) { + XBIOS_oldnumcol = 1<<si.scrPlanes; + } + } + if (XBIOS_oldnumcol) { + VgetRGB(0, XBIOS_oldnumcol, XBIOS_oldpalette); + } + + SDL_XBIOS_ListMilanModes(this, 0); + } + break; + } + + for ( i=0; i<NUM_MODELISTS; ++i ) { + int j; + + SDL_xbiosmode[i] = (xbiosmode_t **) + SDL_malloc((SDL_nummodes[i]+1)*sizeof(xbiosmode_t *)); + if ( SDL_xbiosmode[i] == NULL ) { + SDL_OutOfMemory(); + return(-1); + } + for ( j=0; j<SDL_nummodes[i]; ++j ) { + SDL_xbiosmode[i][j]=(xbiosmode_t *)SDL_malloc(sizeof(xbiosmode_t)); + if ( SDL_xbiosmode[i][j] == NULL ) { + SDL_OutOfMemory(); + return(-1); + } + SDL_memset(SDL_xbiosmode[i][j], 0, sizeof(xbiosmode_t)); + } + SDL_xbiosmode[i][j] = NULL; + + SDL_modelist[i] = (SDL_Rect **) + SDL_malloc((SDL_nummodes[i]+1)*sizeof(SDL_Rect *)); + if ( SDL_modelist[i] == NULL ) { + SDL_OutOfMemory(); + return(-1); + } + for ( j=0; j<SDL_nummodes[i]; ++j ) { + SDL_modelist[i][j]=(SDL_Rect *)SDL_malloc(sizeof(SDL_Rect)); + if ( SDL_modelist[i][j] == NULL ) { + SDL_OutOfMemory(); + return(-1); + } + SDL_memset(SDL_modelist[i][j], 0, sizeof(SDL_Rect)); + } + SDL_modelist[i][j] = NULL; + } + + /* Now fill the mode list */ + switch (XBIOS_cvdo >>16) { + case VDO_ST: + case VDO_STE: + XBIOS_ListSTModes(this, 1); + break; + case VDO_TT: + XBIOS_ListTTModes(this, 1); + break; + case VDO_F30: + /* ScreenBlaster 3 ? */ + if (Getcookie(C_SCPN, &cookie_scpn) == C_FOUND) { + SDL_XBIOS_ListSB3Modes(this, 1, (scpn_cookie_t *)cookie_scpn); + } else + /* Centscreen ? */ + if (Getcookie(C_CNTS, &cookie_cnts) == C_FOUND) { + XBIOS_oldvmode = SDL_XBIOS_ListCentscreenModes(this, 1); + XBIOS_centscreen = SDL_TRUE; + } else + /* Standard, with or without Blowup */ + { + switch (VgetMonitor()) + { + case MONITOR_RGB: + case MONITOR_TV: + XBIOS_ListFalconRgbModes(this, 1); + break; + case MONITOR_VGA: + XBIOS_ListFalconVgaModes(this, 1); + break; + } + + if (Getcookie(C_BLOW, &cookie_blow) == C_FOUND) { + SDL_XBIOS_ListBlowupModes(this, 1, (blow_cookie_t *)cookie_blow); + } + } + break; + case VDO_MILAN: + SDL_XBIOS_ListMilanModes(this, 1); + break; + } + + XBIOS_screens[0]=NULL; + XBIOS_screens[1]=NULL; + XBIOS_shadowscreen=NULL; + + /* Update hardware info */ + this->info.hw_available = 1; + this->info.video_mem = (Uint32) Atari_SysMalloc(-1L, MX_STRAM); + + /* Init chunky to planar routine */ + SDL_Atari_C2pConvert = SDL_Atari_C2pConvert8; + +#if SDL_VIDEO_OPENGL + SDL_AtariGL_InitPointers(this); +#endif + + /* Disable screensavers */ + if (SDL_XBIOS_TveillePresent(this)) { + SDL_XBIOS_TveilleDisable(this); + } + + /* We're done! */ + return(0); +} + +static SDL_Rect **XBIOS_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags) +{ + return(SDL_modelist[((format->BitsPerPixel+7)/8)-1]); +} + +static void XBIOS_FreeBuffers(_THIS) +{ + int i; + + for (i=0;i<2;i++) { + if (XBIOS_screensmem[i]!=NULL) { + if ((XBIOS_cvdo>>16) == VDO_MILAN) { + if (i==1) { + VsetScreen(-1, -1, MI_MAGIC, CMD_FREEPAGE); + } + } else { + Mfree(XBIOS_screensmem[i]); + } + XBIOS_screensmem[i]=NULL; + } + } + + if (XBIOS_shadowscreen!=NULL) { + Mfree(XBIOS_shadowscreen); + XBIOS_shadowscreen=NULL; + } +} + +static SDL_Surface *XBIOS_SetVideoMode(_THIS, SDL_Surface *current, + int width, int height, int bpp, Uint32 flags) +{ + int mode, new_depth; + int i, num_buffers; + xbiosmode_t *new_video_mode; + Uint32 new_screen_size; + Uint32 modeflags; + + /* Free current buffers */ + XBIOS_FreeBuffers(this); + + /* Try to set the requested linear video mode */ + bpp = (bpp+7)/8-1; + for ( mode=0; SDL_modelist[bpp][mode]; ++mode ) { + if ( (SDL_modelist[bpp][mode]->w == width) && + (SDL_modelist[bpp][mode]->h == height) ) { + break; + } + } + if ( SDL_modelist[bpp][mode] == NULL ) { + SDL_SetError("Couldn't find requested mode in list"); + return(NULL); + } + new_video_mode = SDL_xbiosmode[bpp][mode]; + + modeflags = SDL_FULLSCREEN | SDL_PREALLOC; + + /* Allocate needed buffers: simple/double buffer and shadow surface */ + new_depth = new_video_mode->depth; + if (new_depth == 4) { + SDL_Atari_C2pConvert = SDL_Atari_C2pConvert4; + new_depth=8; + modeflags |= SDL_SWSURFACE|SDL_HWPALETTE; + } else if (new_depth == 8) { + SDL_Atari_C2pConvert = SDL_Atari_C2pConvert8; + modeflags |= SDL_SWSURFACE|SDL_HWPALETTE; + } else { + modeflags |= SDL_HWSURFACE; + } + + new_screen_size = width * height * ((new_depth)>>3); + new_screen_size += 256; /* To align on a 256 byte adress */ + + if (new_video_mode->flags & XBIOSMODE_C2P) { + XBIOS_shadowscreen = Atari_SysMalloc(new_screen_size, MX_PREFTTRAM); + + if (XBIOS_shadowscreen == NULL) { + SDL_SetError("Can not allocate %d KB for shadow buffer", new_screen_size>>10); + return (NULL); + } + SDL_memset(XBIOS_shadowscreen, 0, new_screen_size); + } + + /* Output buffer needs to be twice in size for the software double-line mode */ + if (new_video_mode->flags & XBIOSMODE_DOUBLELINE) { + new_screen_size <<= 1; + } + + /* Double buffer ? */ + num_buffers = 1; + +#if SDL_VIDEO_OPENGL + if (flags & SDL_OPENGL) { + if (this->gl_config.double_buffer) { + flags |= SDL_DOUBLEBUF; + } + } +#endif + if ((flags & SDL_DOUBLEBUF) && ((XBIOS_cvdo>>16) != VDO_MILAN)) { + num_buffers = 2; + modeflags |= SDL_DOUBLEBUF; + } + + /* Allocate buffers */ + for (i=0; i<num_buffers; i++) { + if ((XBIOS_cvdo>>16) == VDO_MILAN) { + if (i==0) { + XBIOS_screensmem[i] = XBIOS_oldvbase; + } else { + VsetScreen(-1, &XBIOS_screensmem[i], MI_MAGIC, CMD_ALLOCPAGE); + } + } else { + XBIOS_screensmem[i] = Atari_SysMalloc(new_screen_size, MX_STRAM); + } + + if (XBIOS_screensmem[i]==NULL) { + XBIOS_FreeBuffers(this); + SDL_SetError("Can not allocate %d KB for buffer %d", new_screen_size>>10, i); + return (NULL); + } + SDL_memset(XBIOS_screensmem[i], 0, new_screen_size); + + XBIOS_screens[i]=(void *) (( (long) XBIOS_screensmem[i]+256) & 0xFFFFFF00UL); + } + + /* Allocate the new pixel format for the screen */ + if ( ! SDL_ReallocFormat(current, new_depth, 0, 0, 0, 0) ) { + XBIOS_FreeBuffers(this); + SDL_SetError("Couldn't allocate new pixel format for requested mode"); + return(NULL); + } + + XBIOS_current = new_video_mode; + current->w = width; + current->h = height; + current->pitch = (width * new_depth)>>3; + + /* this is for C2P conversion */ + XBIOS_pitch = (new_video_mode->width * new_video_mode->depth)>>3; + + if (new_video_mode->flags & XBIOSMODE_C2P) + current->pixels = XBIOS_shadowscreen; + else + current->pixels = XBIOS_screens[0]; + + XBIOS_fbnum = 0; + +#if SDL_VIDEO_OPENGL + if (flags & SDL_OPENGL) { + if (!SDL_AtariGL_Init(this, current)) { + XBIOS_FreeBuffers(this); + SDL_SetError("Can not create OpenGL context"); + return NULL; + } + + modeflags |= SDL_OPENGL; + } +#endif + + current->flags = modeflags; + +#ifndef DEBUG_VIDEO_XBIOS + /* Now set the video mode */ + if ((XBIOS_cvdo>>16) == VDO_MILAN) { + VsetScreen(-1, XBIOS_screens[0], MI_MAGIC, CMD_SETADR); + } else { + Setscreen(-1,XBIOS_screens[0],-1); + } + + switch(XBIOS_cvdo >> 16) { + case VDO_ST: + Setscreen(-1,-1,new_video_mode->number); + + /* Reset palette */ + for (i=0;i<16;i++) { + TT_palette[i]= ((i>>1)<<8) | (((i*8)/17)<<4) | (i>>1); + } + Setpalette(TT_palette); + break; + case VDO_STE: + Setscreen(-1,-1,new_video_mode->number); + + /* Reset palette */ + for (i=0;i<16;i++) + { + int c; + + c=((i&1)<<3)|((i>>1)&7); + TT_palette[i]=(c<<8)|(c<<4)|c; + } + Setpalette(TT_palette); + break; + case VDO_TT: + EsetShift(new_video_mode->number); + break; + case VDO_F30: + if (XBIOS_centscreen) { + SDL_XBIOS_CentscreenSetmode(this, width, height, new_depth); + } else { + VsetMode(new_video_mode->number); + } + + /* Set hardware palette to black in True Colour */ + if (new_depth > 8) { + SDL_memset(F30_palette, 0, sizeof(F30_palette)); + VsetRGB(0,256,F30_palette); + } + break; + case VDO_MILAN: + VsetScreen(-1, new_video_mode->number, MI_MAGIC, CMD_SETMODE); + + /* Set hardware palette to black in True Colour */ + if (new_depth > 8) { + SDL_memset(F30_palette, 0, sizeof(F30_palette)); + VsetRGB(0,256,F30_palette); + } + break; + } + + Vsync(); +#endif + + this->UpdateRects = XBIOS_UpdateRects; + + return (current); +} + +/* We don't actually allow hardware surfaces other than the main one */ +static int XBIOS_AllocHWSurface(_THIS, SDL_Surface *surface) +{ + return(-1); +} + +static void XBIOS_FreeHWSurface(_THIS, SDL_Surface *surface) +{ + return; +} + +static int XBIOS_LockHWSurface(_THIS, SDL_Surface *surface) +{ + return(0); +} + +static void XBIOS_UnlockHWSurface(_THIS, SDL_Surface *surface) +{ + return; +} + +static void XBIOS_UpdateRects(_THIS, int numrects, SDL_Rect *rects) +{ + SDL_Surface *surface; + + surface = this->screen; + + if (XBIOS_current->flags & XBIOSMODE_C2P) { + int i; + int doubleline = (XBIOS_current->flags & XBIOSMODE_DOUBLELINE ? 1 : 0); + + for (i=0;i<numrects;i++) { + void *source,*destination; + int x1,x2; + + x1 = rects[i].x & ~15; + x2 = rects[i].x+rects[i].w; + if (x2 & 15) { + x2 = (x2 | 15) +1; + } + + source = surface->pixels; + source += surface->pitch * rects[i].y; + source += x1; + + destination = XBIOS_screens[XBIOS_fbnum]; + destination += XBIOS_pitch * rects[i].y; + destination += x1; + + /* Convert chunky to planar screen */ + SDL_Atari_C2pConvert( + source, + destination, + x2-x1, + rects[i].h, + doubleline, + surface->pitch, + XBIOS_pitch + ); + } + } + +#ifndef DEBUG_VIDEO_XBIOS + if ((XBIOS_cvdo>>16) == VDO_MILAN) { + VsetScreen(-1, XBIOS_screens[XBIOS_fbnum], MI_MAGIC, CMD_SETADR); + } else { + Setscreen(-1,XBIOS_screens[XBIOS_fbnum],-1); + } + + Vsync(); +#endif + + if ((surface->flags & SDL_DOUBLEBUF) == SDL_DOUBLEBUF) { + XBIOS_fbnum ^= 1; + if ((XBIOS_current->flags & XBIOSMODE_C2P) == 0) { + surface->pixels=XBIOS_screens[XBIOS_fbnum]; + } + } +} + +static int XBIOS_FlipHWSurface(_THIS, SDL_Surface *surface) +{ + if (XBIOS_current->flags & XBIOSMODE_C2P) { + void *destscr; + int destx; + int doubleline = (XBIOS_current->flags & XBIOSMODE_DOUBLELINE ? 1 : 0); + + /* Center on destination screen */ + destscr = XBIOS_screens[XBIOS_fbnum]; + destscr += XBIOS_pitch * ((XBIOS_current->height - surface->h) >> 1); + destx = (XBIOS_current->width - surface->w) >> 1; + destx &= ~15; + destscr += destx; + + /* Convert chunky to planar screen */ + SDL_Atari_C2pConvert( + surface->pixels, + destscr, + surface->w, + surface->h, + doubleline, + surface->pitch, + XBIOS_pitch + ); + } + +#ifndef DEBUG_VIDEO_XBIOS + if ((XBIOS_cvdo>>16) == VDO_MILAN) { + VsetScreen(-1, XBIOS_screens[XBIOS_fbnum], MI_MAGIC, CMD_SETADR); + } else { + Setscreen(-1,XBIOS_screens[XBIOS_fbnum],-1); + } + + Vsync(); +#endif + + if ((surface->flags & SDL_DOUBLEBUF) == SDL_DOUBLEBUF) { + XBIOS_fbnum ^= 1; + if ((XBIOS_current->flags & XBIOSMODE_C2P) == 0) { + surface->pixels=XBIOS_screens[XBIOS_fbnum]; + } + } + + return(0); +} + +static int XBIOS_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors) +{ +#ifndef DEBUG_VIDEO_XBIOS + int i; + int r,v,b; + + switch( XBIOS_cvdo >> 16) { + case VDO_ST: + case VDO_STE: + for (i=0;i<ncolors;i++) + { + r = colors[i].r; + v = colors[i].g; + b = colors[i].b; + + TT_palette[firstcolor+i]=((r*30)+(v*59)+(b*11))/100; + } + SDL_Atari_C2pConvert4_pal(TT_palette); /* convert the lighting */ + break; + case VDO_TT: + for(i = 0; i < ncolors; i++) + { + r = colors[i].r; + v = colors[i].g; + b = colors[i].b; + + TT_palette[i]=((r>>4)<<8)|((v>>4)<<4)|(b>>4); + } + EsetPalette(firstcolor,ncolors,TT_palette); + break; + case VDO_F30: + case VDO_MILAN: + for(i = 0; i < ncolors; i++) + { + r = colors[i].r; + v = colors[i].g; + b = colors[i].b; + + F30_palette[i]=(r<<16)|(v<<8)|b; + } + VsetRGB(firstcolor,ncolors,F30_palette); + break; + } +#endif + + return(1); +} + +/* Note: If we are terminated, this could be called in the middle of + another SDL video routine -- notably UpdateRects. +*/ +static void XBIOS_VideoQuit(_THIS) +{ + int i,j; + + Atari_ShutdownEvents(); + + /* Restore video mode and palette */ +#ifndef DEBUG_VIDEO_XBIOS + switch(XBIOS_cvdo >> 16) { + case VDO_ST: + case VDO_STE: + Setscreen(-1,XBIOS_oldvbase,XBIOS_oldvmode); + if (XBIOS_oldnumcol) { + Setpalette(XBIOS_oldpalette); + } + break; + case VDO_TT: + Setscreen(-1,XBIOS_oldvbase,-1); + EsetShift(XBIOS_oldvmode); + if (XBIOS_oldnumcol) { + EsetPalette(0, XBIOS_oldnumcol, XBIOS_oldpalette); + } + break; + case VDO_F30: + Setscreen(-1, XBIOS_oldvbase, -1); + if (XBIOS_centscreen) { + SDL_XBIOS_CentscreenRestore(this, XBIOS_oldvmode); + } else { + VsetMode(XBIOS_oldvmode); + } + if (XBIOS_oldnumcol) { + VsetRGB(0, XBIOS_oldnumcol, XBIOS_oldpalette); + } + break; + case VDO_MILAN: + VsetScreen(-1, &XBIOS_oldvbase, MI_MAGIC, CMD_SETADR); + VsetScreen(-1, &XBIOS_oldvmode, MI_MAGIC, CMD_SETMODE); + if (XBIOS_oldnumcol) { + VsetRGB(0, XBIOS_oldnumcol, XBIOS_oldpalette); + } + break; + } + Vsync(); +#endif + +#if SDL_VIDEO_OPENGL + if (gl_active) { + SDL_AtariGL_Quit(this, SDL_TRUE); + } +#endif + + if (XBIOS_oldpalette) { + SDL_free(XBIOS_oldpalette); + XBIOS_oldpalette=NULL; + } + XBIOS_FreeBuffers(this); + + /* Free mode list */ + for ( i=0; i<NUM_MODELISTS; ++i ) { + if ( SDL_modelist[i] != NULL ) { + for ( j=0; SDL_modelist[i][j]; ++j ) + SDL_free(SDL_modelist[i][j]); + SDL_free(SDL_modelist[i]); + SDL_modelist[i] = NULL; + } + if ( SDL_xbiosmode[i] != NULL ) { + for ( j=0; SDL_xbiosmode[i][j]; ++j ) + SDL_free(SDL_xbiosmode[i][j]); + SDL_free(SDL_xbiosmode[i]); + SDL_xbiosmode[i] = NULL; + } + } + + this->screen->pixels = NULL; + + /* Restore screensavers */ + if (SDL_XBIOS_TveillePresent(this)) { + SDL_XBIOS_TveilleEnable(this); + } +} + +#if SDL_VIDEO_OPENGL + +static void XBIOS_GL_SwapBuffers(_THIS) +{ + SDL_AtariGL_SwapBuffers(this); + XBIOS_FlipHWSurface(this, this->screen); + SDL_AtariGL_MakeCurrent(this); +} + +#endif diff --git a/3rdparty/SDL/src/video/xbios/SDL_xbios.h b/3rdparty/SDL/src/video/xbios/SDL_xbios.h new file mode 100644 index 0000000..3ad6827 --- /dev/null +++ b/3rdparty/SDL/src/video/xbios/SDL_xbios.h @@ -0,0 +1,111 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#ifndef _SDL_xbios_h +#define _SDL_xbios_h + +#include "SDL_stdinc.h" +#include "../SDL_sysvideo.h" + +/* Hidden "this" pointer for the video functions */ +#define _THIS SDL_VideoDevice *this + +#define XBIOSMODE_DOUBLELINE (1<<0) +#define XBIOSMODE_C2P (1<<1) + +typedef struct +{ + Uint16 number; /* Video mode number */ + Uint16 width; /* Size */ + Uint16 height; + Uint16 depth; /* bits per plane */ + Uint16 flags; +} xbiosmode_t; + +/* Private display data */ +#define NUM_MODELISTS 4 /* 8, 16, 24, and 32 bits-per-pixel */ + +struct SDL_PrivateVideoData { + long cookie_vdo; + long old_video_mode; /* Old video mode before entering SDL */ + void *old_video_base; /* Old pointer to screen buffer */ + void *old_palette; /* Old palette */ + Uint32 old_num_colors; /* Nb of colors in saved palette */ + + void *screens[2]; /* Pointers to aligned screen buffer */ + void *screensmem[2]; /* Pointers to screen buffer */ + void *shadowscreen; /* Shadow screen for c2p conversion */ + int frame_number; /* Number of frame for double buffer */ + int pitch; /* Destination line width for C2P */ + + SDL_bool centscreen; /* Centscreen extension present ? */ + + xbiosmode_t *current; /* Current set mode */ + int SDL_nummodes[NUM_MODELISTS]; + SDL_Rect **SDL_modelist[NUM_MODELISTS]; + xbiosmode_t **SDL_xbiosmode[NUM_MODELISTS]; +}; + +/* _VDO cookie values */ +enum { + VDO_ST=0, + VDO_STE, + VDO_TT, + VDO_F30, + VDO_MILAN +}; + +/* Monitor types */ +enum { + MONITOR_MONO=0, + MONITOR_TV, + MONITOR_VGA, + MONITOR_RGB +}; + +/* EgetShift masks */ +#define ES_MODE 0x0700 + +/* Hidden structure -> variables names */ +#define SDL_nummodes (this->hidden->SDL_nummodes) +#define SDL_modelist (this->hidden->SDL_modelist) +#define SDL_xbiosmode (this->hidden->SDL_xbiosmode) +#define XBIOS_mutex (this->hidden->mutex) +#define XBIOS_cvdo (this->hidden->cookie_vdo) +#define XBIOS_oldpalette (this->hidden->old_palette) +#define XBIOS_oldnumcol (this->hidden->old_num_colors) +#define XBIOS_oldvbase (this->hidden->old_video_base) +#define XBIOS_oldvmode (this->hidden->old_video_mode) +#define XBIOS_screens (this->hidden->screens) +#define XBIOS_screensmem (this->hidden->screensmem) +#define XBIOS_shadowscreen (this->hidden->shadowscreen) +#define XBIOS_fbnum (this->hidden->frame_number) +#define XBIOS_pitch (this->hidden->pitch) +#define XBIOS_centscreen (this->hidden->centscreen) +#define XBIOS_current (this->hidden->current) + +/*--- Functions prototypes ---*/ + +void SDL_XBIOS_AddMode(_THIS, int actually_add, const xbiosmode_t *modeinfo); + +#endif /* _SDL_xbios_h */ diff --git a/3rdparty/SDL/src/video/xbios/SDL_xbios_blowup.c b/3rdparty/SDL/src/video/xbios/SDL_xbios_blowup.c new file mode 100644 index 0000000..2950b84 --- /dev/null +++ b/3rdparty/SDL/src/video/xbios/SDL_xbios_blowup.c @@ -0,0 +1,77 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* + Blowup extension definitions + + Patrice Mandin +*/ + +#include <mint/falcon.h> + +#include "SDL_xbios.h" +#include "SDL_xbios_blowup.h" + +void SDL_XBIOS_ListBlowupModes(_THIS, int actually_add, blow_cookie_t *cookie_blow) +{ + int i, j, num_mode, bank; + blow_mode_t *blow_mode; + xbiosmode_t modeinfo; + + if (actually_add) { + /* Set bit 15 for old modes */ + for (i=0;i<NUM_MODELISTS;i++) { + if ( SDL_xbiosmode[i] != NULL ) { + for ( j=0; SDL_xbiosmode[i][j]; ++j ) { + SDL_xbiosmode[i][j]->number |= 1<<15; + } + } + } + } + + /* Add Blowup modes for 8 and 16 bpp */ + for (num_mode=3; num_mode<5; num_mode++) { + bank = cookie_blow->num_mode[num_mode]; + blow_mode = &(cookie_blow->blowup_modes[num_mode+(bank*5)]); + + /* Check extended mode enabled */ + if (blow_mode->enabled == 0) { + /* Check monitor needed for this mode */ + if ((blow_mode->monitor == cookie_blow->montype) + || ((blow_mode->monitor == MONITOR_TV) + && (cookie_blow->montype == MONITOR_RGB)) + || ((blow_mode->monitor == MONITOR_RGB) + && (cookie_blow->montype == MONITOR_TV))) + { + /* we can use this extended mode */ + modeinfo.number = (num_mode == 3 ? BPS8 : BPS16); + modeinfo.width = blow_mode->width + 1; + modeinfo.height = blow_mode->height + 1; + modeinfo.depth = (num_mode == 3 ? 8 : 16); + modeinfo.flags = (modeinfo.depth == 8 ? XBIOSMODE_C2P : 0); + + SDL_XBIOS_AddMode(this, actually_add, &modeinfo); + } + } + } +} diff --git a/3rdparty/SDL/src/video/xbios/SDL_xbios_blowup.h b/3rdparty/SDL/src/video/xbios/SDL_xbios_blowup.h new file mode 100644 index 0000000..09a3651 --- /dev/null +++ b/3rdparty/SDL/src/video/xbios/SDL_xbios_blowup.h @@ -0,0 +1,86 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* + Blowup extension definitions + + Patrice Mandin +*/ + +#ifndef _SDL_xbios_blowup_h +#define _SDL_xbios_blowup_h + +#include "SDL_xbios.h" + +/*--- Types ---*/ + +typedef struct { + /* 64 bytes */ + unsigned short enabled; /* Extended mode enabled ? 0=yes, <>0=no */ + unsigned short dummy10[6]; + unsigned short registers_0E; /* value for register 0xffff820e */ + unsigned short registers_10; /* value for register 0xffff8210 */ + unsigned short dummy11[23]; + + /* 64 bytes */ + unsigned short width; /* width-1 */ + unsigned short height; /* height-1 */ + unsigned short dummy20; + unsigned long screensize; /* screensize in bytes */ + unsigned short dummy21[8]; + unsigned short virtual; /* Virtual screen ? */ + unsigned short virwidth; /* Virtual screen width */ + unsigned short virheight; /* Virtual screen height */ + + unsigned short dummy22; + unsigned short monitor; /* Monitor defined for this mode */ + unsigned short extension; /* Extended mode defined ? 0=yes, 1=no */ + unsigned short dummy23[13]; + + /* 64 bytes */ + unsigned short dummy30; + unsigned short registers_82[6]; /* values for registers 0xffff8282-8c */ + unsigned short dummy31[9]; + + unsigned short dummy32; + unsigned short registers_A2[6]; /* values for registers 0xffff82a2-ac */ + unsigned short dummy33[9]; + + /* 64 bytes */ + unsigned short registers_C0; /* value for register 0xffff82c0 */ + unsigned short registers_C2; /* value for register 0xffff82c2 */ + unsigned short dummy40[30]; +} blow_mode_t; + +typedef struct { + blow_mode_t blowup_modes[10]; + unsigned char num_mode[6]; + unsigned long dummy; + unsigned short montype; +} blow_cookie_t; + +/*--- Functions prototypes ---*/ + +void SDL_XBIOS_ListBlowupModes(_THIS, int actually_add, blow_cookie_t *cookie_blow); + +#endif /* _SDL_xbios_blowup_h */ diff --git a/3rdparty/SDL/src/video/xbios/SDL_xbios_centscreen.c b/3rdparty/SDL/src/video/xbios/SDL_xbios_centscreen.c new file mode 100644 index 0000000..6daade2 --- /dev/null +++ b/3rdparty/SDL/src/video/xbios/SDL_xbios_centscreen.c @@ -0,0 +1,104 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* + Centscreen extension definitions + + Patrice Mandin +*/ + +#include <mint/falcon.h> + +#include "SDL_xbios.h" +#include "SDL_xbios_centscreen.h" + +int SDL_XBIOS_ListCentscreenModes(_THIS, int actually_add) +{ + centscreen_mode_t curmode, listedmode; + unsigned long result; + int cur_handle; /* Current Centscreen mode handle */ + + /* Add Centscreen modes */ + Vread(&curmode); + cur_handle = curmode.handle; + curmode.mode = curmode.physx = curmode.physy = curmode.plan = + curmode.logx = curmode.logy = -1; + + result = Vfirst(&curmode, &listedmode); + if (result==0) { + while (result==0) { + /* Don't add modes with virtual screen */ + if ((listedmode.mode & CSCREEN_VIRTUAL)==0) { + /* Don't add modes with bpp<8 */ + if (listedmode.plan>=8) { + xbiosmode_t modeinfo; + + modeinfo.number = listedmode.mode; + modeinfo.width = listedmode.physx; + modeinfo.height = listedmode.physy; + modeinfo.depth = listedmode.plan; + modeinfo.flags = (modeinfo.depth == 8 ? XBIOSMODE_C2P : 0); + + SDL_XBIOS_AddMode(this, actually_add, &modeinfo); + } + } + SDL_memcpy(&curmode, &listedmode, sizeof(centscreen_mode_t)); + curmode.mode = curmode.physx = curmode.physy = curmode.plan = + curmode.logx = curmode.logy = -1; + result = Vnext(&curmode, &listedmode); + } + } else { + fprintf(stderr, "No suitable Centscreen modes\n"); + } + + return cur_handle; +} + +void SDL_XBIOS_CentscreenSetmode(_THIS, int width, int height, int planes) +{ + centscreen_mode_t newmode, curmode; + + newmode.handle = newmode.mode = newmode.logx = newmode.logy = -1; + newmode.physx = width; + newmode.physy = height; + newmode.plan = planes; + Vwrite(0, &newmode, &curmode); + +#ifdef SDL_VIDEO_DISABLE_SCREENSAVER + /* Disable screensaver */ + Vread(&newmode); + newmode.mode &= ~(CSCREEN_SAVER|CSCREEN_ENERGYSTAR); + Vwrite(0, &newmode, &curmode); +#endif /* SDL_VIDEO_DISABLE_SCREENSAVER */ +} + +void SDL_XBIOS_CentscreenRestore(_THIS, int prev_handle) +{ + centscreen_mode_t newmode, curmode; + + /* Restore old video mode */ + newmode.handle = prev_handle; + newmode.mode = newmode.physx = newmode.physy = newmode.plan = + newmode.logx = newmode.logy = -1; + Vwrite(0, &newmode, &curmode); +} diff --git a/3rdparty/SDL/src/video/xbios/SDL_xbios_centscreen.h b/3rdparty/SDL/src/video/xbios/SDL_xbios_centscreen.h new file mode 100644 index 0000000..dfe88d9 --- /dev/null +++ b/3rdparty/SDL/src/video/xbios/SDL_xbios_centscreen.h @@ -0,0 +1,114 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* + Centscreen extension definitions + + Patrice Mandin +*/ + +#ifndef _SDL_xbios_centscreen_h +#define _SDL_xbios_centscreen_h + +#include <mint/falcon.h> /* for trap_14_xxx macros */ + +#include "SDL_xbios.h" + +/*--- Defines ---*/ + +#define CSCREEN_ENERGYSTAR (1<<9) +#define CSCREEN_SAVER (1<<10) +#define CSCREEN_VIRTUAL (1<<11) +#define CSCREEN_EXTCLOCK_CT2 (1<<12) +#define CSCREEN_EXTCLOCK (1<<13) +#define CSCREEN_STANDARD (1<<14) +#define CSCREEN_DEFAULT (1<<15) + +/*--- Structures ---*/ + +typedef struct { + unsigned short handle; /* videomode handle */ + unsigned short mode; /* Falcon videomode code */ + unsigned short physx; /* visible width */ + unsigned short physy; /* visible height */ + unsigned short plan; /* bitplanes */ + unsigned short logx; /* virtual width */ + unsigned short logy; /* virtual height */ + unsigned short eco; /* screen saver delay */ + unsigned short eco2; /* energy star screen saver delay */ + unsigned short wsize; /* screen width (mm) */ + unsigned short hsize; /* screen height (mm) */ + unsigned short dummy[21]; + unsigned char name[32]; /* videomode name */ +} centscreen_mode_t; + +/*--- Functions prototypes ---*/ + +#define Vread(current_mode) \ + (void)trap_14_wl((short)0x41,(long)(current_mode)) +#define Vwrite(init_vdi, inparam, outparam) \ + (long)trap_14_wwll((short)0x42,(short)(init_vdi),(long)(inparam),(long)(outparam)) +#define Vattrib(inparam, outparam) \ + (void)trap_14_wll((short)0x43,(long)(inparam),(long)(outparam)) +#define Vcreate(inparam, outparam) \ + (void)trap_14_wll((short)0x44,(long)(inparam),(long)(outparam)) +#define Vdelete(handle) \ + (long)trap_14_ww((short)0x45,(short)(handle)) +#define Vfirst(mask,mode) \ + (long)trap_14_wll((short)0x46,(long)(mask),(long)(mode)) +#define Vnext(mask,mode) \ + (long)trap_14_wll((short)0x47,(long)(mask),(long)(mode)) +#define Vvalid(handle) \ + (long)trap_14_ww((short)0x48,(short)(handle)) +#define Vload() \ + (long)trap_14_w((short)0x49) +#define Vsave() \ + (long)trap_14_w((short)0x4a) +#define Vopen() \ + (long)trap_14_w((short)0x4b) +#define Vclose() \ + (long)trap_14_w((short)0x4c) +#define Vscroll(scrollmode) \ + (long)trap_14_ww((short)0x4d,(short)(scrollmode)) +#define Voffset() \ + (long)trap_14_w((short)0x4e) +#define Vseek() \ + (long)trap_14_w((short)0x4f) +#define Vlock(cmd) \ + (long)trap_14_ww((short)0x50,(short)(cmd)) +#define SetMon(montype) \ + (long)trap_14_ww((short)0x51,(short)(montype)) +#define MultiMon(cmd) \ + (long)trap_14_ww((short)0x52,(short)(cmd)) +#define VSizeComp() \ + (long)trap_14_w((short)0x53) +#define Vsize(mode) \ + (long)trap_14_wl((short)0x54,(long)(mode)) + +/*--- Functions prototypes ---*/ + +int SDL_XBIOS_ListCentscreenModes(_THIS, int actually_add); +void SDL_XBIOS_CentscreenSetmode(_THIS, int width, int height, int planes); +void SDL_XBIOS_CentscreenRestore(_THIS, int prev_handle); + +#endif /* _SDL_xbios_centscreen_h */ diff --git a/3rdparty/SDL/src/video/xbios/SDL_xbios_milan.c b/3rdparty/SDL/src/video/xbios/SDL_xbios_milan.c new file mode 100644 index 0000000..a99ee18 --- /dev/null +++ b/3rdparty/SDL/src/video/xbios/SDL_xbios_milan.c @@ -0,0 +1,106 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* + Milan Xbios video functions + + Patrice Mandin +*/ + +#include <mint/cookie.h> +#include <mint/falcon.h> + +#include "SDL_xbios.h" +#include "SDL_xbios_milan.h" + +#define NUM_PREDEFINED_MODES 7 + +typedef struct { + Uint16 width, height; +} predefined_mode_t; + +static const predefined_mode_t mode_list[NUM_PREDEFINED_MODES]={ + {640,400}, + {640,480}, + {800,608}, + {1024,768}, + {1152,864}, + {1280,1024}, + {1600,1200} +}; + +static const Uint8 mode_bpp[4]={ + 8, 15, 16, 32 +}; + +/*--- Variables ---*/ + +static int enum_actually_add; +static SDL_VideoDevice *enum_this; + +/*--- Functions ---*/ + +static unsigned long /*cdecl*/ enumfunc(SCREENINFO *inf, unsigned long flag) +{ + xbiosmode_t modeinfo; + + modeinfo.number = inf->devID; + modeinfo.width = inf->scrWidth; + modeinfo.height = inf->scrHeight; + modeinfo.depth = inf->scrPlanes; + modeinfo.flags = 0; + + SDL_XBIOS_AddMode(enum_this, enum_actually_add, &modeinfo); + + return ENUMMODE_CONT; +} + +void SDL_XBIOS_ListMilanModes(_THIS, int actually_add) +{ + int i; + + /* Read validated predefined modes */ + for (i=0; i<NUM_PREDEFINED_MODES; i++) { + int j; + Uint16 deviceid = 0x1000 + (i<<4); + + for (j=1; j<4; j++) { + if (Validmode(deviceid + j)) { + xbiosmode_t modeinfo; + + modeinfo.number = deviceid + j; + modeinfo.width = mode_list[i].width; + modeinfo.height = mode_list[i].height; + modeinfo.depth = mode_bpp[j-1]; + modeinfo.flags = 0; + + SDL_XBIOS_AddMode(this, actually_add, &modeinfo); + } + } + } + + /* Read custom created modes */ + enum_this = this; + enum_actually_add = actually_add; + VsetScreen(-1, &enumfunc, MI_MAGIC, CMD_ENUMMODES); +} diff --git a/3rdparty/SDL/src/video/xbios/SDL_xbios_milan.h b/3rdparty/SDL/src/video/xbios/SDL_xbios_milan.h new file mode 100644 index 0000000..bcf5c8a --- /dev/null +++ b/3rdparty/SDL/src/video/xbios/SDL_xbios_milan.h @@ -0,0 +1,129 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* + Milan Xbios video functions + + Patrice Mandin +*/ + +#ifndef _SDL_xbios_milan_h +#define _SDL_xbios_milan_h + +#include "SDL_xbios.h" + +/*--- Defines ---*/ + +/* Vsetscreen() parameters */ +#define MI_MAGIC 0x4D49 + +enum { + CMD_GETMODE=0, + CMD_SETMODE, + CMD_GETINFO, + CMD_ALLOCPAGE, + CMD_FREEPAGE, + CMD_FLIPPAGE, + CMD_ALLOCMEM, + CMD_FREEMEM, + CMD_SETADR, + CMD_ENUMMODES +}; + +enum { + ENUMMODE_EXIT=0, + ENUMMODE_CONT +}; + +enum { + BLK_ERR=0, + BLK_OK, + BLK_CLEARED +}; + +/* scrFlags */ +#define SCRINFO_OK 1 + +/* scrClut */ +#define NO_CLUT 0 +#define HARD_CLUT 1 +#define SOFT_CLUT 2 + +/* scrFormat */ +#define INTERLEAVE_PLANES 0 +#define STANDARD_PLANES 1 +#define PACKEDPIX_PLANES 2 + +/* bitFlags */ +#define STANDARD_BITS 1 +#define FALCON_BITS 2 +#define INTEL_BITS 8 + +/*--- Structures ---*/ + +typedef struct _scrblk { + unsigned long size; /* size of strukture */ + unsigned long blk_status; /* status bits of blk */ + unsigned long blk_start; /* Start Adress */ + unsigned long blk_len; /* length of memblk */ + unsigned long blk_x; /* x pos in total screen*/ + unsigned long blk_y; /* y pos in total screen */ + unsigned long blk_w; /* width */ + unsigned long blk_h; /* height */ + unsigned long blk_wrap; /* width in bytes */ +} SCRMEMBLK; + +typedef struct screeninfo { + unsigned long size; /* Size of structure */ + unsigned long devID; /* device id number */ + unsigned char name[64]; /* Friendly name of Screen */ + unsigned long scrFlags; /* some Flags */ + unsigned long frameadr; /* Adress of framebuffer */ + unsigned long scrHeight; /* visible X res */ + unsigned long scrWidth; /* visible Y res */ + unsigned long virtHeight; /* virtual X res */ + unsigned long virtWidth; /* virtual Y res */ + unsigned long scrPlanes; /* color Planes */ + unsigned long scrColors; /* # of colors */ + unsigned long lineWrap; /* # of Bytes to next line */ + unsigned long planeWarp; /* # of Bytes to next plane */ + unsigned long scrFormat; /* screen Format */ + unsigned long scrClut; /* type of clut */ + unsigned long redBits; /* Mask of Red Bits */ + unsigned long greenBits; /* Mask of Green Bits */ + unsigned long blueBits; /* Mask of Blue Bits */ + unsigned long alphaBits; /* Mask of Alpha Bits */ + unsigned long genlockBits;/* Mask of Genlock Bits */ + unsigned long unusedBits; /* Mask of unused Bits */ + unsigned long bitFlags; /* Bits organisation flags */ + unsigned long maxmem; /* max. memory in this mode */ + unsigned long pagemem; /* needed memory for one page */ + unsigned long max_x; /* max. possible width */ + unsigned long max_y; /* max. possible heigth */ +} SCREENINFO; + +/*--- Functions prototypes ---*/ + +void SDL_XBIOS_ListMilanModes(_THIS, int actually_add); + +#endif /* _SDL_xbios_milan_h */ diff --git a/3rdparty/SDL/src/video/xbios/SDL_xbios_sb3.c b/3rdparty/SDL/src/video/xbios/SDL_xbios_sb3.c new file mode 100644 index 0000000..8b0ed2c --- /dev/null +++ b/3rdparty/SDL/src/video/xbios/SDL_xbios_sb3.c @@ -0,0 +1,83 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* + ScreenBlaster 3 functions + + Patrice Mandin +*/ + +/*--- Includes ---*/ + +#include "SDL_stdinc.h" +#include "SDL_xbios.h" +#include "SDL_xbios_sb3.h" + +/*--- Defines ---*/ + +const int SDL_XBIOS_scpn_planes_device[]={ + SCPN_DEV_1BPP, + SCPN_DEV_4BPP, + SCPN_DEV_8BPP, + SCPN_DEV_16BPP, + SCPN_DEV_2BPP, + SCPN_DEV_4BPP, + SCPN_DEV_1BPP +}; + +/*--- Functions ---*/ + +int SDL_XBIOS_SB3Usable(scpn_cookie_t *cookie_scpn) +{ + scpn_screeninfo_t *scrinfo; + int bpp; + + /* Check if current SB3 mode is usable, i.e. 8 or 16bpp */ + scrinfo = cookie_scpn->screen_info; + bpp = 1<<(SDL_XBIOS_scpn_planes_device[scrinfo->device]); + + if ((bpp==8) || (bpp==16)) { + return 1; + } + + return 0; +} + +void SDL_XBIOS_ListSB3Modes(_THIS, int actually_add, scpn_cookie_t *cookie_scpn) +{ + scpn_screeninfo_t *scrinfo; + xbiosmode_t modeinfo; + + scrinfo = cookie_scpn->screen_info; + if (actually_add) { + scrinfo->h_pos = scrinfo->v_pos = 0; + } + + modeinfo.number = -1; + modeinfo.width = scrinfo->virtual_width; + modeinfo.height = scrinfo->virtual_height; + modeinfo.depth = 1<<(SDL_XBIOS_scpn_planes_device[scrinfo->device]); + modeinfo.flags = (modeinfo.depth == 8 ? XBIOSMODE_C2P : 0); + + SDL_XBIOS_AddMode(this, actually_add, &modeinfo); +} diff --git a/3rdparty/SDL/src/video/xbios/SDL_xbios_sb3.h b/3rdparty/SDL/src/video/xbios/SDL_xbios_sb3.h new file mode 100644 index 0000000..3272c31 --- /dev/null +++ b/3rdparty/SDL/src/video/xbios/SDL_xbios_sb3.h @@ -0,0 +1,82 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* + ScreenBlaster 3 definitions + + Patrice Mandin +*/ + +#ifndef _SDL_xbios_sb3_h_ +#define _SDL_xbios_sb3_h_ + +/*--- Defines ---*/ + +#ifndef C_SCPN +#define C_SCPN 0x5343504EL +#endif + +#define SCPN_DEV_1BPP 0 +#define SCPN_DEV_2BPP 1 +#define SCPN_DEV_4BPP 2 +#define SCPN_DEV_8BPP 3 +#define SCPN_DEV_16BPP 4 + +extern const int SDL_XBIOS_scpn_planes_device[]; + +/*--- Types ---*/ + +typedef struct { + unsigned short virtual_width; /* Virtual screen width */ + unsigned short virtual_height; /* Virtual screen height */ + unsigned short visible_width; /* Visible width */ + unsigned short visible_height; /* Visible height */ + unsigned short h_pos; /* Horizontal position in virtual screen */ + unsigned short v_pos; /* Vertical position in virtual screen */ + unsigned short dummy; + unsigned long size; /* Size of screen in bytes */ + unsigned short device; /* Device number to find planes = getRez() */ + /* = Index in scpn_planes_device[] */ +} scpn_screeninfo_t; + +typedef struct { + unsigned long magic; /* just a BRA assembler jump */ + unsigned short version; + void *dummy1; + unsigned short ptsout0_1; + unsigned short ptsout0_2; + unsigned short dummy3; + unsigned char date[8]; /* Date of program build */ + unsigned char asm_string[30]; /* 10 times the 'ASM' string */ + unsigned short dummy4; + scpn_screeninfo_t *screen_info; + unsigned short dummy6; +} scpn_cookie_t; + +/*--- Function prototypes ---*/ + +int SDL_XBIOS_SB3Usable(scpn_cookie_t *cookie_scpn); + +void SDL_XBIOS_ListSB3Modes(_THIS, int actually_add, scpn_cookie_t *cookie_scpn); + +#endif /* _SDL_xbios_sb3_h_ */ diff --git a/3rdparty/SDL/src/video/xbios/SDL_xbios_tveille.c b/3rdparty/SDL/src/video/xbios/SDL_xbios_tveille.c new file mode 100644 index 0000000..b0f8499 --- /dev/null +++ b/3rdparty/SDL/src/video/xbios/SDL_xbios_tveille.c @@ -0,0 +1,63 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* + Turbo veille screensaver + + Patrice Mandin +*/ + +#include <mint/cookie.h> + +#include "SDL_xbios.h" +#include "SDL_xbios_tveille.h" + +static tveille_t *cookie_veil = NULL; +static int status; + +int SDL_XBIOS_TveillePresent(_THIS) +{ + long dummy; + + cookie_veil = NULL; + if (Getcookie(C_VeiL, &dummy) == C_FOUND) { + cookie_veil = (tveille_t *) dummy; + } + + return (cookie_veil != NULL); +} + +void SDL_XBIOS_TveilleDisable(_THIS) +{ + if (cookie_veil) { + status = cookie_veil->enabled; + cookie_veil->enabled = 0xff; + } +} + +void SDL_XBIOS_TveilleEnable(_THIS) +{ + if (cookie_veil) { + cookie_veil->enabled = status; + } +} diff --git a/3rdparty/SDL/src/video/xbios/SDL_xbios_tveille.h b/3rdparty/SDL/src/video/xbios/SDL_xbios_tveille.h new file mode 100644 index 0000000..8a9cd7d --- /dev/null +++ b/3rdparty/SDL/src/video/xbios/SDL_xbios_tveille.h @@ -0,0 +1,64 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* + Turbo veille screensaver + + Patrice Mandin +*/ + +#ifndef _SDL_xbios_tveille_h +#define _SDL_xbios_tveille_h + +#include "SDL_xbios.h" + +/*--- Structures ---*/ + +typedef struct { + unsigned long version; + void (*prg_ptr)(); + void (*kbd_ptr)(); + void (*vbl_ptr)(); + unsigned long vbl_count; + void (*oldkbd_ptr)(); + unsigned long off_count; + unsigned long prg_size; + unsigned long dummy1[4]; + unsigned char dummy2; + unsigned char status; + unsigned short freq; + unsigned short dummy3; + unsigned char clear_first; + unsigned char enabled; /* 0=enabled, 0xff=disabled */ + unsigned char serial_redir; + unsigned char dummy4; + void (*oldserial_ptr)(); +} tveille_t; + +/*--- Functions prototypes ---*/ + +int SDL_XBIOS_TveillePresent(_THIS); +void SDL_XBIOS_TveilleDisable(_THIS); +void SDL_XBIOS_TveilleEnable(_THIS); + +#endif /* _SDL_xbios_tveille_h */ |