ResidualVM logo ResidualVM website - Forums - Contact us BuildBot - Doxygen - Wiki curved edge

gfx_opengl_texture.cpp

Go to the documentation of this file.
00001 /* ResidualVM - A 3D game interpreter
00002  *
00003  * ResidualVM is the legal property of its developers, whose names
00004  * are too numerous to list here. Please refer to the AUTHORS
00005  * file distributed with this source distribution.
00006  *
00007  * This program is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU General Public License
00009  * as published by the Free Software Foundation; either version 2
00010  * of the License, or (at your option) any later version.
00011  *
00012  * This program is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015  * GNU General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU General Public License
00018  * along with this program; if not, write to the Free Software
00019  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00020  *
00021  */
00022 
00023 #include "common/scummsys.h"
00024 
00025 #if defined(USE_OPENGL) || defined(USE_GLES2) || defined(USE_OPENGL_SHADERS)
00026 
00027 #include "engines/myst3/gfx_opengl_texture.h"
00028 
00029 #include "graphics/opengl/context.h"
00030 
00031 namespace Myst3 {
00032 
00033 // From Bit Twiddling Hacks
00034 static uint32 upperPowerOfTwo(uint32 v) {
00035     v--;
00036     v |= v >> 1;
00037     v |= v >> 2;
00038     v |= v >> 4;
00039     v |= v >> 8;
00040     v |= v >> 16;
00041     v++;
00042     return v;
00043 }
00044 
00045 OpenGLTexture::OpenGLTexture() :
00046         internalFormat(0),
00047         sourceFormat(0),
00048         internalWidth(0),
00049         internalHeight(0),
00050         upsideDown(false) {
00051     glGenTextures(1, &id);
00052 }
00053 
00054 OpenGLTexture::OpenGLTexture(const Graphics::Surface *surface) {
00055     width = surface->w;
00056     height = surface->h;
00057     format = surface->format;
00058     upsideDown = false;
00059 
00060     // Pad the textures if non power of two support is unavailable
00061     if (OpenGLContext.NPOTSupported) {
00062         internalHeight = height;
00063         internalWidth = width;
00064     } else {
00065         internalHeight = upperPowerOfTwo(height);
00066         internalWidth = upperPowerOfTwo(width);
00067     }
00068 
00069     if (format.bytesPerPixel == 4) {
00070         assert(surface->format == getRGBAPixelFormat());
00071 
00072         internalFormat = GL_RGBA;
00073         sourceFormat = GL_UNSIGNED_BYTE;
00074     } else if (format.bytesPerPixel == 2) {
00075         internalFormat = GL_RGB;
00076         sourceFormat = GL_UNSIGNED_SHORT_5_6_5;
00077     } else
00078         error("Unknown pixel format");
00079 
00080     glGenTextures(1, &id);
00081     glBindTexture(GL_TEXTURE_2D, id);
00082     glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, internalWidth, internalHeight, 0, internalFormat, sourceFormat, 0);
00083     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
00084     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
00085 
00086     // TODO: If non power of two textures are unavailable this clamping
00087     // has no effect on the padded sides (resulting in white lines on the edges)
00088     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
00089     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
00090 
00091     update(surface);
00092 
00093 }
00094 
00095 OpenGLTexture::~OpenGLTexture() {
00096     glDeleteTextures(1, &id);
00097 }
00098 
00099 void OpenGLTexture::update(const Graphics::Surface *surface) {
00100     updatePartial(surface, Common::Rect(surface->w, surface->h));
00101 }
00102 
00103 void OpenGLTexture::updateTexture(const Graphics::Surface *surface, const Common::Rect &rect) {
00104     assert(surface->format == format);
00105 
00106     glBindTexture(GL_TEXTURE_2D, id);
00107 
00108     if (OpenGLContext.unpackSubImageSupported) {
00109         const Graphics::Surface subArea = surface->getSubArea(rect);
00110 
00111         glPixelStorei(GL_UNPACK_ROW_LENGTH, surface->pitch / surface->format.bytesPerPixel);
00112         glTexSubImage2D(GL_TEXTURE_2D, 0, rect.left, rect.top, subArea.w, subArea.h, internalFormat, sourceFormat, subArea.getPixels());
00113         glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
00114     } else {
00115         // GL_UNPACK_ROW_LENGTH is not supported, don't bother and do a full texture update
00116         glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, surface->w, surface->h, internalFormat, sourceFormat, surface->getPixels());
00117     }
00118 }
00119 
00120 void OpenGLTexture::updatePartial(const Graphics::Surface *surface, const Common::Rect &rect) {
00121     updateTexture(surface, rect);
00122 }
00123 
00124 void OpenGLTexture::copyFromFramebuffer(const Common::Rect &screen) {
00125     internalFormat = GL_RGB;
00126     width  = screen.width();
00127     height = screen.height();
00128     upsideDown = true;
00129 
00130     // Pad the textures if non power of two support is unavailable
00131     if (OpenGLContext.NPOTSupported) {
00132         internalHeight = height;
00133         internalWidth = width;
00134     } else {
00135         internalHeight = upperPowerOfTwo(height);
00136         internalWidth = upperPowerOfTwo(width);
00137     }
00138 
00139     glBindTexture(GL_TEXTURE_2D, id);
00140     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
00141     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
00142 
00143     glCopyTexImage2D(GL_TEXTURE_2D, 0, internalFormat, screen.left, screen.top, internalWidth, internalHeight, 0);
00144 }
00145 
00146 } // End of namespace Myst3
00147 
00148 #endif


Generated on Sat Aug 1 2020 05:01:20 for ResidualVM by doxygen 1.7.1
curved edge   curved edge