void OpenGLGraphics::SetPixel ( Uint32 _surfaceID, int x, int y, Uint32 _color ) { if ( _surfaceID == SCREEN_SURFACE_ID ) { g_openGL->VertexArrayStatePrimitive (); g_openGL->DeactivateTextureRect (); glDisable ( GL_BLEND ); ASSERT_OPENGL_ERRORS; #ifndef TARGET_OS_WINDOWS m_vertexArray[0] = x; m_vertexArray[1] = y; _color |= FULL_ALPHA; g_openGL->ActivateColour ( _color ); glDrawArrays ( GL_POINTS, 0, 1 ); #else glRasterPos2i ( x, y ); ASSERT_OPENGL_ERRORS; glDrawPixels ( 1, 1, GL_RGBA, GL_UNSIGNED_INT, &_color ); ASSERT_OPENGL_ERRORS; #endif glEnable ( GL_BLEND ); ASSERT_OPENGL_ERRORS; } else { ARCReleaseAssert ( m_textures.valid ( _surfaceID ) ); OpenGLTexture *tex = m_textures.get ( _surfaceID ); tex->SetPixel ( x, y, _color ); tex->Damage(); } }
int OpenGLGraphics::FillRect ( Uint32 _surfaceID, SDL_Rect *_destRect, Uint32 _color ) { ARCReleaseAssert ( m_sdlScreen != NULL ); if ( _color == m_colorKey ) _color = m_colorKey & ZERO_ALPHA; if (_surfaceID == SCREEN_SURFACE_ID) { // fill a rectangle on screen g_openGL->ActivateColour ( _color ); g_openGL->DeactivateTextureRect (); g_openGL->VertexArrayStatePrimitive (); if ( _destRect ) { m_vertexArray[0] = _destRect->x; m_vertexArray[1] = _destRect->y; m_vertexArray[2] = _destRect->x + _destRect->w; m_vertexArray[3] = _destRect->y; m_vertexArray[4] = _destRect->x; m_vertexArray[5] = _destRect->y + _destRect->h; m_vertexArray[6] = _destRect->x + _destRect->w; m_vertexArray[7] = _destRect->y + _destRect->h; } else { m_vertexArray[0] = 0; m_vertexArray[1] = 0; m_vertexArray[2] = m_sdlScreen->m_sdlSurface->w; m_vertexArray[3] = 0; m_vertexArray[4] = 0; m_vertexArray[5] = m_sdlScreen->m_sdlSurface->h; m_vertexArray[6] = m_sdlScreen->m_sdlSurface->w; m_vertexArray[7] = m_sdlScreen->m_sdlSurface->h; } glDrawArrays ( GL_TRIANGLE_STRIP, 0, 4 ); ASSERT_OPENGL_ERRORS; return 0; } else { ARCReleaseAssert ( m_textures.valid ( _surfaceID ) ); OpenGLTexture *tex = m_textures.get ( _surfaceID ); ARCReleaseAssert ( tex != NULL ); int r = SDL_FillRect ( tex->m_sdlSurface, _destRect, _color ); tex->Damage (); return r; } }
int OpenGLGraphics::Blit ( Uint32 _sourceSurfaceID, SDL_Rect const *_sourceRect, Uint32 _destSurfaceID, SDL_Rect const *_destRect ) { ARCReleaseAssert ( m_sdlScreen != NULL ); OpenGLTexture *fromSurface = NULL; OpenGLTexture *toSurface = NULL; SDL_Rect *sourceRect = NULL; SDL_Rect *destRect = NULL; if ( _sourceSurfaceID == SCREEN_SURFACE_ID ) { // trying to blit from screen? // not at the moment, sadly return -1; } // Get the SDL surface for the source surface. ARCReleaseAssert ( m_textures.valid ( _sourceSurfaceID ) ); fromSurface = m_textures.get ( _sourceSurfaceID ); ARCReleaseAssert ( fromSurface != NULL ); // Get the SDL surface for the destination surface. if ( _destSurfaceID != SCREEN_SURFACE_ID ) { ARCReleaseAssert ( m_textures.valid ( _destSurfaceID ) ); toSurface = m_textures.get ( _destSurfaceID ); ARCReleaseAssert ( toSurface != NULL ); } else { toSurface = m_sdlScreen; } // With SDL, you can have a NULL destination rectangle if you are just // writing to 0,0 and the max possible WxH on the surface. SDL_Rect nullDestRect; if ( !_destRect ) { nullDestRect.x = 0; nullDestRect.y = 0; nullDestRect.w = m_sdlScreen->m_sdlSurface->w; nullDestRect.h = m_sdlScreen->m_sdlSurface->h; destRect = &nullDestRect; } else { memcpy ( &nullDestRect, _destRect, sizeof(SDL_Rect) ); destRect = &nullDestRect; } // With SDL, you can have a NULL source rectangle if you are just // reading from 0,0 and the max possible WxH on the surface. SDL_Rect nullSourceRect; if ( !_sourceRect ) { nullSourceRect.x = 0; nullSourceRect.y = 0; if ( g_openGL->GetSetting ( OPENGL_TEX_ALLOW_NPOT, false ) ) { nullSourceRect.w = fromSurface->m_sdlSurface->w; nullSourceRect.h = fromSurface->m_sdlSurface->h; } else { nullSourceRect.w = fromSurface->m_originalWidth; nullSourceRect.h = fromSurface->m_originalHeight; } sourceRect = &nullSourceRect; } else { memcpy ( &nullSourceRect, _sourceRect, sizeof(SDL_Rect) ); sourceRect = &nullSourceRect; } if ( destRect->x > toSurface->m_sdlSurface->w ) { // This blit is completely off the surface. return 1; } if ( destRect->y > toSurface->m_sdlSurface->h ) { // This blit is completely off the surface. return 1; } // Is this blit is going to be partially off the surface? if ( destRect->x + sourceRect->w > toSurface->m_sdlSurface->w ) sourceRect->w = toSurface->m_sdlSurface->w - destRect->x; if ( destRect->y + sourceRect->h > toSurface->m_sdlSurface->h ) sourceRect->h = toSurface->m_sdlSurface->h - destRect->y; // With SDL, you don't have to specify the dest width/height. With OpenGL, we do. destRect->w = sourceRect->w; destRect->h = sourceRect->h; // Now we need to do the actual blit! if ( _destSurfaceID == SCREEN_SURFACE_ID ) { fromSurface->Upload(); // draw from sourceSurfaceID g_openGL->ActivateTextureRect(); fromSurface->Bind(); g_openGL->ActivateWhiteWithAlpha ( fromSurface->m_alpha ); g_openGL->VertexArrayStateTexture (); short *vertexArray = m_vertexArray, *texCoordArrayi = m_texCoordArrayi; float *texCoordArrayf = m_texCoordArrayf; vertexArray = m_vertexArray; vertexArray[0] = destRect->x; vertexArray[1] = destRect->y; vertexArray[2] = destRect->x + destRect->w; vertexArray[3] = destRect->y; vertexArray[4] = destRect->x; vertexArray[5] = destRect->y + destRect->h; vertexArray[6] = destRect->x + destRect->w; vertexArray[7] = destRect->y + destRect->h; if ( g_openGL->GetSetting ( OPENGL_USE_TEXTURE_RECTANGLES, false ) ) { texCoordArrayi[0] = sourceRect->x; texCoordArrayi[1] = sourceRect->y; texCoordArrayi[2] = sourceRect->x + sourceRect->w; texCoordArrayi[3] = sourceRect->y; texCoordArrayi[4] = sourceRect->x; texCoordArrayi[5] = sourceRect->y + sourceRect->h; texCoordArrayi[6] = sourceRect->x + sourceRect->w; texCoordArrayi[7] = sourceRect->y + sourceRect->h; } else { float w = (float)fromSurface->m_sdlSurface->w, h = (float)fromSurface->m_sdlSurface->h; float x = (float)sourceRect->x, y = (float)sourceRect->y; texCoordArrayf[0] = x / w; texCoordArrayf[1] = y / h; texCoordArrayf[2] = x / w + (float)sourceRect->w / w; texCoordArrayf[3] = y / h; texCoordArrayf[4] = x / w; texCoordArrayf[5] = y / h + (float)sourceRect->h / h; texCoordArrayf[6] = x / w + (float)sourceRect->w / w; texCoordArrayf[7] = y / h + (float)sourceRect->h / h; } glDrawArrays ( GL_TRIANGLE_STRIP, 0, 4 ); ASSERT_OPENGL_ERRORS; return 0; } else { // This is a very hackish way to do it, but the alpha settings // aren't preserved across blits for some reason, so this is // necessary! // Fill with fully opaque colour key. //SDL_FillRect ( toSurface->m_sdlSurface, destRect, FULL_ALPHA | m_colorKey ); // Blit int res = SDL_BlitSurface ( fromSurface->m_sdlSurface, sourceRect, toSurface->m_sdlSurface, destRect ); // Replace the fully opaque colour key with a fully transparent // colour key. //ReplaceColour ( _destSurfaceID, destRect, FULL_ALPHA | m_colorKey, ZERO_ALPHA & m_colorKey ); // We want to upload the textures to graphics memory // later in order to make things fast. toSurface->Damage(); return res; } }
Uint32 OpenGLGraphics::LoadImage ( const char *_filename, bool _isColorKeyed ) { ARCReleaseAssert ( _filename != NULL ); // Load the image from RAM. SDL_Surface* src = g_app->m_resource->GetImage ( _filename ); // use SDL_Image to load the image ARCReleaseAssert ( src != NULL ); Uint32 oldWidth = 0, oldHeight = 0; Uint32 rmask, gmask, bmask, amask; #if SDL_BYTEORDER == SDL_BIG_ENDIAN rmask = 0xff000000; gmask = 0x00ff0000; bmask = 0x0000ff00; amask = 0x000000ff; #else rmask = 0x000000ff; gmask = 0x0000ff00; bmask = 0x00ff0000; amask = 0xff000000; #endif Uint32 targetW = src->w, targetH = src->h; if ( !g_openGL->GetSetting ( OPENGL_TEX_ALLOW_NPOT, false ) ) { oldWidth = targetW, oldHeight = targetH; if ( !isPowerOfTwo ( targetW ) ) targetW = nearestPowerOfTwo ( targetW ); if ( !isPowerOfTwo ( targetH ) ) targetH = nearestPowerOfTwo ( targetH ); ARCReleaseAssert ( isPowerOfTwo ( targetW * targetH ) ); } if ( g_openGL->GetSetting ( OPENGL_TEX_FORCE_SQUARE, false ) ) { targetH = targetW = std::max ( targetW, targetH ); } OpenGLTexture *tex = new OpenGLTexture(); Uint32 ret = m_textures.insert ( tex ); tex->Dispose(); tex->Create ( targetW, targetH, _isColorKeyed ); ARCReleaseAssert ( tex->m_sdlSurface != NULL ); if ( _isColorKeyed && m_colorKeySet ) { SDL_FillRect ( tex->m_sdlSurface, NULL, ZERO_ALPHA & m_colorKey ); SDL_SetColorKey ( tex->m_sdlSurface, SDL_SRCCOLORKEY | SDL_RLEACCEL, m_colorKey ); } SDL_SetAlpha ( tex->m_sdlSurface, 0, SDL_ALPHA_OPAQUE ); SDL_BlitSurface ( src, NULL, tex->m_sdlSurface, NULL ); SDL_FreeSurface ( src ); tex->Damage(); return ret; }