/*************************************************************************** SDLgfx.cpp Gambas extension using SDL (c) 2006 Laurent Carlier BenoƮt Minisini This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 1, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ***************************************************************************/ #include "SDLgfx.h" #include "SDLcore.h" #include "SDLapp.h" #include #include // texture status values #define TEXTURE_OK (0) #define TEXTURE_TO_RELOAD (1<<0) #define TEX_TO_REDEFINE (1<<1) // for ellipses #define PI 3.14159265359 // debug // #define DEBUGGFX // fill patterns static GLubyte VertPattern[] = {0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22}; static GLubyte HoriPattern[] = {0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; static GLubyte CrosPattern[] = {0xFF, 0xFF, 0xFF, 0xFF, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0xFF, 0xFF, 0xFF, 0xFF, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0xFF, 0xFF, 0xFF, 0xFF, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0xFF, 0xFF, 0xFF, 0xFF, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0xFF, 0xFF, 0xFF, 0xFF, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0xFF, 0xFF, 0xFF, 0xFF, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0xFF, 0xFF, 0xFF, 0xFF, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0xFF, 0xFF, 0xFF, 0xFF, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22}; static GLubyte BdiaPattern[] = {0x80, 0x80, 0x80, 0x80, 0x40, 0x40, 0x40, 0x40, 0x20, 0x20, 0x20, 0x20, 0x10, 0x10, 0x10, 0x10, 0x08, 0x08, 0x08, 0x08, 0x04, 0x04, 0x04, 0x04, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x80, 0x80, 0x80, 0x80, 0x40, 0x40, 0x40, 0x40, 0x20, 0x20, 0x20, 0x20, 0x10, 0x10, 0x10, 0x10, 0x08, 0x08, 0x08, 0x08, 0x04, 0x04, 0x04, 0x04, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x80, 0x80, 0x80, 0x80, 0x40, 0x40, 0x40, 0x40, 0x20, 0x20, 0x20, 0x20, 0x10, 0x10, 0x10, 0x10, 0x08, 0x08, 0x08, 0x08, 0x04, 0x04, 0x04, 0x04, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x80, 0x80, 0x80, 0x80, 0x40, 0x40, 0x40, 0x40, 0x20, 0x20, 0x20, 0x20, 0x10, 0x10, 0x10, 0x10, 0x08, 0x08, 0x08, 0x08, 0x04, 0x04, 0x04, 0x04, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01}; static GLubyte DiaPattern[] = {0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x04, 0x04, 0x04, 0x04, 0x08, 0x08, 0x08, 0x08, 0x10, 0x10, 0x10, 0x10, 0x20, 0x20, 0x20, 0x20, 0x40, 0x40, 0x40, 0x40, 0x80, 0x80, 0x80, 0x80, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x04, 0x04, 0x04, 0x04, 0x08, 0x08, 0x08, 0x08, 0x10, 0x10, 0x10, 0x10, 0x20, 0x20, 0x20, 0x20, 0x40, 0x40, 0x40, 0x40, 0x80, 0x80, 0x80, 0x80, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x04, 0x04, 0x04, 0x04, 0x08, 0x08, 0x08, 0x08, 0x10, 0x10, 0x10, 0x10, 0x20, 0x20, 0x20, 0x20, 0x40, 0x40, 0x40, 0x40, 0x80, 0x80, 0x80, 0x80, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x04, 0x04, 0x04, 0x04, 0x08, 0x08, 0x08, 0x08, 0x10, 0x10, 0x10, 0x10, 0x20, 0x20, 0x20, 0x20, 0x40, 0x40, 0x40, 0x40, 0x80, 0x80, 0x80, 0x80}; static GLubyte DiaCPattern[] = {0x81, 0x81, 0x81, 0x81, 0x42, 0x42, 0x42, 0x42, 0x24, 0x24, 0x24, 0x24, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x24, 0x24, 0x24, 0x24, 0x42, 0x42, 0x42, 0x42, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x42, 0x42, 0x42, 0x42, 0x24, 0x24, 0x24, 0x24, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x24, 0x24, 0x24, 0x24, 0x42, 0x42, 0x42, 0x42, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x42, 0x42, 0x42, 0x42, 0x24, 0x24, 0x24, 0x24, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x24, 0x24, 0x24, 0x24, 0x42, 0x42, 0x42, 0x42, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x42, 0x42, 0x42, 0x42, 0x24, 0x24, 0x24, 0x24, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x24, 0x24, 0x24, 0x24, 0x42, 0x42, 0x42, 0x42, 0x81, 0x81, 0x81, 0x81}; static GLubyte Dns1Pattern[] = {0xDD, 0xDD, 0xDD, 0xDD, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xDD, 0xDD, 0xDD, 0xDD, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xDD, 0xDD, 0xDD, 0xDD, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xDD, 0xDD, 0xDD, 0xDD, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xDD, 0xDD, 0xDD, 0xDD, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xDD, 0xDD, 0xDD, 0xDD, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xDD, 0xDD, 0xDD, 0xDD, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xDD, 0xDD, 0xDD, 0xDD, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; static GLubyte Dns2Pattern[] = {0xDD, 0xDD, 0xDD, 0xDD, 0xFF, 0xFF, 0xFF, 0xFF, 0x77, 0x77, 0x77, 0x77, 0xFF, 0xFF, 0xFF, 0xFF, 0xDD, 0xDD, 0xDD, 0xDD, 0xFF, 0xFF, 0xFF, 0xFF, 0x77, 0x77, 0x77, 0x77, 0xFF, 0xFF, 0xFF, 0xFF, 0xDD, 0xDD, 0xDD, 0xDD, 0xFF, 0xFF, 0xFF, 0xFF, 0x77, 0x77, 0x77, 0x77, 0xFF, 0xFF, 0xFF, 0xFF, 0xDD, 0xDD, 0xDD, 0xDD, 0xFF, 0xFF, 0xFF, 0xFF, 0x77, 0x77, 0x77, 0x77, 0xFF, 0xFF, 0xFF, 0xFF, 0xDD, 0xDD, 0xDD, 0xDD, 0xFF, 0xFF, 0xFF, 0xFF, 0x77, 0x77, 0x77, 0x77, 0xFF, 0xFF, 0xFF, 0xFF, 0xDD, 0xDD, 0xDD, 0xDD, 0xFF, 0xFF, 0xFF, 0xFF, 0x77, 0x77, 0x77, 0x77, 0xFF, 0xFF, 0xFF, 0xFF, 0xDD, 0xDD, 0xDD, 0xDD, 0xFF, 0xFF, 0xFF, 0xFF, 0x77, 0x77, 0x77, 0x77, 0xFF, 0xFF, 0xFF, 0xFF, 0xDD, 0xDD, 0xDD, 0xDD, 0xFF, 0xFF, 0xFF, 0xFF, 0x77, 0x77, 0x77, 0x77, 0xFF, 0xFF, 0xFF, 0xFF}; static GLubyte Dns3Pattern[] = {0xDD, 0xDD, 0xDD, 0xDD, 0xAA, 0xAA, 0xAA, 0xAA, 0x77, 0x77, 0x77, 0x77, 0xAA, 0xAA, 0xAA, 0xAA, 0xDD, 0xDD, 0xDD, 0xDD, 0xAA, 0xAA, 0xAA, 0xAA, 0x77, 0x77, 0x77, 0x77, 0xAA, 0xAA, 0xAA, 0xAA, 0xDD, 0xDD, 0xDD, 0xDD, 0xAA, 0xAA, 0xAA, 0xAA, 0x77, 0x77, 0x77, 0x77, 0xAA, 0xAA, 0xAA, 0xAA, 0xDD, 0xDD, 0xDD, 0xDD, 0xAA, 0xAA, 0xAA, 0xAA, 0x77, 0x77, 0x77, 0x77, 0xAA, 0xAA, 0xAA, 0xAA, 0xDD, 0xDD, 0xDD, 0xDD, 0xAA, 0xAA, 0xAA, 0xAA, 0x77, 0x77, 0x77, 0x77, 0xAA, 0xAA, 0xAA, 0xAA, 0xDD, 0xDD, 0xDD, 0xDD, 0xAA, 0xAA, 0xAA, 0xAA, 0x77, 0x77, 0x77, 0x77, 0xAA, 0xAA, 0xAA, 0xAA, 0xDD, 0xDD, 0xDD, 0xDD, 0xAA, 0xAA, 0xAA, 0xAA, 0x77, 0x77, 0x77, 0x77, 0xAA, 0xAA, 0xAA, 0xAA, 0xDD, 0xDD, 0xDD, 0xDD, 0xAA, 0xAA, 0xAA, 0xAA, 0x77, 0x77, 0x77, 0x77, 0xAA, 0xAA, 0xAA, 0xAA}; static GLubyte Dns4Pattern[] = {0x55, 0x55, 0x55, 0x55, 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, 0xAA, 0xAA, 0xAA, 0xAA}; static GLubyte Dns5Pattern[] = {0xAA, 0xAA, 0xAA, 0xAA, 0x44, 0x44, 0x44, 0x44, 0xAA, 0xAA, 0xAA, 0xAA, 0x11, 0x11, 0x11, 0x11, 0xAA, 0xAA, 0xAA, 0xAA, 0x44, 0x44, 0x44, 0x44, 0xAA, 0xAA, 0xAA, 0xAA, 0x11, 0x11, 0x11, 0x11, 0xAA, 0xAA, 0xAA, 0xAA, 0x44, 0x44, 0x44, 0x44, 0xAA, 0xAA, 0xAA, 0xAA, 0x11, 0x11, 0x11, 0x11, 0xAA, 0xAA, 0xAA, 0xAA, 0x44, 0x44, 0x44, 0x44, 0xAA, 0xAA, 0xAA, 0xAA, 0x11, 0x11, 0x11, 0x11, 0xAA, 0xAA, 0xAA, 0xAA, 0x44, 0x44, 0x44, 0x44, 0xAA, 0xAA, 0xAA, 0xAA, 0x11, 0x11, 0x11, 0x11, 0xAA, 0xAA, 0xAA, 0xAA, 0x44, 0x44, 0x44, 0x44, 0xAA, 0xAA, 0xAA, 0xAA, 0x11, 0x11, 0x11, 0x11, 0xAA, 0xAA, 0xAA, 0xAA, 0x44, 0x44, 0x44, 0x44, 0xAA, 0xAA, 0xAA, 0xAA, 0x11, 0x11, 0x11, 0x11, 0xAA, 0xAA, 0xAA, 0xAA, 0x44, 0x44, 0x44, 0x44, 0xAA, 0xAA, 0xAA, 0xAA, 0x11, 0x11, 0x11, 0x11}; static GLubyte Dns6Pattern[] = {0x22, 0x22, 0x22, 0x22, 0x00, 0x00, 0x00, 0x00, 0x88, 0x88, 0x88, 0x88, 0x00, 0x00, 0x00, 0x00, 0x22, 0x22, 0x22, 0x22, 0x00, 0x00, 0x00, 0x00, 0x88, 0x88, 0x88, 0x88, 0x00, 0x00, 0x00, 0x00, 0x22, 0x22, 0x22, 0x22, 0x00, 0x00, 0x00, 0x00, 0x88, 0x88, 0x88, 0x88, 0x00, 0x00, 0x00, 0x00, 0x22, 0x22, 0x22, 0x22, 0x00, 0x00, 0x00, 0x00, 0x88, 0x88, 0x88, 0x88, 0x00, 0x00, 0x00, 0x00, 0x22, 0x22, 0x22, 0x22, 0x00, 0x00, 0x00, 0x00, 0x88, 0x88, 0x88, 0x88, 0x00, 0x00, 0x00, 0x00, 0x22, 0x22, 0x22, 0x22, 0x00, 0x00, 0x00, 0x00, 0x88, 0x88, 0x88, 0x88, 0x00, 0x00, 0x00, 0x00, 0x22, 0x22, 0x22, 0x22, 0x00, 0x00, 0x00, 0x00, 0x88, 0x88, 0x88, 0x88, 0x00, 0x00, 0x00, 0x00, 0x22, 0x22, 0x22, 0x22, 0x00, 0x00, 0x00, 0x00, 0x88, 0x88, 0x88, 0x88, 0x00, 0x00, 0x00, 0x00}; static GLubyte Dns7Pattern[] = {0x22, 0x22, 0x22, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x22, 0x22, 0x22, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x22, 0x22, 0x22, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x22, 0x22, 0x22, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x22, 0x22, 0x22, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x22, 0x22, 0x22, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x22, 0x22, 0x22, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x22, 0x22, 0x22, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; static void SetLinePattern(int value) { GLushort pattern = 0xFFFF; if (value == SDL::SolidLine) return; if (value == SDL::DotLine) pattern = 0xCCCC; if (value == SDL::DashLine) pattern = 0xAAAA; if (value == SDL::DashDotLine) pattern = 0xE4E4; if (value == SDL::DashDotDotLine) pattern = 0xF98C; glEnable(GL_LINE_STIPPLE); glLineStipple(2, pattern); } static void SetFillPattern(int value) { if (!value) glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); else glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); if (value <= SDL::SolidFill) return; glEnable(GL_POLYGON_STIPPLE); if (value == SDL::VerticalFill) glPolygonStipple(VertPattern); if (value == SDL::HorizontalFill) glPolygonStipple(HoriPattern); if (value == SDL::CrossFill) glPolygonStipple(CrosPattern); if (value == SDL::BackDiagFill) glPolygonStipple(BdiaPattern); if (value == SDL::DiagFill) glPolygonStipple(DiaPattern); if (value == SDL::DiagCrossFill) glPolygonStipple(DiaCPattern); if (value == SDL::Dense1Fill) glPolygonStipple(Dns1Pattern); if (value == SDL::Dense2Fill) glPolygonStipple(Dns2Pattern); if (value == SDL::Dense3Fill) glPolygonStipple(Dns3Pattern); if (value == SDL::Dense4Fill) glPolygonStipple(Dns4Pattern); if (value == SDL::Dense5Fill) glPolygonStipple(Dns5Pattern); if (value == SDL::Dense6Fill) glPolygonStipple(Dns6Pattern); if (value == SDL::Dense7Fill) glPolygonStipple(Dns7Pattern); } SDLgfx::SDLgfx(SDLwindow *window) { hSurfaceInfo = window->hSurfaceInfo; hWindowDraw = true; hContextDefined = false; resetGfx(); } SDLgfx::SDLgfx(SDLsurface *surface) { hSurfaceInfo = surface->hSurfaceInfo; hWindowDraw = false; hContextDefined = false; resetGfx(); /* Does the surface already got a context (a Pbuffer is already defined ?) */ if (hContext) return; /* we define the pixel buffer if needed */ int scrnum; GLXFBConfig *fbconfig; XVisualInfo *visinfo; int nitems; Display *disp = SDLapp->X11appDisplay(); int attrib[] = { GLX_DOUBLEBUFFER, False, GLX_RED_SIZE, 1, GLX_GREEN_SIZE, 1, GLX_BLUE_SIZE, 1, GLX_RENDER_TYPE, GLX_RGBA_BIT, GLX_DRAWABLE_TYPE, GLX_PBUFFER_BIT | GLX_WINDOW_BIT, None }; int pbufAttrib[] = { GLX_PBUFFER_WIDTH, hSurface->w, GLX_PBUFFER_HEIGHT, hSurface->h, GLX_LARGEST_PBUFFER, False, None }; SDLapp->LockX11(); scrnum = DefaultScreen(disp); fbconfig = glXChooseFBConfig(disp, scrnum, attrib, &nitems); if (!fbconfig) { SDLcore::RaiseError("SDLgfx: error, couldn't get fbconfig"); return; } hPbuffer = glXCreatePbuffer(disp, fbconfig[0], pbufAttrib); visinfo = glXGetVisualFromFBConfig(disp, fbconfig[0] ); if (!visinfo ) { SDLcore::RaiseError("SDLgfx: error, couldn't get an RGBA, double-buffered visual"); return; } if (!SDLcore::GetWindow()) { SDLcore::RaiseError("SDLgfx: window not defined, will be fixed later !"); return; } hContext = glXCreateContext(disp, visinfo, SDLcore::GetWindow()->hSurfaceInfo->Ctx, GL_TRUE); if (!hContext ) { SDLcore::RaiseError("SDLgfx: error, Call to glXCreateContext failed!"); return; } XFree(fbconfig); XFree(visinfo); hContextDefined = true; SDLapp->UnlockX11(); } SDLgfx::~SDLgfx() { if (hWindowDraw) return; if (!hContextDefined) return; Display *disp = SDLapp->X11appDisplay(); glXDestroyContext(disp, hContext); glXDestroyPbuffer(disp, hPbuffer); } void SDLgfx::resetGfx(void) { hForeColor = 0xFFFFFFFF; hBackColor = 0x00000000; hLine = SDL::SolidLine; hLineWidth = 1; hFill = SDL::NoFill; hTextureStatus = TEXTURE_TO_RELOAD; } void SDLgfx::SetLineStyle(int style) { if (style>SDL::DashDotDotLine) style = SDL::DashDotDotLine; hLine = style; } void SDLgfx::SetFillStyle(int style) { if (style>SDL::Dense7Fill) style = SDL::Dense7Fill; hFill = style; } void SDLgfx::Clear(void) { if (!hSurface) return; Uint32 myColor = hBackColor; if (hSurface->flags & SDL_OPENGL) { glClearColor((GLfloat((hBackColor >> 24) & 0xFF)/255), (GLfloat((hBackColor >> 16) & 0xFF)/255), (GLfloat((hBackColor >> 8) & 0xFF)/255), 1.0f); glClear(GL_COLOR_BUFFER_BIT); } else { Uint32 FillColor = SDL_MapRGB(hSurface->format, ((hBackColor >> 24) & 0xFF), ((hBackColor >> 16) & 0xFF), ((hBackColor >> 8) & 0xFF)); if (SDL_FillRect(hSurface, NULL, FillColor)<0) SDLcore::RaiseError(SDL_GetError()); } hBackColor = myColor; hTextureStatus = TEXTURE_TO_RELOAD; } void SDLgfx::DrawPixel(int x, int y) { if (!hSurface) return; glBegin(GL_POINTS); glColor4f((GLfloat((hForeColor >> 24) & 0xFF)/ 255), (GLfloat((hForeColor >> 16) & 0xFF)/255), (GLfloat((hForeColor >> 8) & 0xFF)/255), (GLfloat(hForeColor & 0xFF)/255)); glVertex2i(x, y); glEnd(); hTextureStatus = TEXTURE_TO_RELOAD; } void SDLgfx::DrawLine(int x1, int y1, int x2, int y2) { if (!hSurface) return; if (!hLine) // SDLgfx::NoLine return; if (hSurface->flags & SDL_OPENGL) { glPushAttrib(GL_ALL_ATTRIB_BITS); SetLinePattern(hLine); glLineWidth(GLfloat(hLineWidth)); glBegin(GL_LINES); glColor4f((GLfloat((hForeColor >> 24) & 0xFF)/ 255), (GLfloat((hForeColor >> 16) & 0xFF)/255), (GLfloat((hForeColor >> 8) & 0xFF)/255), (GLfloat(hForeColor & 0xFF)/255)); glVertex2i(x1, y1); glVertex2i(x2, y2); glEnd(); glPopAttrib(); } hTextureStatus = TEXTURE_TO_RELOAD; } void SDLgfx::DrawRect(int x, int y, int w, int h) { if (!hSurface) return; if (!hFill && !hLine) return; if (hSurface->flags & SDL_OPENGL) { glPushAttrib(GL_ALL_ATTRIB_BITS); SetFillPattern(hFill); glColor4f((GLfloat((hForeColor >> 24) & 0xFF)/ 255), (GLfloat((hForeColor >> 16) & 0xFF)/255), (GLfloat((hForeColor >> 8) & 0xFF)/255), (GLfloat(hForeColor & 0xFF)/255)); glBegin(GL_QUADS); glVertex2i(x, y); glVertex2i(x+w, y); glVertex2i(x+w, y+h); glVertex2i(x, y+h); glEnd(); if (hFill>SDL::SolidFill) { SetFillPattern(SDL::NoFill); SetLinePattern(hLine); glLineWidth(GLfloat(hLineWidth)); glBegin(GL_QUADS); glVertex2i(x, y); glVertex2i(x+w, y); glVertex2i(x+w, y+h); glVertex2i(x, y+h); glEnd(); } glPopAttrib(); } } void SDLgfx::DrawEllipse(int x, int y, int w, int h) { if (!hSurface) return; if (!hFill && !hLine) return; double angle; double step = 2 * PI / 360; glPushAttrib(GL_ALL_ATTRIB_BITS); SetFillPattern(hFill); glColor4f((GLfloat((hForeColor >> 24) & 0xFF)/ 255), (GLfloat((hForeColor >> 16) & 0xFF)/255), (GLfloat((hForeColor >> 8) & 0xFF)/255), (GLfloat(hForeColor & 0xFF)/255)); glBegin(GL_POLYGON); for (angle=0; angle < 2 * PI; angle += step) { glVertex2d(x + (w * cos(angle)), y + (h * sin(angle))); } glEnd(); if (hFill>SDL::SolidFill) { SetFillPattern(SDL::NoFill); SetLinePattern(hLine); glLineWidth(GLfloat(hLineWidth)); glBegin(GL_POLYGON); for (angle=0; angle < 2 * PI; angle += step) { glVertex2d(x + (w * cos(angle)), y + (h * sin(angle))); } glEnd(); } glPopAttrib(); } void SDLgfx::Blit(SDLsurface *surface, int x, int y, int srcX, int srcY, int srcWidth, int srcHeight, int width, int height) { if (!hSurface) return; // will keep current SDL_INFO struct SDL_INFO *tmpInfo = hSurfaceInfo; int myWidth = 0, myHeight = 0; // we will work with the SDLsurface SDL_INFO struct hSurfaceInfo = surface->hSurfaceInfo; if (!hSurface) goto _endblit; if ((srcX > hSurface->w) || (srcY > hSurface->h)) goto _endblit; if ((srcHeight<0) || ((srcY + srcHeight) > hSurface->h)) myHeight = hSurface->h - srcY; else myHeight = srcHeight; if ((srcWidth<0) || ((srcX + srcWidth) > hSurface->w)) myWidth = hSurface->w - srcX; else myWidth = srcWidth; GLdouble myTexX, myTexY, myTexHeight, myTexWidth; ManageTexture(); myTexX = ((srcX * hTextureWidth) / hSurface->w); myTexY = ((srcY * hTextureHeight) / hSurface->h); myTexWidth = (((srcX + myWidth)* hTextureWidth) / hSurface->w); myTexHeight = (((srcY + myHeight)* hTextureHeight) / hSurface->h); if (width != -1) myWidth = width; if (height != -1) myHeight = height; glBegin(GL_QUADS); glColor4f(1.0, 1.0, 1.0, 1.0); glTexCoord2d(myTexX, myTexY); glVertex2i(x, y); glTexCoord2d(myTexX, myTexHeight); glVertex2i(x, y + myHeight); glTexCoord2d(myTexWidth, myTexHeight); glVertex2i(x + myWidth, y + myHeight); glTexCoord2d(myTexWidth, myTexY); glVertex2i(x + myWidth, y); glEnd(); _endblit: hSurfaceInfo = tmpInfo; } static int power_of_two(int input) { int value = 1; while ( value < input ) { value <<= 1; } return value; } void SDLgfx::ManageTexture() { if (!hTexture) { glGenTextures(1, &hTexture); hTextureStatus = TEXTURE_TO_RELOAD; } glEnable(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D, hTexture); if (hTextureStatus & TEXTURE_TO_RELOAD) { #ifdef DEBUGGFX std::cout << "Loading texture " << hTextureIndex << std::endl; #endif int w, h; SDL_Surface *image; Uint32 saved_flags; Uint8 saved_alpha; /* Use the surface width and height expanded to powers of 2 */ w = power_of_two(hSurface->w); h = power_of_two(hSurface->h); hTextureWidth = GLdouble(hSurface->w) / w; /* Max X */ hTextureHeight = GLdouble(hSurface->h) / h; /* Max Y */ image = SDL_CreateRGBSurface(SDL_SWSURFACE, w, h, 32, #if SDL_BYTEORDER == SDL_LIL_ENDIAN /* OpenGL RGBA masks */ 0x000000FF, 0x0000FF00, 0x00FF0000, 0xFF000000 #else 0xFF000000, 0x00FF0000, 0x0000FF00, 0x000000FF #endif ); if ( image == NULL ) return; /* Save the alpha blending attributes */ saved_flags = hSurface->flags & (SDL_SRCALPHA | SDL_RLEACCELOK); saved_alpha = hSurface->format->alpha; if ((saved_flags & SDL_SRCALPHA) == SDL_SRCALPHA) SDL_SetAlpha(hSurface, 0, 0); /* Copy the surface into the GL texture image */ SDL_BlitSurface(hSurface, NULL, image, NULL); /* Restore the alpha blending attributes */ if ((saved_flags & SDL_SRCALPHA) == SDL_SRCALPHA ) SDL_SetAlpha(hSurface, saved_flags, saved_alpha); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, image->pixels); /* Use of CLAMP_TO_EDGE, without it give a black line around the texture with DRI radeon drivers */ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); SDL_FreeSurface(image); /* No longer needed */ hTextureStatus = TEXTURE_OK; } }