home *** CD-ROM | disk | FTP | other *** search
- // VirtualDub - Video processing and capture application
- // A/V interface library
- // Copyright (C) 1998-2006 Avery Lee
- //
- // 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., 675 Mass Ave, Cambridge, MA 02139, USA.
-
- #include <vd2/system/vdtypes.h>
- #include <vd2/Riza/opengl.h>
- #include <windows.h>
-
- namespace {
- static const char *const kWGLFunctions[]={
- "wglCreateContext",
- "wglDeleteContext",
- "wglMakeCurrent",
- "wglGetProcAddress",
- "wglSwapBuffers",
- "wglUseFontBitmapsA",
- };
-
- static const char *const kGLFunctions[]={
- "glAlphaFunc",
- "glBegin",
- "glBindTexture",
- "glBlendFunc",
- "glCallList",
- "glClear",
- "glClearColor",
- "glColor4d",
- "glColor4f",
- "glColor4ub",
- "glColorMask",
- "glCopyTexSubImage2D",
- "glDeleteLists",
- "glDeleteTextures",
- "glDepthFunc",
- "glDepthMask",
- "glDisable",
- "glDrawBuffer",
- "glEnable",
- "glEnd",
- "glEndList",
- "glFeedbackBuffer",
- "glFinish",
- "glFlush",
- "glFrontFace",
- "glGetError",
- "glGetFloatv",
- "glGetIntegerv",
- "glGetTexLevelParameteriv",
- "glGenLists",
- "glGetString",
- "glGenTextures",
- "glLoadIdentity",
- "glLoadMatrixd",
- "glMatrixMode",
- "glNewList",
- "glOrtho",
- "glPixelStorei",
- "glPopAttrib",
- "glPushAttrib",
- "glReadBuffer",
- "glReadPixels",
- "glRenderMode",
- "glTexCoord2d",
- "glTexCoord2f",
- "glTexCoord2fv",
- "glTexEnvf",
- "glTexEnvi",
- "glTexImage1D",
- "glTexImage2D",
- "glTexParameterfv",
- "glTexParameteri",
- "glTexSubImage1D",
- "glTexSubImage2D",
- "glVertex2d",
- "glVertex2f",
- "glVertex2i",
- "glVertex3fv",
- "glViewport",
- };
-
- static const char *const kGLExtFunctions[]={
- // ARB_multitexture
- "glActiveTextureARB",
- "glMultiTexCoord2fARB",
-
- // ARB_vertex_buffer_object (EXT_pixel_buffer_object/ARB_pixel_buffer_object)
- "glBindBufferARB",
- "glDeleteBuffersARB",
- "glGenBuffersARB",
- "glIsBufferARB",
- "glBufferDataARB",
- "glBufferSubDataARB",
- "glGetBufferSubDataARB",
- "glMapBufferARB",
- "glUnmapBufferARB",
- "glGetBufferParameterivARB",
- "glGetBufferPointervARB",
-
- // NV_register_combiners
- "glCombinerParameterfvNV",
- "glCombinerParameterivNV",
- "glCombinerParameterfNV",
- "glCombinerParameteriNV",
- "glCombinerInputNV",
- "glCombinerOutputNV",
- "glFinalCombinerInputNV",
- "glGetCombinerInputParameterfvNV",
- "glGetCombinerInputParameterivNV",
- "glGetCombinerOutputParameterfvNV",
- "glGetCombinerOutputParameterivNV",
- "glGetFinalCombinerInputParameterfvNV",
- "glGetFinalCombinerInputParameterivNV",
-
- // NV_register_combiners2
- "glCombinerStageParameterfvNV",
-
- // ATI_fragment_shader
- "glGenFragmentShadersATI",
- "glBindFragmentShaderATI",
- "glDeleteFragmentShaderATI",
- "glBeginFragmentShaderATI",
- "glEndFragmentShaderATI",
- "glPassTexCoordATI",
- "glSampleMapATI",
- "glColorFragmentOp1ATI",
- "glColorFragmentOp2ATI",
- "glColorFragmentOp3ATI",
- "glAlphaFragmentOp1ATI",
- "glAlphaFragmentOp2ATI",
- "glAlphaFragmentOp3ATI",
- "glSetFragmentShaderConstantATI",
-
- // NV_occlusion_query
- "glGenOcclusionQueriesNV",
- "glDeleteOcclusionQueriesNV",
- "glIsOcclusionQueryNV",
- "glBeginOcclusionQueryNV",
- "glEndOcclusionQueryNV",
- "glGetOcclusionQueryivNV",
- "glGetOcclusionQueryuivNV",
-
- // EXT_framebuffer_object
- "glIsRenderbufferEXT",
- "glBindRenderbufferEXT",
- "glDeleteRenderbuffersEXT",
- "glGenRenderbuffersEXT",
- "glRenderbufferStorageEXT",
- "glGetRenderbufferParameterivEXT",
- "glIsFramebufferEXT",
- "glBindFramebufferEXT",
- "glDeleteFramebuffersEXT",
- "glGenFramebuffersEXT",
- "glCheckFramebufferStatusEXT",
- "glFramebufferTexture1DEXT",
- "glFramebufferTexture2DEXT",
- "glFramebufferTexture3DEXT",
- "glFramebufferRenderbufferEXT",
- "glGetFramebufferAttachmentParameterivEXT",
- "glGenerateMipmapEXT",
-
- // ARB_vertex_program
- "glVertexAttrib1sARB",
- "glVertexAttrib1fARB",
- "glVertexAttrib1dARB",
- "glVertexAttrib2sARB",
- "glVertexAttrib2fARB",
- "glVertexAttrib2dARB",
- "glVertexAttrib3sARB",
- "glVertexAttrib3fARB",
- "glVertexAttrib3dARB",
- "glVertexAttrib4sARB",
- "glVertexAttrib4fARB",
- "glVertexAttrib4dARB",
- "glVertexAttrib4NubARB",
- "glVertexAttrib1svARB",
- "glVertexAttrib1fvARB",
- "glVertexAttrib1dvARB",
- "glVertexAttrib2svARB",
- "glVertexAttrib2fvARB",
- "glVertexAttrib2dvARB",
- "glVertexAttrib3svARB",
- "glVertexAttrib3fvARB",
- "glVertexAttrib3dvARB",
- "glVertexAttrib4bvARB",
- "glVertexAttrib4svARB",
- "glVertexAttrib4ivARB",
- "glVertexAttrib4ubvARB",
- "glVertexAttrib4usvARB",
- "glVertexAttrib4uivARB",
- "glVertexAttrib4fvARB",
- "glVertexAttrib4dvARB",
- "glVertexAttrib4NbvARB",
- "glVertexAttrib4NsvARB",
- "glVertexAttrib4NivARB",
- "glVertexAttrib4NubvARB",
- "glVertexAttrib4NusvARB",
- "glVertexAttrib4NuivARB",
- "glVertexAttribPointerARB",
- "glEnableVertexAttribArrayARB",
- "glDisableVertexAttribArrayARB",
- "glProgramStringARB",
- "glBindProgramARB",
- "glDeleteProgramsARB",
- "glGenProgramsARB",
- "glProgramEnvParameter4dARB",
- "glProgramEnvParameter4dvARB",
- "glProgramEnvParameter4fARB",
- "glProgramEnvParameter4fvARB",
- "glProgramLocalParameter4dARB",
- "glProgramLocalParameter4dvARB",
- "glProgramLocalParameter4fARB",
- "glProgramLocalParameter4fvARB",
- "glGetProgramEnvParameterdvARB",
- "glGetProgramEnvParameterfvARB",
- "glGetProgramLocalParameterdvARB",
- "glGetProgramLocalParameterfvARB",
- "glGetProgramivARB",
- "glGetProgramStringARB",
- "glGetVertexAttribdvARB",
- "glGetVertexAttribfvARB",
- "glGetVertexAttribivARB",
- "glGetVertexAttribPointervARB",
- "glIsProgramARB",
-
- // EXT_blend_minmax
- "glBlendEquationEXT",
-
- // EXT_secondary_color
- "glSecondaryColor3ubEXT",
-
- // WGL_ARB_extensions_string
- "wglGetExtensionsStringARB",
-
- // WGL_EXT_extensions_string
- "wglGetExtensionsStringEXT",
-
- // WGL_ARB_make_current_read
- "wglMakeContextCurrentARB",
- "wglGetCurrentReadDCARB",
-
- // WGL_EXT_swap_control
- "wglSwapIntervalEXT",
- "wglGetSwapIntervalEXT",
- };
- }
-
- VDOpenGLBinding::VDOpenGLBinding()
- : mhmodOGL(NULL)
- , mhdc(NULL)
- , mhglrc(NULL)
- {
- }
-
- VDOpenGLBinding::~VDOpenGLBinding() {
- }
-
- bool VDOpenGLBinding::Init() {
- mhmodOGL = LoadLibrary("opengl32");
- if (!mhmodOGL)
- return false;
-
- // pull wgl functions
- for(int i=0; i<sizeof(kWGLFunctions)/sizeof(kWGLFunctions[0]); ++i) {
- void *p = (void *)GetProcAddress(mhmodOGL, kWGLFunctions[i]);
-
- if (!p) {
- Shutdown();
- return false;
- }
-
- ((void **)static_cast<VDAPITableWGL *>(this))[i] = p;
- }
-
- return true;
- }
-
- void VDOpenGLBinding::Shutdown() {
- End();
- Detach();
-
- if (mhmodOGL) {
- FreeLibrary(mhmodOGL);
- mhmodOGL = NULL;
- }
- }
-
- bool VDOpenGLBinding::Attach(HDC hdc, int minColorBits, int minAlphaBits, int minDepthBits, int minStencilBits, bool doubleBuffer) {
- PIXELFORMATDESCRIPTOR pfd={};
-
- pfd.nSize = sizeof(PIXELFORMATDESCRIPTOR);
- pfd.nVersion = 1;
- pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL;
- if (doubleBuffer)
- pfd.dwFlags |= PFD_DOUBLEBUFFER;
- pfd.iPixelType = PFD_TYPE_RGBA;
- pfd.cColorBits = minColorBits;
- pfd.cAlphaBits = minAlphaBits;
- pfd.cDepthBits = minDepthBits;
- pfd.cStencilBits = minStencilBits;
- pfd.iLayerType = PFD_MAIN_PLANE;
-
- int pf = ChoosePixelFormat(hdc, &pfd);
- if (!pf) {
- Detach();
- return false;
- }
-
- if (!SetPixelFormat(hdc, pf, &pfd)) {
- Detach();
- return false;
- }
-
- mhglrc = wglCreateContext(hdc);
- if (!mhglrc)
- return false;
-
- if (!Begin(hdc)) {
- Detach();
- return false;
- }
-
- for(int i=0; i<sizeof(kGLFunctions)/sizeof(kGLFunctions[0]); ++i) {
- void *p = (void *)GetProcAddress(mhmodOGL, kGLFunctions[i]);
-
- if (!p) {
- Detach();
- return false;
- }
-
- ((void **)static_cast<VDAPITableOpenGL *>(this))[i] = p;
- }
-
- for(int i=0; i<sizeof(kGLExtFunctions)/sizeof(kGLExtFunctions[0]); ++i) {
- void *p = (void *)wglGetProcAddress(kGLExtFunctions[i]);
-
- ((void **)static_cast<VDAPITableOpenGLEXT *>(this))[i] = p;
- }
-
- const char *ext = (const char *)glGetString(GL_EXTENSIONS);
-
- ARB_fragment_program = false;
- ARB_multitexture = false;
- ARB_pixel_buffer_object = false;
- ARB_vertex_program = false;
- ATI_fragment_shader = false;
- EXT_blend_minmax = false;
- EXT_blend_subtract = false;
- EXT_framebuffer_object = false;
- EXT_pixel_buffer_object = false;
- EXT_texture_env_combine = false;
- EXT_texture_edge_clamp = false;
- NV_occlusion_query = false;
- NV_register_combiners = false;
- NV_register_combiners2 = false;
-
- if (ext) {
- for(;;) {
- while(*ext == ' ')
- ++ext;
-
- if (!*ext)
- break;
-
- const char *start = ext;
- while(*ext && *ext != ' ')
- ++ext;
-
- int len = ext - start;
-
- switch(len) {
- case 19:
- if (!memcmp(start, "GL_ARB_multitexture", 19))
- ARB_multitexture = true;
- else if (!memcmp(start, "GL_EXT_blend_minmax", 19))
- EXT_blend_minmax = true;
- break;
-
- case 20:
- if (!memcmp(start, "GL_EXT_blend_subtract", 20))
- EXT_blend_subtract = true;
- break;
-
- case 21:
- if (!memcmp(start, "GL_NV_occlusion_query", 21))
- NV_occlusion_query = true;
- else if (!memcmp(start, "GL_ARB_vertex_program", 21))
- ARB_vertex_program = true;
- break;
-
- case 22:
- if (!memcmp(start, "GL_ATI_fragment_shader", 22))
- ATI_fragment_shader = true;
- else if (!memcmp(start, "GL_EXT_secondary_color", 22))
- EXT_secondary_color = true;
- break;
-
- case 23:
- if (!memcmp(start, "GL_ARB_fragment_program", 23))
- ARB_fragment_program = true;
- break;
-
- case 24:
- if (!memcmp(start, "GL_NV_register_combiners", 24))
- NV_register_combiners = true;
- break;
- case 25:
- if (!memcmp(start, "GL_NV_register_combiners2", 25))
- NV_register_combiners2 = true;
- else if (!memcmp(start, "GL_EXT_framebuffer_object", 25))
- EXT_framebuffer_object = true;
- else if (!memcmp(start, "GL_EXT_texture_edge_clamp", 25))
- EXT_texture_edge_clamp = true;
- break;
- case 26:
- if (!memcmp(start, "GL_EXT_pixel_buffer_object", 26))
- EXT_pixel_buffer_object = true;
- else if (!memcmp(start, "GL_ARB_pixel_buffer_object", 26))
- EXT_pixel_buffer_object = ARB_pixel_buffer_object = true;
- else if (!memcmp(start, "GL_EXT_texture_env_combine", 26))
- EXT_texture_env_combine = true;
- else if (!memcmp(start, "GL_ARB_texture_env_combine", 26))
- EXT_texture_env_combine = true;
- break;
- }
- }
- }
-
- ext = NULL;
- if (wglGetExtensionsStringARB)
- ext = wglGetExtensionsStringARB(hdc);
- else if (wglGetExtensionsStringEXT)
- ext = wglGetExtensionsStringEXT();
-
- EXT_swap_control = false;
- ARB_make_current_read = false;
- if (ext) {
- for(;;) {
- while(*ext == ' ')
- ++ext;
-
- if (!*ext)
- break;
-
- const char *start = ext;
- while(*ext && *ext != ' ')
- ++ext;
-
- int len = ext - start;
-
- switch(len) {
- case 20:
- if (!memcmp(start, "WGL_EXT_swap_control", 20))
- EXT_swap_control = true;
- break;
- case 25:
- if (!memcmp(start, "WGL_ARB_make_current_read", 25))
- ARB_make_current_read = true;
- break;
- }
- }
- }
-
- End();
-
- return true;
- }
-
- bool VDOpenGLBinding::AttachAux(HDC hdc, int minColorBits, int minAlphaBits, int minDepthBits, int minStencilBits, bool doubleBuffer) {
- PIXELFORMATDESCRIPTOR pfd={};
-
- pfd.nSize = sizeof(PIXELFORMATDESCRIPTOR);
- pfd.nVersion = 1;
- pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL;
- if (doubleBuffer)
- pfd.dwFlags |= PFD_DOUBLEBUFFER;
- pfd.iPixelType = PFD_TYPE_RGBA;
- pfd.cColorBits = minColorBits;
- pfd.cAlphaBits = minAlphaBits;
- pfd.cDepthBits = minDepthBits;
- pfd.cStencilBits = minStencilBits;
- pfd.iLayerType = PFD_MAIN_PLANE;
-
- int pf = ChoosePixelFormat(hdc, &pfd);
- if (!pf)
- return false;
-
- if (!SetPixelFormat(hdc, pf, &pfd))
- return false;
-
- return true;
- }
-
- void VDOpenGLBinding::Detach() {
- if (mhglrc) {
- wglDeleteContext(mhglrc);
- mhglrc = NULL;
- }
- }
-
- bool VDOpenGLBinding::Begin(HDC hdc) {
- if (!wglMakeCurrent(hdc, mhglrc))
- return false;
-
- mhdc = hdc;
- return true;
- }
-
- void VDOpenGLBinding::End() {
- if (mhdc) {
- wglMakeCurrent(mhdc, NULL);
- mhdc = NULL;
- }
- }
-
- namespace {
- void CreateNVRegisterCombinerSetup(VDOpenGLBinding& gl, const VDOpenGLNVRegisterCombinerConfig& config, bool nvrc2) {
- // load base constants
- if (!nvrc2) {
- for(int i=0; i<config.mConstantCount; ++i)
- gl.glCombinerParameterfvNV(GL_CONSTANT_COLOR0_NV + i, config.mpConstants[i]);
- }
-
- static const GLenum kRegisterTable[16]={
- GL_ZERO,
- GL_DISCARD_NV,
- GL_SPARE0_NV,
- GL_SPARE1_NV,
- GL_PRIMARY_COLOR_NV,
- GL_SECONDARY_COLOR_NV,
- GL_CONSTANT_COLOR0_NV,
- GL_CONSTANT_COLOR1_NV,
- GL_SPARE0_PLUS_SECONDARY_COLOR_NV,
- GL_E_TIMES_F_NV,
- GL_ZERO,
- GL_ZERO,
- GL_TEXTURE0_ARB,
- GL_TEXTURE1_ARB,
- GL_TEXTURE2_ARB,
- GL_TEXTURE3_ARB,
- };
-
- static const GLenum kScaleTable[4]={
- GL_NONE,
- GL_SCALE_BY_TWO_NV,
- GL_SCALE_BY_FOUR_NV,
- GL_SCALE_BY_ONE_HALF_NV,
- };
-
- static const GLenum kSourceMappingTable[8]={
- GL_UNSIGNED_IDENTITY_NV,
- GL_UNSIGNED_INVERT_NV,
- GL_SIGNED_IDENTITY_NV,
- GL_SIGNED_NEGATE_NV,
- GL_EXPAND_NORMAL_NV,
- GL_EXPAND_NEGATE_NV,
- GL_HALF_BIAS_NORMAL_NV,
- GL_HALF_BIAS_NEGATE_NV
- };
-
- // create combiner stages
- const uint8 *src = config.mpByteCode;
- for(int stage=0; stage<config.mGeneralCombinerCount; ++stage) {
- GLenum stageToken = GL_COMBINER0_NV + stage;
-
- // load per-stage colors
- if (nvrc2) {
- uint8 c0 = src[0];
- uint8 c1 = src[1];
- src += 2;
-
- if (c0 != 0xff)
- gl.glCombinerStageParameterfvNV(GL_COMBINER0_NV + stage, GL_CONSTANT_COLOR0_NV, config.mpConstants[c0]);
- if (c1 != 0xff)
- gl.glCombinerStageParameterfvNV(GL_COMBINER0_NV + stage, GL_CONSTANT_COLOR1_NV, config.mpConstants[c1]);
- VDASSERT(!gl.glGetError());
- }
-
- // load combiner halves
- for(int half=0; half<2; ++half) {
- GLenum portionToken = half ? GL_ALPHA : GL_RGB;
-
- // decode output
- GLenum dst0 = kRegisterTable[src[0] >> 4];
- GLenum dst1 = kRegisterTable[src[1] & 15];
- GLenum dst2 = kRegisterTable[src[1] >> 4];
- GLenum dstscale = kScaleTable[src[0] & 3];
- GLenum dstbias = src[0] & 4 ? GL_BIAS_BY_NEGATIVE_ONE_HALF_NV : GL_NONE;
- GLenum dstDotAB = src[2] & 1 ? GL_TRUE : GL_FALSE;
- GLenum dstDotCD = src[2] & 2 ? GL_TRUE : GL_FALSE;
- GLenum dstMux = src[2] & 4 ? GL_TRUE : GL_FALSE;
- src += 3;
-
- gl.glCombinerOutputNV(stageToken, portionToken, dst0, dst1, dst2, dstscale, dstbias, dstDotAB, dstDotCD, dstMux);
- VDASSERT(!gl.glGetError());
-
- // decode sources
- for(int i=0; i<4; ++i) {
- uint8 c = *src++;
- GLenum srcreg = kRegisterTable[c & 15];
- GLenum srcmap = kSourceMappingTable[(c >> 4) & 7];
- GLenum srcportion = c & 0x80 ? GL_ALPHA : half ? GL_BLUE : GL_RGB;
-
- gl.glCombinerInputNV(stageToken, portionToken, GL_VARIABLE_A_NV + i, srcreg, srcmap, srcportion);
- VDASSERT(!gl.glGetError());
- }
- }
- }
-
- gl.glCombinerParameteriNV(GL_NUM_GENERAL_COMBINERS_NV, config.mGeneralCombinerCount);
-
- // load final combiner
- if (nvrc2) {
- uint8 c0 = src[0];
- uint8 c1 = src[1];
- src += 2;
-
- if (c0 != 0xff)
- gl.glCombinerParameterfvNV(GL_CONSTANT_COLOR0_NV, config.mpConstants[c0]);
- if (c1 != 0xff)
- gl.glCombinerParameterfvNV(GL_CONSTANT_COLOR1_NV, config.mpConstants[c1]);
- VDASSERT(!gl.glGetError());
- }
-
- for(int i=0; i<7; ++i) {
- uint8 c = *src++;
- GLenum srcreg = kRegisterTable[c & 15];
- GLenum srcmap = kSourceMappingTable[(c >> 4) & 7];
- GLenum srcportion = c & 0x80 ? GL_ALPHA : i == 6 ? GL_BLUE : GL_RGB;
-
- gl.glFinalCombinerInputNV(GL_VARIABLE_A_NV + i, srcreg, srcmap, srcportion);
- VDASSERT(!gl.glGetError());
- }
- }
-
- void CreateATIFragmentShader(VDOpenGLBinding& gl, const VDOpenGLATIFragmentShaderConfig& config) {
- enum {
- kTexAddrT0 = 0x00,
- kTexAddrT1 = 0x01,
- kTexAddrT2 = 0x02,
- kTexAddrT3 = 0x03,
- kTexAddrT4 = 0x04,
- kTexAddrT5 = 0x05,
- kTexAddrR0 = 0x08,
- kTexAddrR1 = 0x09,
- kTexAddrR2 = 0x0A,
- kTexAddrR3 = 0x0B,
- kTexAddrR4 = 0x0C,
- kTexAddrR5 = 0x0D,
- kTexSwizzleXYZ = 0x00,
- kTexSwizzleXYW = 0x10,
- kTexSwizzleXYZ_DZ = 0x20,
- kTexSwizzleXYW_DW = 0x30,
- kTexSwizzleMask = 0x30,
- kTexModeTexcrd = 0x40,
- kTexModeTexld = 0x80,
- kTexModeMask = 0xC0
- };
-
- enum {
- kChannelOpAdd,
- kChannelOpSub,
- kChannelOpMul,
- kChannelOpMad,
- kChannelOpLerp,
- kChannelOpMov,
- kChannelOpCnd,
- kChannelOpCnd0,
- kChannelOpDot2Add,
- kChannelOpDot3,
- kChannelOpDot4,
- kChannelOpTexcrd,
- kChannelOpTexld,
- kChannelOpMask = 0x0F,
- kChannelOpModScaleMask = 0x70,
- kChannelOpModScaleX2 = 0x10,
- kChannelOpModScaleX4 = 0x20,
- kChannelOpModScaleX8 = 0x30,
- kChannelOpModScaleD2 = 0x40,
- kChannelOpModScaleD4 = 0x50,
- kChannelOpModScaleD8 = 0x60,
- kChannelOpModSaturate = 0x80
- };
-
- enum {
- kChanRegR0,
- kChanRegR1,
- kChanRegR2,
- kChanRegR3,
- kChanRegR4,
- kChanRegR5,
- kChanRegC0,
- kChanRegC1,
- kChanRegC2,
- kChanRegC3,
- kChanRegC4,
- kChanRegC5,
- kChanRegC6,
- kChanRegC7,
- kChanRegZero,
- kChanRegOne,
- kChanRegV0,
- kChanRegV1,
- kChanSrcMod2X = 0x01,
- kChanSrcModComp = 0x02,
- kChanSrcModNegate = 0x04,
- kChanSrcModBias = 0x08,
- kChanSrcSwizzleRed = 0x10,
- kChanSrcSwizzleGreen = 0x20,
- kChanSrcSwizzleBlue = 0x30,
- kChanSrcSwizzleAlpha = 0x40,
- kChanDstMaskRed = 0x10,
- kChanDstMaskGreen = 0x20,
- kChanDstMaskBlue = 0x40,
- kChanDstMaskAlpha = 0x80
- };
-
- VDASSERT(!gl.glGetError());
- gl.glBeginFragmentShaderATI();
-
- // load constants
- for(uint8 i=0; i<config.mConstantCount; ++i)
- gl.glSetFragmentShaderConstantATI(GL_CON_0_ATI + i, config.mpConstants[i]);
- VDASSERT(!gl.glGetError());
-
- // create passes
- const uint8 *src = config.mpByteCode;
- while(uint8 opCount = *src++) {
- // set up texture interpolators
- for(int i=0; i<6; ++i) {
- uint8 texOp = *src++;
-
- if (!texOp)
- continue;
-
- static const GLenum kTexSwizzleMode[4]={
- GL_SWIZZLE_STR_ATI,
- GL_SWIZZLE_STQ_ATI,
- GL_SWIZZLE_STR_DR_ATI,
- GL_SWIZZLE_STQ_DQ_ATI
- };
-
- GLenum dst = GL_REG_0_ATI + i;
- GLenum src = (texOp & 8 ? GL_REG_0_ATI : GL_TEXTURE0_ARB) + (texOp & 7);
- GLenum swizzle = kTexSwizzleMode[(texOp >> 4) & 3];
-
- switch(texOp & kTexModeMask) {
- case kTexModeTexcrd:
- gl.glPassTexCoordATI(dst, src, swizzle);
- break;
- case kTexModeTexld:
- gl.glSampleMapATI(dst, src, swizzle);
- break;
- }
- }
- VDASSERT(!gl.glGetError());
-
- // set up alu ops
- while(opCount--) {
- static const GLenum kOpTable[][2]={
- { GL_ADD_ATI, 2 },
- { GL_SUB_ATI, 2 },
- { GL_MUL_ATI, 2 },
- { GL_MAD_ATI, 3 },
- { GL_LERP_ATI, 3 },
- { GL_MOV_ATI, 1 },
- { GL_CND_ATI, 3 },
- { GL_CND0_ATI, 3 },
- { GL_DOT2_ADD_ATI, 3 },
- { GL_DOT3_ATI, 2 },
- { GL_DOT4_ATI, 2 },
- };
-
- static const GLuint kDstModTable[16]={
- GL_NONE,
- GL_2X_BIT_ATI,
- GL_4X_BIT_ATI,
- GL_8X_BIT_ATI,
- GL_HALF_BIT_ATI,
- GL_QUARTER_BIT_ATI,
- GL_EIGHTH_BIT_ATI,
- GL_NONE,
- GL_SATURATE_BIT_ATI,
- GL_SATURATE_BIT_ATI | GL_2X_BIT_ATI,
- GL_SATURATE_BIT_ATI | GL_4X_BIT_ATI,
- GL_SATURATE_BIT_ATI | GL_8X_BIT_ATI,
- GL_SATURATE_BIT_ATI | GL_HALF_BIT_ATI,
- GL_SATURATE_BIT_ATI | GL_QUARTER_BIT_ATI,
- GL_SATURATE_BIT_ATI | GL_EIGHTH_BIT_ATI,
- GL_SATURATE_BIT_ATI,
- };
-
- static const GLenum kRegTable[]={
- GL_REG_0_ATI,
- GL_REG_1_ATI,
- GL_REG_2_ATI,
- GL_REG_3_ATI,
- GL_REG_4_ATI,
- GL_REG_5_ATI,
- GL_CON_0_ATI,
- GL_CON_1_ATI,
- GL_CON_2_ATI,
- GL_CON_3_ATI,
- GL_CON_4_ATI,
- GL_CON_5_ATI,
- GL_CON_6_ATI,
- GL_CON_7_ATI,
- GL_ZERO,
- GL_ONE,
- GL_PRIMARY_COLOR_ARB,
- GL_SECONDARY_INTERPOLATOR_ATI
- };
-
- static const GLenum kRepTable[]={
- GL_NONE,
- GL_RED,
- GL_GREEN,
- GL_BLUE,
- GL_ALPHA
- };
-
- const uint8 opcode = *src++;
- const uint8 dstarg = *src++;
-
- GLenum op = kOpTable[opcode & 15][0];
- GLenum dstMod = kDstModTable[opcode >> 4];
- GLenum dstReg = kRegTable[dstarg & 15];
- GLuint rgbMask = (dstarg >> 4) & 7;
- bool alphaMask = (dstarg & 0x80) != 0;
-
- int srcCount = kOpTable[opcode & 15][1];
- GLenum srcReg[3];
- GLenum srcRep[3];
- GLuint srcMod[3];
- for(int i=0; i<srcCount; ++i) {
- const uint8 mod = src[1];
-
- srcReg[i] = kRegTable[src[0]];
- srcRep[i] = kRepTable[mod >> 4];
- srcMod[i] = mod & 15;
- src += 2;
- }
-
- switch(srcCount) {
- case 1:
- if (rgbMask)
- gl.glColorFragmentOp1ATI(op, dstReg, rgbMask, dstMod, srcReg[0], srcRep[0], srcMod[0]);
- if (alphaMask)
- gl.glAlphaFragmentOp1ATI(op, dstReg, dstMod, srcReg[0], srcRep[0], srcMod[0]);
- break;
- case 2:
- if (rgbMask)
- gl.glColorFragmentOp2ATI(op, dstReg, rgbMask, dstMod, srcReg[0], srcRep[0], srcMod[0], srcReg[1], srcRep[1], srcMod[1]);
- if (alphaMask)
- gl.glAlphaFragmentOp2ATI(op, dstReg, dstMod, srcReg[0], srcRep[0], srcMod[0], srcReg[1], srcRep[1], srcMod[1]);
- break;
- case 3:
- if (rgbMask)
- gl.glColorFragmentOp3ATI(op, dstReg, rgbMask, dstMod, srcReg[0], srcRep[0], srcMod[0], srcReg[1], srcRep[1], srcMod[1], srcReg[2], srcRep[2], srcMod[2]);
- if (alphaMask)
- gl.glAlphaFragmentOp3ATI(op, dstReg, dstMod, srcReg[0], srcRep[0], srcMod[0], srcReg[1], srcRep[1], srcMod[1], srcReg[2], srcRep[2], srcMod[2]);
- break;
- }
- VDASSERT(!gl.glGetError());
-
- }
- }
-
- gl.glEndFragmentShaderATI();
- VDASSERT(!gl.glGetError());
- }
- }
-
- GLenum VDOpenGLBinding::InitTechniques(const VDOpenGLTechnique *techniques, int techniqueCount) {
- GLuint listBase = glGenLists(techniqueCount);
-
- for(int i=0; i<techniqueCount; ++i) {
- const VDOpenGLTechnique& tech = techniques[i];
- GLenum shader;
-
- switch(tech.mFragmentShaderMode) {
- case kVDOpenGLFragmentShaderModeNVRC2:
- if (!NV_register_combiners2)
- continue;
- // fall through
- case kVDOpenGLFragmentShaderModeNVRC:
- if (!NV_register_combiners)
- continue;
- break;
- case kVDOpenGLFragmentShaderModeATIFS:
- if (!ATI_fragment_shader)
- continue;
- break;
- }
-
- if (tech.mFragmentShaderMode == kVDOpenGLFragmentShaderModeATIFS) {
- shader = glGenFragmentShadersATI(1);
- glBindFragmentShaderATI(shader);
- CreateATIFragmentShader(*this, *(const VDOpenGLATIFragmentShaderConfig *)tech.mpFragmentShader);
- glBindFragmentShaderATI(0);
- }
-
- glNewList(listBase + i, GL_COMPILE);
- switch(tech.mFragmentShaderMode) {
- case kVDOpenGLFragmentShaderModeNVRC:
- glEnable(GL_REGISTER_COMBINERS_NV);
- glDisable(GL_PER_STAGE_CONSTANTS_NV);
- if (ATI_fragment_shader)
- glDisable(GL_FRAGMENT_SHADER_ATI);
- CreateNVRegisterCombinerSetup(*this, *(const VDOpenGLNVRegisterCombinerConfig *)tech.mpFragmentShader, false);
- break;
- case kVDOpenGLFragmentShaderModeNVRC2:
- glEnable(GL_REGISTER_COMBINERS_NV);
- glEnable(GL_PER_STAGE_CONSTANTS_NV);
- if (ATI_fragment_shader)
- glDisable(GL_FRAGMENT_SHADER_ATI);
- CreateNVRegisterCombinerSetup(*this, *(const VDOpenGLNVRegisterCombinerConfig *)tech.mpFragmentShader, true);
- break;
- case kVDOpenGLFragmentShaderModeATIFS:
- if (NV_register_combiners)
- glDisable(GL_REGISTER_COMBINERS_NV);
- glEnable(GL_FRAGMENT_SHADER_ATI);
- glBindFragmentShaderATI(shader);
- break;
- }
- glEndList();
- }
-
- return listBase;
- }
-
- void VDOpenGLBinding::DisableFragmentShaders() {
- if (NV_register_combiners)
- glDisable(GL_REGISTER_COMBINERS_NV);
- if (ATI_fragment_shader)
- glDisable(GL_FRAGMENT_SHADER_ATI);
- }
-