mirror of https://github.com/odrling/Aegisub
Tweak how the OpenGL 1.1 code behaves slightly; distortion with Windows 7's OpenGL emulation is now at most .1% instead of at most 2%.
Originally committed to SVN as r3723.
This commit is contained in:
parent
5b9da0c56a
commit
5404b45017
|
@ -53,6 +53,7 @@
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
#include "video_frame.h"
|
#include "video_frame.h"
|
||||||
|
|
||||||
|
// Windows only has headers for OpenGL 1.1 and GL_CLAMP_TO_EDGE is 1.2
|
||||||
#ifndef GL_CLAMP_TO_EDGE
|
#ifndef GL_CLAMP_TO_EDGE
|
||||||
#define GL_CLAMP_TO_EDGE 0x812F
|
#define GL_CLAMP_TO_EDGE 0x812F
|
||||||
#endif
|
#endif
|
||||||
|
@ -66,12 +67,19 @@ namespace {
|
||||||
int dataOffset;
|
int dataOffset;
|
||||||
int sourceH;
|
int sourceH;
|
||||||
int sourceW;
|
int sourceW;
|
||||||
|
|
||||||
|
int textureH;
|
||||||
|
int textureW;
|
||||||
|
|
||||||
float destH;
|
float destH;
|
||||||
float destW;
|
float destW;
|
||||||
float destX;
|
float destX;
|
||||||
float destY;
|
float destY;
|
||||||
float texH;
|
|
||||||
float texW;
|
float texTop;
|
||||||
|
float texBottom;
|
||||||
|
float texLeft;
|
||||||
|
float texRight;
|
||||||
};
|
};
|
||||||
/// @brief Test if a texture can be created
|
/// @brief Test if a texture can be created
|
||||||
/// @param width The width of the texture
|
/// @param width The width of the texture
|
||||||
|
@ -94,6 +102,7 @@ namespace {
|
||||||
VideoOutGL::VideoOutGL()
|
VideoOutGL::VideoOutGL()
|
||||||
: maxTextureSize(0),
|
: maxTextureSize(0),
|
||||||
supportsRectangularTextures(false),
|
supportsRectangularTextures(false),
|
||||||
|
supportsGlClampToEdge(false),
|
||||||
internalFormat(0),
|
internalFormat(0),
|
||||||
frameWidth(0),
|
frameWidth(0),
|
||||||
frameHeight(0),
|
frameHeight(0),
|
||||||
|
@ -102,10 +111,40 @@ VideoOutGL::VideoOutGL()
|
||||||
textureList(),
|
textureList(),
|
||||||
textureCount(0),
|
textureCount(0),
|
||||||
textureRows(0),
|
textureRows(0),
|
||||||
textureCols(0),
|
textureCols(0)
|
||||||
openGL11(false)
|
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
|
/// @brief Runtime detection of required OpenGL capabilities
|
||||||
|
void VideoOutGL::DetectOpenGLCapabilities() {
|
||||||
|
if (maxTextureSize != 0) return;
|
||||||
|
|
||||||
|
// Test for supported internalformats
|
||||||
|
if (TestTexture(64, 64, GL_RGBA8)) internalFormat = GL_RGBA8;
|
||||||
|
else if (TestTexture(64, 64, GL_RGBA)) internalFormat = GL_RGBA;
|
||||||
|
else throw VideoOutUnsupportedException(L"Could not create a 64x64 RGB texture in any format.");
|
||||||
|
|
||||||
|
// Test for the maximum supported texture size
|
||||||
|
glGetIntegerv(GL_MAX_TEXTURE_SIZE, &maxTextureSize);
|
||||||
|
while (maxTextureSize > 64 && !TestTexture(maxTextureSize, maxTextureSize, internalFormat)) maxTextureSize >>= 1;
|
||||||
|
wxLogDebug("VideoOutGL::DetectOpenGLCapabilities: Maximum texture size is %dx%d\n", maxTextureSize, maxTextureSize);
|
||||||
|
|
||||||
|
// Test for rectangular texture support
|
||||||
|
supportsRectangularTextures = TestTexture(maxTextureSize, maxTextureSize >> 1, internalFormat);
|
||||||
|
|
||||||
|
// Test GL_CLAMP_TO_EDGE support
|
||||||
|
GLuint texture;
|
||||||
|
glGenTextures(1, &texture);
|
||||||
|
glTexImage2D(GL_PROXY_TEXTURE_2D, 0, GL_RGBA8, 64, 64, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||||
|
if (glGetError()) {
|
||||||
|
supportsGlClampToEdge = false;
|
||||||
|
wxLogDebug("VideoOutGL::DetectOpenGLCapabilities: Using GL_CLAMP\n");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
supportsGlClampToEdge = true;
|
||||||
|
wxLogDebug("VideoOutGL::DetectOpenGLCapabilities: Using GL_CLAMP_TO_EDGE\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// @brief If needed, create the grid of textures for displaying frames of the given format
|
/// @brief If needed, create the grid of textures for displaying frames of the given format
|
||||||
/// @param width The frame's width
|
/// @param width The frame's width
|
||||||
|
@ -117,25 +156,7 @@ void VideoOutGL::InitTextures(int width, int height, GLenum format, int bpp) {
|
||||||
if (width == frameWidth && height == frameHeight && format == frameFormat) return;
|
if (width == frameWidth && height == frameHeight && format == frameFormat) return;
|
||||||
wxLogDebug("VideoOutGL::InitTextures: Video size: %dx%d\n", width, height);
|
wxLogDebug("VideoOutGL::InitTextures: Video size: %dx%d\n", width, height);
|
||||||
|
|
||||||
// If nessesary, detect what the user's OpenGL supports
|
DetectOpenGLCapabilities();
|
||||||
if (maxTextureSize == 0) {
|
|
||||||
// Test for supported internalformats
|
|
||||||
if (TestTexture(64, 64, GL_RGBA8)) internalFormat = GL_RGBA8;
|
|
||||||
else if (TestTexture(64, 64, GL_RGBA)) internalFormat = GL_RGBA;
|
|
||||||
else throw VideoOutUnsupportedException(L"Could not create a 64x64 RGB texture in any format.");
|
|
||||||
|
|
||||||
// Test for the maximum supported texture size
|
|
||||||
glGetIntegerv(GL_MAX_TEXTURE_SIZE, &maxTextureSize);
|
|
||||||
while (maxTextureSize > 64 && !TestTexture(maxTextureSize, maxTextureSize, internalFormat)) maxTextureSize >>= 1;
|
|
||||||
|
|
||||||
// Test for rectangular texture support
|
|
||||||
supportsRectangularTextures = TestTexture(maxTextureSize, maxTextureSize >> 1, internalFormat);
|
|
||||||
|
|
||||||
// Check OpenGL version
|
|
||||||
if (strncmp((const char *)glGetString(GL_VERSION), "1.1", 3) == 0) {
|
|
||||||
openGL11 = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Clean up old textures
|
// Clean up old textures
|
||||||
if (textureIdList.size() > 0) {
|
if (textureIdList.size() > 0) {
|
||||||
|
@ -145,6 +166,7 @@ void VideoOutGL::InitTextures(int width, int height, GLenum format, int bpp) {
|
||||||
textureList.clear();
|
textureList.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Create the textures
|
||||||
textureRows = (int)ceil(double(height) / maxTextureSize);
|
textureRows = (int)ceil(double(height) / maxTextureSize);
|
||||||
textureCols = (int)ceil(double(width) / maxTextureSize);
|
textureCols = (int)ceil(double(width) / maxTextureSize);
|
||||||
textureIdList.resize(textureRows * textureCols);
|
textureIdList.resize(textureRows * textureCols);
|
||||||
|
@ -185,9 +207,20 @@ void VideoOutGL::InitTextures(int width, int height, GLenum format, int bpp) {
|
||||||
int w = textureW;
|
int w = textureW;
|
||||||
int h = textureH;
|
int h = textureH;
|
||||||
if (!supportsRectangularTextures) w = h = MAX(w, h);
|
if (!supportsRectangularTextures) w = h = MAX(w, h);
|
||||||
|
|
||||||
|
if (supportsGlClampToEdge) {
|
||||||
|
ti.texLeft = 0.0f;
|
||||||
|
ti.texTop = 0.0f;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// Stretch the texture a half pixel in each direction to eliminate the border
|
||||||
|
ti.texLeft = 1.0f / (2 * w);
|
||||||
|
ti.texTop = 1.0f / (2 * h);
|
||||||
|
}
|
||||||
|
|
||||||
// Calculate what percent of the texture is actually used
|
// Calculate what percent of the texture is actually used
|
||||||
ti.texW = float(ti.sourceW) / w;
|
ti.texRight = float(ti.sourceW) / w - ti.texLeft;
|
||||||
ti.texH = float(ti.sourceH) / h;
|
ti.texBottom = float(ti.sourceH) / h - ti.texTop;
|
||||||
|
|
||||||
// destW/H is the percent of the output which this texture covers
|
// destW/H is the percent of the output which this texture covers
|
||||||
ti.destW = float(w) / width;
|
ti.destW = float(w) / width;
|
||||||
|
@ -207,8 +240,7 @@ void VideoOutGL::InitTextures(int width, int height, GLenum format, int bpp) {
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||||
if (GLenum err = glGetError()) throw VideoOutOpenGLException(L"glTexParameteri(GL_TEXTURE_MAG_FILTER)", err);
|
if (GLenum err = glGetError()) throw VideoOutOpenGLException(L"glTexParameteri(GL_TEXTURE_MAG_FILTER)", err);
|
||||||
|
|
||||||
// GL_CLAMP_TO_EDGE was added in OpenGL 1.2, and W7's emulation only supports 1.1
|
GLint mode = supportsGlClampToEdge ? GL_CLAMP_TO_EDGE : GL_CLAMP;
|
||||||
GLint mode = openGL11 ? GL_REPEAT : GL_CLAMP_TO_EDGE;
|
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, mode);
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, mode);
|
||||||
if (GLenum err = glGetError()) throw VideoOutOpenGLException(L"glTexParameteri(GL_TEXTURE_WRAP_S)", err);
|
if (GLenum err = glGetError()) throw VideoOutOpenGLException(L"glTexParameteri(GL_TEXTURE_WRAP_S)", err);
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, mode);
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, mode);
|
||||||
|
@ -221,6 +253,7 @@ void VideoOutGL::InitTextures(int width, int height, GLenum format, int bpp) {
|
||||||
sourceY += sourceH;
|
sourceY += sourceH;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Store the information needed to know when the grid must be recreated
|
||||||
frameWidth = width;
|
frameWidth = width;
|
||||||
frameHeight = height;
|
frameHeight = height;
|
||||||
frameFormat = format;
|
frameFormat = format;
|
||||||
|
@ -249,33 +282,28 @@ void VideoOutGL::DisplayFrame(AegiVideoFrame frame, int sw, int sh) {
|
||||||
|
|
||||||
glBindTexture(GL_TEXTURE_2D, ti.textureID);
|
glBindTexture(GL_TEXTURE_2D, ti.textureID);
|
||||||
if (GLenum err = glGetError()) throw VideoOutOpenGLException(L"glBindTexture", err);
|
if (GLenum err = glGetError()) throw VideoOutOpenGLException(L"glBindTexture", err);
|
||||||
|
|
||||||
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, ti.sourceW, ti.sourceH, format, GL_UNSIGNED_BYTE, frame.data[0] + ti.dataOffset);
|
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, ti.sourceW, ti.sourceH, format, GL_UNSIGNED_BYTE, frame.data[0] + ti.dataOffset);
|
||||||
if (GLenum err = glGetError()) throw VideoOutOpenGLException(L"glTexSubImage2D", err);
|
if (GLenum err = glGetError()) throw VideoOutOpenGLException(L"glTexSubImage2D", err);
|
||||||
|
|
||||||
glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
|
glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
|
||||||
if (GLenum err = glGetError()) throw VideoOutOpenGLException(L"glColor4f", err);
|
if (GLenum err = glGetError()) throw VideoOutOpenGLException(L"glColor4f", err);
|
||||||
float top = 0.0f;
|
|
||||||
float bottom = ti.texH;
|
|
||||||
float left = 0.0f;
|
|
||||||
float right = 1.0f;
|
|
||||||
|
|
||||||
// Slightly stretch the texture under opengl 1.1 to make up for the lack of GL_CLAMP_TO_EDGE
|
float top, bottom;
|
||||||
if (openGL11) {
|
|
||||||
top = 0.01f;
|
|
||||||
bottom -= 0.01f;
|
|
||||||
left = 0.01f;
|
|
||||||
right -= 0.01f;
|
|
||||||
}
|
|
||||||
if (frame.flipped) {
|
if (frame.flipped) {
|
||||||
float t = top;
|
top = ti.texBottom;
|
||||||
top = bottom;
|
bottom = ti.texTop;
|
||||||
bottom = t;
|
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
top = ti.texTop;
|
||||||
|
bottom = ti.texBottom;
|
||||||
|
}
|
||||||
|
|
||||||
glBegin(GL_QUADS);
|
glBegin(GL_QUADS);
|
||||||
glTexCoord2f(left, top); glVertex2f(destX, destY);
|
glTexCoord2f(ti.texLeft, top); glVertex2f(destX, destY);
|
||||||
glTexCoord2f(right, top); glVertex2f(destX + destW, destY);
|
glTexCoord2f(ti.texRight, top); glVertex2f(destX + destW, destY);
|
||||||
glTexCoord2f(right, bottom); glVertex2f(destX + destW, destY + destH);
|
glTexCoord2f(ti.texRight, bottom); glVertex2f(destX + destW, destY + destH);
|
||||||
glTexCoord2f(left, bottom); glVertex2f(destX, destY + destH);
|
glTexCoord2f(ti.texLeft, bottom); glVertex2f(destX, destY + destH);
|
||||||
glEnd();
|
glEnd();
|
||||||
if (GLenum err = glGetError()) throw VideoOutOpenGLException(L"GL_QUADS", err);
|
if (GLenum err = glGetError()) throw VideoOutOpenGLException(L"GL_QUADS", err);
|
||||||
}
|
}
|
||||||
|
|
|
@ -53,8 +53,11 @@ private:
|
||||||
int maxTextureSize;
|
int maxTextureSize;
|
||||||
/// Whether rectangular textures are supported by the user's graphics card
|
/// Whether rectangular textures are supported by the user's graphics card
|
||||||
bool supportsRectangularTextures;
|
bool supportsRectangularTextures;
|
||||||
|
/// Whether GL_CLAMP_TO_EDGE is supported by the user's drivers
|
||||||
|
bool supportsGlClampToEdge;
|
||||||
/// The internalformat to use
|
/// The internalformat to use
|
||||||
int internalFormat;
|
int internalFormat;
|
||||||
|
|
||||||
/// The frame height which the texture grid has been set up for
|
/// The frame height which the texture grid has been set up for
|
||||||
int frameWidth;
|
int frameWidth;
|
||||||
/// The frame width which the texture grid has been set up for
|
/// The frame width which the texture grid has been set up for
|
||||||
|
@ -72,8 +75,7 @@ private:
|
||||||
/// The number of columns of textures
|
/// The number of columns of textures
|
||||||
int textureCols;
|
int textureCols;
|
||||||
|
|
||||||
bool openGL11;
|
void DetectOpenGLCapabilities();
|
||||||
|
|
||||||
void InitTextures(int width, int height, GLenum format, int bpp);
|
void InitTextures(int width, int height, GLenum format, int bpp);
|
||||||
|
|
||||||
VideoOutGL(const VideoOutGL &);
|
VideoOutGL(const VideoOutGL &);
|
||||||
|
|
Loading…
Reference in New Issue