📄 opengl.h
字号:
/* * Copyright (C) 2005-2008 gulikoza * * 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-1307, USA. *//* $Id$ */#ifndef OPENGL_H#define OPENGL_H#if (C_OPENGL)#define MODULE "OpenGL"#include "SDL_opengl.h"static const char *FShader = "uniform sampler2DRect ytex;\n" "uniform sampler2DRect utex, vtex;\n" "void main(void) {\n" " float nx, ny, r, g, b, y, u, v;\n" " vec4 txl, ux, vx;" " nx = gl_TexCoord[0].x;\n" " ny = gl_TexCoord[0].y;\n" " y = texture2DRect(ytex, vec2(nx, ny)).r;\n" " u = texture2DRect(utex, vec2(nx/2.0, ny/2.0)).r;\n" " v = texture2DRect(vtex, vec2(nx/2.0, ny/2.0)).r;\n" " y = 1.1643 * (y - 0.0625);\n" " u = u - 0.5;\n" " v = v - 0.5;\n" " r = y + 1.5958 * v;\n" " g = y - 0.39173 * u - 0.81290 * v;\n" " b = y + 2.017 * u;\n" " gl_FragColor = vec4(r, g, b, 1.0);\n" "}\n";class OpenGL : public Output {private: GLuint texobj[3]; unsigned char *texdata; unsigned short texwidth, texheight; GLhandleARB fs, p; GLuint displaylist, PBObuffer; SDL_Rect display; PFNGLACTIVETEXTUREARBPROC pglActiveTextureARB; PFNGLBINDBUFFERARBPROC pglBindBufferARB; PFNGLMAPBUFFERARBPROC pglMapBufferARB; PFNGLUNMAPBUFFERARBPROC pglUnmapBufferARB; void PrintShaderLog(GLhandleARB obj) { char * log; int l = 0, w = 0; PFNGLGETOBJECTPARAMETERIVARBPROC pglGetObjectParameterivARB; PFNGLGETINFOLOGARBPROC pglGetInfoLogARB; pglGetObjectParameterivARB = (PFNGLGETOBJECTPARAMETERIVARBPROC)SDL_GL_GetProcAddress("glGetObjectParameterivARB"); pglGetInfoLogARB = (PFNGLGETINFOLOGARBPROC)SDL_GL_GetProcAddress("glGetInfoLogARB"); pglGetObjectParameterivARB(obj, GL_OBJECT_INFO_LOG_LENGTH_ARB, &l); if(l > 0) { log = (char *)malloc(sizeof(char)*l); pglGetInfoLogARB(obj, l, &w, log); ERROR_MSG("%s", ((*log)==' ') ? log+1 : log); free(log); } }protected:public: OpenGL():texdata(NULL),fs(0),p(0),displaylist(0),PBObuffer(0), pglActiveTextureARB(NULL),pglBindBufferARB(NULL),pglMapBufferARB(NULL),pglUnmapBufferARB(NULL) { texobj[0] = texobj[1] = texobj[2] = 0; ERROR_MSG("Created " MODULE " object"); } ~OpenGL() { Free(); ERROR_MSG("Destroyed " MODULE " object"); } int Create(int w, int h, Uint32 f, SDL_Surface * s) { GLint res; // Function pointers PFNGLUNIFORM1IARBPROC pglUniform1iARB = NULL; PFNGLGETUNIFORMLOCATIONARBPROC pglGetUniformLocationARB = NULL; PFNGLCREATESHADEROBJECTARBPROC pglCreateShaderObjectARB = NULL; PFNGLCREATEPROGRAMOBJECTARBPROC pglCreateProgramObjectARB = NULL; PFNGLSHADERSOURCEARBPROC pglShaderSourceARB = NULL; PFNGLCOMPILESHADERARBPROC pglCompileShaderARB = NULL; PFNGLATTACHOBJECTARBPROC pglAttachObjectARB = NULL; PFNGLLINKPROGRAMARBPROC pglLinkProgramARB = NULL; PFNGLUSEPROGRAMOBJECTARBPROC pglUseProgramObjectARB = NULL; PFNGLGETOBJECTPARAMETERIVARBPROC pglGetObjectParameterivARB = NULL; PFNGLGENBUFFERSARBPROC pglGenBuffersARB = NULL; PFNGLBUFFERDATAARBPROC pglBufferDataARB = NULL; if((s == NULL) || (s->flags&SDL_OPENGL != SDL_OPENGL)) { ERROR_MSG("Could not get OpenGL surface!"); return -1; }#if (SDL_IS_PATCHED) // If SDL is not patched, then OpenGL will fail to initialize SDL_GL_MakeCurrent(0);#endif // Need multitexturing and ARB_fragment_shader support const char *c = (const char*)glGetString(GL_EXTENSIONS); if(c && (strstr(c, "ARB_fragment_shader")) && (strstr(c, "ARB_multitexture"))) { pglActiveTextureARB = (PFNGLACTIVETEXTUREARBPROC)SDL_GL_GetProcAddress("glActiveTextureARB"); pglUniform1iARB = (PFNGLUNIFORM1IARBPROC)SDL_GL_GetProcAddress("glUniform1iARB"); pglGetUniformLocationARB = (PFNGLGETUNIFORMLOCATIONARBPROC)SDL_GL_GetProcAddress("glGetUniformLocationARB"); pglShaderSourceARB = (PFNGLSHADERSOURCEARBPROC)SDL_GL_GetProcAddress("glShaderSourceARB"); pglCompileShaderARB = (PFNGLCOMPILESHADERARBPROC)SDL_GL_GetProcAddress("glCompileShaderARB"); pglCreateShaderObjectARB = (PFNGLCREATESHADEROBJECTARBPROC)SDL_GL_GetProcAddress("glCreateShaderObjectARB"); pglCreateProgramObjectARB = (PFNGLCREATEPROGRAMOBJECTARBPROC)SDL_GL_GetProcAddress("glCreateProgramObjectARB"); pglAttachObjectARB = (PFNGLATTACHOBJECTARBPROC)SDL_GL_GetProcAddress("glAttachObjectARB"); pglLinkProgramARB = (PFNGLLINKPROGRAMARBPROC)SDL_GL_GetProcAddress("glLinkProgramARB"); pglUseProgramObjectARB = (PFNGLUSEPROGRAMOBJECTARBPROC)SDL_GL_GetProcAddress("glUseProgramObjectARB"); pglGetObjectParameterivARB = (PFNGLGETOBJECTPARAMETERIVARBPROC)SDL_GL_GetProcAddress("glGetObjectParameterivARB"); if(strstr(c, "ARB_pixel_buffer_object")) { pglGenBuffersARB = (PFNGLGENBUFFERSARBPROC)SDL_GL_GetProcAddress("glGenBuffersARB"); pglBindBufferARB = (PFNGLBINDBUFFERARBPROC)SDL_GL_GetProcAddress("glBindBufferARB"); pglBufferDataARB = (PFNGLBUFFERDATAARBPROC)SDL_GL_GetProcAddress("glBufferDataARB"); pglMapBufferARB = (PFNGLMAPBUFFERARBPROC)SDL_GL_GetProcAddress("glMapBufferARB"); pglUnmapBufferARB = (PFNGLUNMAPBUFFERARBPROC)SDL_GL_GetProcAddress("glUnmapBufferARB"); } } if(!pglActiveTextureARB || !pglUniform1iARB || !pglGetUniformLocationARB || !pglShaderSourceARB || !pglCompileShaderARB || !pglCreateShaderObjectARB || !pglCreateProgramObjectARB || !pglAttachObjectARB || !pglLinkProgramARB || !pglUseProgramObjectARB || !pglGetObjectParameterivARB) { ERROR_MSG("Required OpenGL functions not supported!"); return -1; } h = h>>half; width = w; height = h; format = f; surface = s; texwidth = ALIGN(w, 64); texheight = ALIGN(h, 64); if(pglGenBuffersARB && pglBindBufferARB && pglBufferDataARB && pglMapBufferARB && pglUnmapBufferARB) { pglGenBuffersARB(1, &PBObuffer); pglBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, PBObuffer); pglBufferDataARB(GL_PIXEL_UNPACK_BUFFER_ARB, texwidth * texheight + ((texwidth * texheight)>>1), NULL, GL_STREAM_DRAW_ARB); pglBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, 0); LOG_MSG("Created %dx%d PBO buffer", texwidth, texheight); } else { texdata = (unsigned char *)_aligned_malloc(texwidth * texheight + ((texwidth * texheight)>>1), 64); if(texdata == NULL) { ERROR_MSG("Out of memory!"); return -1; } LOG_MSG("Created %dx%d textures", texwidth, texheight); } glClearColor(0, 0, 0, 0); glHint(GL_POLYGON_SMOOTH_HINT, GL_NICEST); glShadeModel(GL_FLAT); glDisable(GL_DEPTH_TEST); glDisable(GL_LIGHTING); glDisable(GL_CULL_FACE); glClear(GL_COLOR_BUFFER_BIT); glGenTextures(3, texobj); p = pglCreateProgramObjectARB(); fs = pglCreateShaderObjectARB(GL_FRAGMENT_SHADER_ARB); /* Compile the shader */ pglShaderSourceARB(fs, 1, &FShader, NULL); pglCompileShaderARB(fs); pglGetObjectParameterivARB(fs, GL_OBJECT_COMPILE_STATUS_ARB, &res); if(res == 0) { ERROR_MSG("Error compiling fragment shader"); PrintShaderLog(fs); return -1; } pglAttachObjectARB(p, fs); pglLinkProgramARB(p); pglGetObjectParameterivARB(p, GL_OBJECT_LINK_STATUS_ARB, &res); if(res == 0) { ERROR_MSG("Error linking program"); PrintShaderLog(p); return -1; }#ifndef RELEASE LOG_MSG("Shader status: "); PrintShaderLog(p);#endif pglUseProgramObjectARB(p); pglActiveTextureARB(GL_TEXTURE1); glEnable(GL_TEXTURE_RECTANGLE_ARB); pglUniform1iARB(pglGetUniformLocationARB(p, "utex"), 1); glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_S, GL_CLAMP); glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T, GL_CLAMP); glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL); pglActiveTextureARB(GL_TEXTURE2); glEnable(GL_TEXTURE_RECTANGLE_ARB); pglUniform1iARB(pglGetUniformLocationARB(p, "vtex"), 2); glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_S, GL_CLAMP); glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T, GL_CLAMP); glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL); pglActiveTextureARB(GL_TEXTURE0); glEnable(GL_TEXTURE_RECTANGLE_ARB); pglUniform1iARB(pglGetUniformLocationARB(p, "ytex"), 0); glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_S, GL_CLAMP); glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T, GL_CLAMP); glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL); // Create display list displaylist = glGenLists(1); glNewList(displaylist, GL_COMPILE); glBegin(GL_QUADS); // lower left glTexCoord2f(0, height); glVertex2f(0.0f, 0.0f); // lower right glTexCoord2f(width, height); glVertex2f(1.0f, 0.0f); // upper right glTexCoord2f(width, 0); glVertex2f(1.0f, 1.0f); // upper left glTexCoord2f(0, 0); glVertex2f(0.0f, 1.0f); glEnd(); glEndList(); return 0; } void Free(void) { LOG_MSG("Freeing video surface"); display.w = display.h = 0; if(displaylist) glDeleteLists(1, displaylist); displaylist = 0; if(texobj[0]) glDeleteTextures(3, texobj); texobj[0] = texobj[1] = texobj[2] = 0; if((!PBObuffer) && texdata) _aligned_free(texdata); texdata = NULL; // Delete PBO buffer PFNGLDELETEBUFFERSARBPROC pglDeleteBuffersARB; pglDeleteBuffersARB = (PFNGLDELETEBUFFERSARBPROC)SDL_GL_GetProcAddress("glDeleteBuffersARB"); if(pglDeleteBuffersARB && PBObuffer) pglDeleteBuffersARB(1, &PBObuffer); PBObuffer = 0; // Delete shaders PFNGLDETACHOBJECTARBPROC pglDetachObjectARB; PFNGLDELETEOBJECTARBPROC pglDeleteObjectARB; pglDetachObjectARB = (PFNGLDETACHOBJECTARBPROC)SDL_GL_GetProcAddress("glDetachObjectARB"); pglDeleteObjectARB = (PFNGLDELETEOBJECTARBPROC)SDL_GL_GetProcAddress("glDeleteObjectARB"); if(pglDetachObjectARB && pglDeleteObjectARB && p && fs) { pglDetachObjectARB(p, fs); pglDeleteObjectARB(fs); pglDeleteObjectARB(p); }#if (SDL_IS_PATCHED) // Release context if it's current if(glGetString(GL_EXTENSIONS)) { LOG_MSG("Releasing context"); SDL_GL_MakeCurrent(1); }#endif fs = p = 0; } int CopyData(struct Buffer *buffer) { if(deinterlacer->IsHalf() != half) { height <<= half; half = !half; if(surface) { Free(); Create(width, height, format, surface); } } if(PBObuffer) { pglBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, PBObuffer); texdata = (unsigned char*)pglMapBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, GL_WRITE_ONLY); } if(texdata == NULL) return -1; unsigned char * ptr[3]; ptr[2] = texdata; ptr[0] = texdata + (texwidth * texheight); ptr[1] = ptr[0] + ((texwidth * texheight)>>2); if(buffer == NULL) { for(int i = height>>1; i; i--) { SDL_memset(ptr[2], 0, width); ptr[2] += texwidth; SDL_memset(ptr[2], 0, width); ptr[2] += texwidth; SDL_memset(ptr[1], 0x80, width>>1); ptr[1] += texwidth>>1; SDL_memset(ptr[0], 0x80, width>>1); ptr[0] += texwidth>>1; } } else { unsigned char *src[3]; src[2] = buffer->data[0]; src[0] = buffer->data[1]; src[1] = buffer->data[2]; deint d; d.src_pitch[2] = buffer->src_width; d.src_pitch[0] = d.src_pitch[1] = buffer->src_width>>1; d.dst_pitch[2] = texwidth; d.dst_pitch[0] = texwidth>>1; d.dst_pitch[1] = texwidth>>1; d.width = buffer->dst_width; d.height = buffer->height; Render(ptr, src, &d); } if(PBObuffer) { pglUnmapBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB); pglBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, 0); } return 0; } int SwapBuffers(SDL_Rect * clip) { if(SDL_memcmp(&display, clip, sizeof(SDL_Rect))) { SDL_memcpy(&display, clip, sizeof(SDL_Rect)); glViewport(display.x, display.y, display.w, display.h); LOG_MSG("Viewport set to %dx%d", display.w, display.h); glMatrixMode(GL_PROJECTION); glLoadIdentity(); glOrtho(0.0f, display.w, 0.0f, display.h, -1.0f, 1.0f); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glScalef(display.w, display.h, 1.0f); } glClear(GL_COLOR_BUFFER_BIT); if((PBObuffer == 0) && (texdata == NULL)) { SDL_GL_SwapBuffers(); return -1; } else if(PBObuffer) { texdata = 0; pglBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, PBObuffer); } pglActiveTextureARB(GL_TEXTURE0); glBindTexture(GL_TEXTURE_RECTANGLE_ARB, texobj[0]); glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_LUMINANCE, texwidth, texheight, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, texdata); pglActiveTextureARB(GL_TEXTURE1); glBindTexture(GL_TEXTURE_RECTANGLE_ARB, texobj[1]); glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_LUMINANCE, texwidth>>1, texheight>>1, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, texdata + (texwidth * texheight)); pglActiveTextureARB(GL_TEXTURE2); glBindTexture(GL_TEXTURE_RECTANGLE_ARB, texobj[2]); glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_LUMINANCE, texwidth>>1, texheight>>1, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, texdata + (texwidth * texheight) + ((texwidth * texheight)>>2)); if(PBObuffer) { pglBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, 0); } glCallList(displaylist); SDL_GL_SwapBuffers(); return 0; }};#undef MODULE#endif // C_OPENGL#endif // OPENGL_H
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -