123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338 |
- /* GCSx
- ** OPENGL.CPP
- **
- ** Core OpenGL functions
- */
- /*****************************************************************************
- ** Copyright (C) 2003-2006 Janson
- **
- ** 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 2 of the License, 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., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
- *****************************************************************************/
- #include "all.h"
- int alphaOn = 0;
- int blendOn = 0;
- void oglInit(int width, int height) { start_func
- oglError("oglInit: selectVideoMode");
- oglDebug(glViewport(0, 0, width, height));
- oglDebug(glClearColor(0.0f, 0.0f, 0.0f, 0.0f));
- oglDebug(glEnable(GL_TEXTURE_2D));
- oglDebug(glDisable(GL_DEPTH_TEST));
- oglDebug(glAlphaFunc(GL_GREATER, 0));
- oglDebug(glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA));
- oglDebug(glDisable(GL_ALPHA_TEST));
- oglDebug(glDisable(GL_BLEND));
- alphaOn = 0;
- blendOn = 0;
- // May change later
- oglDebug(glShadeModel(GL_SMOOTH));
- // Change to modulate to allow coloring
- oglDebug(glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE));
- oglDebug(glMatrixMode(GL_PROJECTION));
- oglDebug(glLoadIdentity());
- oglDebug(glOrtho(0, width, height, 0, 0, 1));
- oglDebug(glMatrixMode(GL_MODELVIEW));
- oglError("oglInit");
-
- // Some places optimize output and need to reset when GL is initialized
- TextureMap::setupOptimizations();
- }
- void oglAlphaMode(int transparency, int fullAlpha) { start_func
- if (fullAlpha) {
- if (!blendOn) {
- oglDebug(glEnable(GL_BLEND));
- blendOn = 1;
- }
- }
- else {
- if (blendOn) {
- oglDebug(glDisable(GL_BLEND));
- blendOn = 0;
- }
- }
- if ((transparency) && (!fullAlpha)) {
- if (!alphaOn) {
- oglDebug(glEnable(GL_ALPHA_TEST));
- alphaOn = 1;
- }
- }
- else {
- if (alphaOn) {
- oglDebug(glDisable(GL_ALPHA_TEST));
- alphaOn = 0;
- }
- }
- }
- int oglTestPossibleTextures(int width, int height, int withAlpha, int limit) { start_func
- // Test data-
- Uint8* testdata = new Uint8[width * height * (withAlpha ? 4 : 3)];
- Uint8* writeTo = testdata;
- for (int pos = width * height * (withAlpha ? 4 : 3); pos > 0; --pos)
- *writeTo++ = rand();
- // Limit to 8 seconds
- long long ticks = SDL_GetTicks();
- int time;
- // Add texture storage in powers of 2
- int allocSize = 64;
- GLuint* textures = new GLuint[allocSize];
- GLboolean* residencies = new GLboolean[allocSize];
- // Add textures 8 at a time
- int pos = 0;
- int found = 0;
- GLint getData;
- while (pos <= limit) {
- // Allocate more space?
- if (pos >= allocSize) {
- GLuint* newTextures = new GLuint[allocSize * 2];
- GLboolean* newResidencies = new GLboolean[allocSize * 2];
- memcpy(newTextures, textures, sizeof(GLuint[allocSize]));
- memcpy(newResidencies, residencies, sizeof(GLboolean[allocSize]));
- delete[] textures;
- delete[] residencies;
- textures = newTextures;
- residencies = newResidencies;
- allocSize *= 2;
- }
- // Create new texture
- oglDebug(glGenTextures(8, textures + pos));
- for (int subpos = 0; subpos < 8; ++subpos) {
- oglDebug(glBindTexture(GL_TEXTURE_2D, textures[pos]));
- oglDebug(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST));
- oglDebug(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST));
- residencies[pos] = GL_TRUE;
- oglDebug(glTexImage2D(GL_TEXTURE_2D, 0, withAlpha ? GL_RGBA : GL_RGB, width, height, 0,
- withAlpha ? GL_RGBA : GL_RGB, GL_UNSIGNED_BYTE, testdata));
- // Verify storage
- oglDebug(glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &getData));
- if (getData != width) {
- found = 1;
- break;
- }
- // Draw with texture
- glBegin(GL_QUADS);
- glTexCoord2f(0.0, 0.0); glVertex3i(0, 0, 0);
- glTexCoord2f(1.0, 0.0); glVertex3i(width, 0, 0);
- glTexCoord2f(1.0, 1.0); glVertex3i(width, height, 0);
- glTexCoord2f(0.0, 1.0); glVertex3i(0, height, 0);
- oglDebug(glEnd());
- ++pos;
- }
- if (found) break;
- // Verify residency of ALL textures
- if (glAreTexturesResident(pos, textures, residencies) == GL_FALSE) {
- found = 1;
- break;
- }
-
- if (SDL_GetTicks() - ticks > 8000) {
- time = 1;
- break;
- }
- }
- oglDebug(glDeleteTextures(pos, textures));
- delete[] textures;
- delete[] residencies;
- delete[] testdata;
- oglError("oglTestPossibleTextures");
-
- if (found) {
- if (withAlpha) {
- debugWrite("Maximum %dx%d RGBA textures resident: %d", width, height, pos - 8);
- }
- else {
- debugWrite("Maximum %dx%d RGB textures resident: %d", width, height, pos - 8);
- }
- return pos - 1;
- }
- else {
- if (withAlpha) {
- debugWrite("Maximum %dx%d RGBA textures resident: over %d", width, height, pos - 8);
- }
- else {
- debugWrite("Maximum %dx%d RGB textures resident: over %d", width, height, pos - 8);
- }
- if (time) {
- debugWrite("(test aborted due to time)");
- }
- return -1;
- }
- }
- void oglTestCapabilities() { start_func
- GLint result;
- // Reported capabilities
- oglDebug(glGetIntegerv(GL_DOUBLEBUFFER, &result));
- if (result == GL_TRUE) {
- debugWrite(DEBUG_VIDEO, "Double-buffering: Supported");
- }
- else {
- debugWrite(DEBUG_VIDEO, "Double-buffering: Not supported");
- }
- oglDebug(glGetIntegerv(GL_MAX_TEXTURE_SIZE, &result));
- debugWrite(DEBUG_VIDEO, "Stated max texture size: %d", result);
- int maxSize = result;
- int minSize = 1;
- // Report on min/max sizes
- int size;
- for (int withAlpha = 0; withAlpha <= 1; ++withAlpha) {
- int found = 0;
- for (size = 64; size >= 1; size /= 2) {
- oglDebug(glTexImage2D(GL_PROXY_TEXTURE_2D, 0, withAlpha ? GL_RGBA : GL_RGB, size, size, 0,
- withAlpha ? GL_RGBA : GL_RGB, GL_UNSIGNED_BYTE, NULL));
- // Verify storage
- oglDebug(glGetTexLevelParameteriv(GL_PROXY_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &result));
- if (result != size) {
- found = 1;
- break;
- }
- oglDebug(glGetTexLevelParameteriv(GL_PROXY_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &result));
- if (result != size) {
- found = 1;
- break;
- }
- }
- if (found) size *= 2;
- else size = 1;
- if (withAlpha) {
- debugWrite(DEBUG_VIDEO, "Min texture size with alpha: %d", size);
- }
- else {
- debugWrite(DEBUG_VIDEO, "Min texture size, no alpha: %d", size);
- }
- if (size > minSize) minSize = size;
- found = 0;
- for (size = 64; size <= 65536; size *= 2) {
- oglDebug(glTexImage2D(GL_PROXY_TEXTURE_2D, 0, withAlpha ? GL_RGBA : GL_RGB, size, size, 0,
- withAlpha ? GL_RGBA : GL_RGB, GL_UNSIGNED_BYTE, NULL));
- // Verify storage
- oglDebug(glGetTexLevelParameteriv(GL_PROXY_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &result));
- if (result != size) {
- found = 1;
- break;
- }
- oglDebug(glGetTexLevelParameteriv(GL_PROXY_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &result));
- if (result != size) {
- found = 1;
- break;
- }
- }
- if (found) {
- size /= 2;
- if (withAlpha) {
- debugWrite(DEBUG_VIDEO, "Max texture size with alpha: %d", size);
- }
- else {
- debugWrite(DEBUG_VIDEO, "Max texture size, no alpha: %d", size);
- }
- }
- else {
- if (withAlpha) {
- debugWrite(DEBUG_VIDEO, "Max texture size with alpha: over 65536");
- }
- else {
- debugWrite(DEBUG_VIDEO, "Max texture size, no alpha: over 65536");
- }
- }
- // Track min between the three
- if (size < maxSize) maxSize = size;
- }
-
- // Attempt non-square texture
- oglDebug(glTexImage2D(GL_PROXY_TEXTURE_2D, 0, GL_RGBA, maxSize,
- maxSize / 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL));
- // Clear error status (an error is expected here)
- while (glGetError()) ;
- // Verify storage
- oglDebug(glGetTexLevelParameteriv(GL_PROXY_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &result));
- if (result == maxSize) {
- oglDebug(glGetTexLevelParameteriv(GL_PROXY_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &result));
- if (result == maxSize / 2) {
- debugWrite(DEBUG_VIDEO, "Non-square textures: Supported");
- }
- else {
- debugWrite(DEBUG_VIDEO, "Non-square textures: Not supported");
- }
- }
- else {
- debugWrite(DEBUG_VIDEO, "Non-square textures: Not supported");
- }
-
- // Attempt non-^2 texture
- glTexImage2D(GL_PROXY_TEXTURE_2D, 0, GL_RGBA, 100, 100, 0,
- GL_RGBA, GL_UNSIGNED_BYTE, NULL);
- // Clear error status (an error is expected here)
- while (glGetError()) ;
- // Verify storage
- oglDebug(glGetTexLevelParameteriv(GL_PROXY_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &result));
- oglError("oglTestCapabilities");
- if (result == 100) {
- debugWrite(DEBUG_VIDEO, "Non-^2 textures: Supported");
- }
- else {
- debugWrite(DEBUG_VIDEO, "Non-^2 textures: Not supported");
- }
- // Always force ^2 textures as some cards support non-^2 textures but VERY SLOWLY
- config->write(OGL_POWER_OF_TWO, 1);
- config->write(OGL_MIN_SIZE, minSize);
- config->write(OGL_MAX_SIZE, maxSize);
- }
- void oglError(const char* note) { start_func
- const char* errStr;
- while (GLenum err = glGetError()) {
- switch (err) {
- case GL_INVALID_ENUM:
- errStr = "Invalid Enum";
- break;
- case GL_INVALID_VALUE:
- errStr = "Invalid Value";
- break;
- case GL_INVALID_OPERATION:
- errStr = "Invalid Operation";
- break;
- case GL_STACK_OVERFLOW:
- errStr = "Stack Overflow";
- break;
- case GL_STACK_UNDERFLOW:
- errStr = "Stack Underflow";
- break;
- case GL_OUT_OF_MEMORY:
- errStr = "Out of Memory";
- break;
- }
- debugWrite(DEBUG_VIDEO, "%s: GL Error: %s", note, errStr);
- }
- }
|