36 #include "SDL_image.h"
116 static std::string backend_name =
"OpenGL";
122 Uint32 flags = SDL_INIT_VIDEO;
123 if (SDL_InitSubSystem(flags) < 0)
124 throw SDLException(SDL_GetError());
125 SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
126 SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 8);
128 SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL);
133 glClear(GL_COLOR_BUFFER_BIT);
139 SDL_Surface *img = IMG_Load(icon.c_str());
141 SDL_WM_SetIcon(img, 0);
142 SDL_FreeSurface(img);
146 SDL_WM_SetCaption(title.c_str(), 0);
156 if (bitsPerPixel != 0) {
157 uint16_t bpp = SDL_VideoModeOK(width, height, bitsPerPixel, flags);
159 throw SDLException(
"Selected video mode not supported!");
166 m_screen = SDL_SetVideoMode(width, height, bitsPerPixel, flags);
168 throw SDLException(
"Unable to set video mode selected!");
173 <<
"Videomode " << width <<
"x" << height
174 <<
" at " << int32_t(bitsPerPixel) <<
" bpp");
189 throw SDLException(SDL_GetError());
192 glViewport(0, 0, width, height);
193 glMatrixMode(GL_PROJECTION);
195 glOrtho(0, width, height, 0, -1, 1);
196 glMatrixMode(GL_MODELVIEW);
199 glEnable(GL_CULL_FACE);
203 glPixelStorei(GL_PACK_ALIGNMENT, 1);
204 glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
206 glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
209 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
211 glEnable(GL_SCISSOR_TEST);
213 glEnableClientState(GL_COLOR_ARRAY);
214 glEnableClientState(GL_VERTEX_ARRAY);
231 SDL_GL_SwapBuffers();
240 return new GLImage(name, loader);
250 if (32 == surface->format->BitsPerPixel
263 && surface->flags & SDL_SRCALPHA ) {
270 SDL_Surface* conv = SDL_ConvertSurface(surface, &
m_rgba_format, SDL_SWSURFACE | SDL_SRCALPHA);
274 SDL_FreeSurface(surface);
285 if (32 == surface->format->BitsPerPixel
298 && surface->flags & SDL_SRCALPHA ) {
300 return new GLImage(name, surface);
305 SDL_Surface* conv = SDL_ConvertSurface(surface, &
m_rgba_format, SDL_SWSURFACE | SDL_SRCALPHA);
309 SDL_FreeSurface(surface);
314 return new GLImage(data, width, height);
318 return new GLImage(name, data, width, height);
325 glDisable(GL_COLOR_MATERIAL);
326 }
else if (lighting != 0) {
329 glColorMaterial(GL_FRONT, GL_DIFFUSE);
330 glEnable(GL_COLOR_MATERIAL);
344 glActiveTexture(GL_TEXTURE0 + texUnit);
348 glEnable(GL_TEXTURE_2D);
350 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
360 glActiveTexture(GL_TEXTURE0 + texUnit);
364 glDisable(GL_TEXTURE_2D);
366 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
377 glActiveTexture(GL_TEXTURE0 + texUnit);
380 glBindTexture(GL_TEXTURE_2D, texId);
387 glBindTexture(GL_TEXTURE_2D, texId);
393 glEnable(GL_LIGHTING);
400 glDisable(GL_LIGHTING);
407 GLfloat lightDiffuse[] = {red, green, blue, 1.0f};
408 glLightfv(GL_LIGHT0, GL_DIFFUSE, lightDiffuse);
420 glEnable(GL_STENCIL_TEST);
427 glDisable(GL_STENCIL_TEST);
449 glClearStencil(buffer);
452 glClear(GL_STENCIL_BUFFER_BIT);
462 glEnable(GL_ALPHA_TEST);
469 glDisable(GL_ALPHA_TEST);
476 glAlphaFunc(GL_GREATER, ref_alpha);
491 glActiveTexture(GL_TEXTURE1);
494 glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, rgbaf);
501 glVertexPointer(2, GL_FLOAT, stride, ptr);
508 glColorPointer(4, GL_UNSIGNED_BYTE, stride, ptr);
516 glClientActiveTexture(GL_TEXTURE0 + texUnit);
519 glTexCoordPointer(2, GL_FLOAT, stride, ptr);
526 glEnable(GL_SCISSOR_TEST);
533 glDisable(GL_SCISSOR_TEST);
542 case 0 : src_fact = GL_ZERO;
break;
543 case 1 : src_fact = GL_ONE;
break;
544 case 2 : src_fact = GL_DST_COLOR;
break;
545 case 3 : src_fact = GL_ONE_MINUS_DST_COLOR;
break;
546 case 4 : src_fact = GL_SRC_ALPHA;
break;
547 case 5 : src_fact = GL_ONE_MINUS_SRC_ALPHA;
break;
548 case 6 : src_fact = GL_DST_ALPHA;
break;
549 case 7 : src_fact = GL_ONE_MINUS_DST_ALPHA;
break;
551 default : src_fact = GL_DST_COLOR;
break;
555 case 0 : dst_fact = GL_ZERO;
break;
556 case 1 : dst_fact = GL_ONE;
break;
557 case 2 : dst_fact = GL_SRC_COLOR;
break;
558 case 3 : dst_fact = GL_ONE_MINUS_SRC_COLOR;
break;
559 case 4 : dst_fact = GL_SRC_ALPHA;
break;
560 case 5 : dst_fact = GL_ONE_MINUS_SRC_ALPHA;
break;
561 case 6 : dst_fact = GL_DST_ALPHA;
break;
562 case 7 : dst_fact = GL_ONE_MINUS_DST_ALPHA;
break;
564 default : dst_fact = GL_SRC_ALPHA;
break;
570 glBlendFunc(src_fact, dst_fact);
579 while (count != elements) {
599 bool texture =
false;
600 bool blending =
false;
602 bool stencil =
false;
622 GLenum mode = GL_QUADS;
630 bool multitextured =
false;
636 int32_t* currentIndex = &index;
637 uint32_t* currentElements = &elements;
643 if (ro.
mode != mode) {
652 if (ro.
src != src || ro.
dst != dst) {
680 if (*currentElements > 0) {
682 glDrawArrays(mode, *currentIndex, *currentElements);
683 *currentIndex += *currentElements;
704 multitextured =
true;
705 currentElements = &elements2T;
706 currentIndex = &index2T;
717 multitextured =
false;
718 currentIndex = &index;
719 currentElements = &elements;
737 *currentElements = ro.
size;
772 *currentElements += ro.
size;
776 glDrawArrays(mode, *currentIndex, *currentElements);
796 if ((x < 0) || (x >= (int32_t)
m_target->w) ||
797 (y < 0) || (y >= (int32_t)
m_target->h)) {
801 rd.
vertex[0] =
static_cast<float>(x);
802 rd.
vertex[1] =
static_cast<float>(y);
817 rd.
vertex[0] =
static_cast<float>(p1.
x);
818 rd.
vertex[1] =
static_cast<float>(p1.
y);
825 rd.
vertex[0] =
static_cast<float>(p2.
x);
826 rd.
vertex[1] =
static_cast<float>(p2.
y);
835 rd.
vertex[0] =
static_cast<float>(p1.
x);
836 rd.
vertex[1] =
static_cast<float>(p1.
y);
843 rd.
vertex[0] =
static_cast<float>(p2.
x);
844 rd.
vertex[1] =
static_cast<float>(p2.
y);
847 rd.
vertex[0] =
static_cast<float>(p3.
x);
848 rd.
vertex[1] =
static_cast<float>(p3.
y);
857 rd.
vertex[0] =
static_cast<float>(p.
x);
858 rd.
vertex[1] =
static_cast<float>(p.
y);
864 rd.
vertex[0] =
static_cast<float>(p.
x+w);
867 rd.
vertex[1] =
static_cast<float>(p.
y+h);
870 rd.
vertex[0] =
static_cast<float>(p.
x);
879 rd.
vertex[0] =
static_cast<float>(p.
x);
880 rd.
vertex[1] =
static_cast<float>(p.
y);
887 rd.
vertex[1] =
static_cast<float>(p.
y+h);
890 rd.
vertex[0] =
static_cast<float>(p.
x+w);
893 rd.
vertex[1] =
static_cast<float>(p.
y);
902 rd.
vertex[0] =
static_cast<float>(p1.
x);
903 rd.
vertex[1] =
static_cast<float>(p1.
y);
910 rd.
vertex[0] =
static_cast<float>(p2.
x);
911 rd.
vertex[1] =
static_cast<float>(p2.
y);
914 rd.
vertex[0] =
static_cast<float>(p3.
x);
915 rd.
vertex[1] =
static_cast<float>(p3.
y);
918 rd.
vertex[0] =
static_cast<float>(p4.
x);
919 rd.
vertex[1] =
static_cast<float>(p4.
y);
928 rd.
vertex[0] =
static_cast<float>(p.
x-size);
929 rd.
vertex[1] =
static_cast<float>(p.
y+size);
936 rd.
vertex[0] =
static_cast<float>(p.
x+size);
939 rd.
vertex[1] =
static_cast<float>(p.
y-size);
942 rd.
vertex[0] =
static_cast<float>(p.
x-size);
953 rd.
vertex[0] =
static_cast<float>(p.
x);
954 rd.
vertex[1] =
static_cast<float>(p.
y);
958 rd.
color[3] = intensity;
981 rd.
vertex[0] =
static_cast<float>(rect.
x);
982 rd.
vertex[1] =
static_cast<float>(rect.
y);
991 rd.
vertex[0] =
static_cast<float>(rect.
x);
992 rd.
vertex[1] =
static_cast<float>(rect.
y+rect.
h);
996 rd.
vertex[0] =
static_cast<float>(rect.
x+rect.
w);
997 rd.
vertex[1] =
static_cast<float>(rect.
y+rect.
h);
1001 rd.
vertex[0] =
static_cast<float>(rect.
x+rect.
w);
1002 rd.
vertex[1] =
static_cast<float>(rect.
y);
1003 rd.
texel[1] = st[1];
1010 rd.
vertex[0] =
static_cast<float>(rect.
x);
1011 rd.
vertex[1] =
static_cast<float>(rect.
y);
1012 rd.
texel[0] = st[0];
1013 rd.
texel[1] = st[1];
1019 rd.
color[3] = alpha;
1022 rd.
vertex[0] =
static_cast<float>(rect.
x);
1023 rd.
vertex[1] =
static_cast<float>(rect.
y+rect.
h);
1024 rd.
texel[1] = st[3];
1028 rd.
vertex[0] =
static_cast<float>(rect.
x+rect.
w);
1029 rd.
vertex[1] =
static_cast<float>(rect.
y+rect.
h);
1030 rd.
texel[0] = st[2];
1034 rd.
vertex[0] =
static_cast<float>(rect.
x+rect.
w);
1035 rd.
vertex[1] =
static_cast<float>(rect.
y);
1036 rd.
texel[1] = st[1];
1042 ro.
rgba[0] = rgba[0];
1043 ro.
rgba[1] = rgba[1];
1044 ro.
rgba[2] = rgba[2];
1045 ro.
rgba[3] = rgba[3];
1051 glActiveTexture(GL_TEXTURE1);
1052 glEnable(GL_TEXTURE_2D);
1058 uint8_t dummydata[3] = {127, 127, 127};
1060 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1061 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1062 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
1063 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
1064 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8, 1, 1, 0,
1065 GL_RGB, GL_UNSIGNED_BYTE, dummydata);
1072 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
1073 glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_INTERPOLATE);
1074 glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_MODULATE);
1077 glTexEnvi(GL_TEXTURE_ENV, GL_SRC0_RGB, GL_TEXTURE0);
1078 glTexEnvi(GL_TEXTURE_ENV, GL_SRC0_ALPHA, GL_TEXTURE0);
1079 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR);
1080 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_ALPHA);
1087 glTexEnvi(GL_TEXTURE_ENV, GL_SRC1_RGB, GL_CONSTANT);
1088 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB, GL_SRC_COLOR);
1092 glTexEnvi(GL_TEXTURE_ENV, GL_SRC2_RGB, GL_CONSTANT);
1093 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_RGB, GL_SRC_ALPHA);
1096 glActiveTexture(GL_TEXTURE1);
1097 glDisable(GL_TEXTURE_2D);
1098 glActiveTexture(GL_TEXTURE0);
1109 SDL_Surface *surface = SDL_CreateRGBSurface(SDL_SWSURFACE, swidth, sheight, 24,
1116 SDL_LockSurface(surface);
1117 pixels =
new uint8_t[swidth * sheight * 3];
1118 glReadPixels(0, 0, swidth, sheight, GL_RGB, GL_UNSIGNED_BYTE, reinterpret_cast<GLvoid*>(pixels));
1119 uint8_t *imagepixels =
reinterpret_cast<uint8_t*
>(surface->pixels);
1121 for (int32_t y = (sheight - 1); y >= 0; --y) {
1122 uint8_t *rowbegin = pixels + y * swidth * 3;
1123 uint8_t *rowend = rowbegin + swidth * 3;
1125 std::copy(rowbegin, rowend, imagepixels);
1128 imagepixels += surface->pitch;
1131 SDL_UnlockSurface(surface);
1134 SDL_FreeSurface(surface);
1141 const bool same_size = (width == swidth && height == sheight);
1143 if (width < 1 || height < 1) {
1154 SDL_Surface* src = SDL_CreateRGBSurface(SDL_SWSURFACE, swidth, sheight, 32,
1161 if (SDL_MUSTLOCK(src)) {
1162 SDL_LockSurface(src);
1164 pixels =
new uint8_t[swidth * sheight * 4];
1165 glReadPixels(0, 0, swidth, sheight, GL_RGBA, GL_UNSIGNED_BYTE, reinterpret_cast<GLvoid*>(pixels));
1169 for (int32_t y = (sheight - 1); y >= 0; --y) {
1170 uint8_t *rowbegin = pixels + y * swidth * 4;
1171 uint8_t *rowend = rowbegin + swidth * 4;
1173 std::copy(rowbegin, rowend, imagepixels);
1176 imagepixels += src->pitch;
1180 SDL_Surface* dst = SDL_CreateRGBSurface(SDL_SWSURFACE, width, height, 32,
1184 uint32_t* src_help_pointer = src_pointer;
1187 int32_t x, y, *sx_ca, *sy_ca;
1188 int32_t sx =
static_cast<int32_t
>(0xffff * src->w / dst->w);
1189 int32_t sy =
static_cast<int32_t
>(0xffff * src->h / dst->h);
1194 int32_t* sx_a =
new int32_t[dst->w + 1];
1196 for (x = 0; x <= dst->w; x++) {
1203 int32_t* sy_a =
new int32_t[dst->h + 1];
1205 for (y = 0; y <= dst->h; y++) {
1215 if (SDL_MUSTLOCK(dst)) {
1216 SDL_LockSurface(dst);
1219 for (y = 0; y < dst->h; y++) {
1220 src_pointer = src_help_pointer;
1222 for (x = 0; x < dst->w; x++) {
1223 *dst_pointer = *src_pointer;
1225 src_pointer += (*sx_ca >> 16);
1229 src_help_pointer = (
uint32_t*)((
uint8_t*)src_help_pointer + (*sy_ca >> 16) * src->pitch);
1232 if (SDL_MUSTLOCK(dst)) {
1233 SDL_UnlockSurface(dst);
1235 if (SDL_MUSTLOCK(src)) {
1236 SDL_UnlockSurface(src);
1242 SDL_FreeSurface(src);
1243 SDL_FreeSurface(dst);
1250 glScissor(cliparea.
x,
getHeight() - cliparea.
y - cliparea.
h, cliparea.
w, cliparea.
h);
1256 glClearColor(red, green, blue, 0.0);
1259 glClear(GL_COLOR_BUFFER_BIT);
1276 GLuint targetid = glimage->
getTexId();
1283 GLubyte* pixels =
new GLubyte[w*h*4];
1285 glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
1286 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
1293 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT,
m_fbo_id);
1294 glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
1295 GL_TEXTURE_2D, targetid, 0);
1298 glViewport(0, 0, w, h);
1299 glMatrixMode(GL_PROJECTION);
1302 glOrtho(0, w, 0, h, -1, 1);
1303 glMatrixMode(GL_MODELVIEW);
1305 glCullFace(GL_FRONT);
1308 glClear(GL_COLOR_BUFFER_BIT);
1323 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
1326 glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 0, 0,
1332 glMatrixMode(GL_PROJECTION);
1335 glMatrixMode(GL_MODELVIEW);
1336 glCullFace(GL_BACK);
Abstract interface for all the renderbackends.
virtual void changeRenderInfos(uint16_t elements, int32_t src, int32_t dst, bool light, bool stentest, uint8_t stenref, GLConstants stenop, GLConstants stenfunc)
Dirty helper function to change the render infos.
T * get() const
allows direct access to underlying pointer
virtual void setScreenMode(const ScreenMode &mode)
Sets the mainscreen display mode.
virtual void setLighting(float red, float green, float blue)
Set colors for lighting.
virtual void fillRectangle(const Point &p, uint16_t w, uint16_t h, uint8_t r, uint8_t g, uint8_t b, uint8_t a=255)
Draws a filled axis parallel rectangle.
virtual uint32_t getLightingModel() const
Gets the current light model.
T h
Height of the rectangle.
Helper class to create log strings out from separate parts Usage: LMsg("some text") << variable << "...
SDL_PixelFormat m_rgba_format
uint32_t getHeight() const
void setCompressed(bool compressed)
uint32_t getSDLFlags() const
Returns the SDL flags used when testing this mode.
virtual void renderVertexArrays()
Render the Vertex Arrays, only for primitives (points, lines,...)
void disableTextures(uint32_t texUnit)
static void saveAsPng(const std::string &filename, const SDL_Surface &surface)
Saves the SDL_Surface to png format.
virtual void init(const std::string &driver)
Initializes the backend.
uint16_t getBPP() const
Returns the number of bits per pixel this mode uses.
virtual bool putPixel(int32_t x, int32_t y, uint8_t r, uint8_t g, uint8_t b, uint8_t a=255)
Writes pixel to given position.
virtual void drawQuad(const Point &p1, const Point &p2, const Point &p3, const Point &p4, uint8_t r, uint8_t g, uint8_t b, uint8_t a=255)
Draws quad between given points with given RGBA.
virtual void drawTriangle(const Point &p1, const Point &p2, const Point &p3, uint8_t r, uint8_t g, uint8_t b, uint8_t a=255)
Draws triangle between given points with given RGBA.
static Logger _log(LM_AUDIO)
void prepareForOverlays()
virtual void drawLine(const Point &p1, const Point &p2, uint8_t r, uint8_t g, uint8_t b, uint8_t a=255)
Draws line between given points with given RGBA.
void setVertexPointer(GLsizei stride, const GLvoid *ptr)
virtual void setClipArea(const Rect &cliparea, bool clear)
Sets given clip area into image.
virtual void drawVertex(const Point &p, const uint8_t size, uint8_t r, uint8_t g, uint8_t b, uint8_t a=255)
Draws a quad that represents a vertex with given RGBA.
uint8_t getStencilRef() const
void setStencilTest(uint8_t stencil_ref, GLenum stencil_op, GLenum stencil_func)
const Rect & getArea() const
void enableTextures(uint32_t texUnit)
virtual void addImageToArray(uint32_t id, const Rect &rec, float const *st, uint8_t alpha, uint8_t const *rgba)
Add the Image data to the array.
virtual void setLightingModel(uint32_t lighting)
Initializes the light.
virtual Image * createImage(IResourceLoader *loader=0)
uint32_t getHeight() const
void setEnvironmentalColor(const uint8_t *rgba)
virtual void resetLighting()
Reset lighting with default values.
std::vector< RenderObject > m_render_objects
void disableScissorTest()
virtual void captureScreen(const std::string &filename)
Creates a Screenshot and saves it to a file.
SDL_Surface * getSurface()
virtual void startFrame()
Called when a new frame starts.
std::vector< renderData2T > m_render_datas2T
virtual void clearBackBuffer()
Forces a clear of the backbuffer.
virtual ~RenderBackendOpenGL()
virtual void changeBlending(int32_t scr, int32_t dst)
Change the Blendingmodel.
bool isCompressed() const
uint16_t getHeight() const
Returns the height of the screen mode.
struct FIFE::RenderBackendOpenGL::currentState m_state
uint32_t getWidth() const
uint32_t active_client_tex
const void * tex_pointer[2]
uint16_t getWidth() const
Returns the width of the screen mode.
virtual void detachRenderTarget()
Detaches current render surface.
SDL_Color m_backgroundcolor
#define FL_LOG(logger, msg)
void setTexCoordPointer(uint32_t texUnit, GLsizei stride, const GLvoid *ptr)
uint32_t getWidth() const
virtual void endFrame()
Called when a frame is finished and ready to be displayed.
const void * vertex_pointer
const void * color_pointer
void setAlphaTest(float ref_alpha)
virtual void createMainScreen(const ScreenMode &mode, const std::string &title, const std::string &icon)
Creates the mainscreen (the display window).
virtual void forceLoadInternal()=0
Forces to load the image into internal memory of GPU.
Implements an Image using OpenGL.
void disableStencilTest()
RenderBackendOpenGL(const SDL_Color &colorkey)
std::vector< renderData > m_render_datas
void setColorPointer(GLsizei stride, const GLvoid *ptr)
virtual void drawRectangle(const Point &p, uint16_t w, uint16_t h, uint8_t r, uint8_t g, uint8_t b, uint8_t a=255)
Draws an axis parallel rectangle.
virtual void drawLightPrimitive(const Point &p, uint8_t intensity, float radius, int32_t subdivisions, float xstretch, float ystretch, uint8_t red, uint8_t green, uint8_t blue)
Draws a light primitive that based on a triangle fan.
virtual void attachRenderTarget(ImagePtr &img, bool discard)
Attaches given image as a new render surface.
RenderObject(GLenum m, uint16_t s, uint32_t t=0)
void deinit()
Performs cleanup actions.
virtual void startFrame()
Called when a new frame starts.
T w
Width of the rectangle.
void bindTexture(uint32_t texUnit, GLuint texId)
virtual void endFrame()
Called when a frame is finished and ready to be displayed.
virtual void resetStencilBuffer(uint8_t buffer)
Reset stencil buffer with given value.
virtual const std::string & getName() const
The name of the renderbackend.