home *** CD-ROM | disk | FTP | other *** search
/ Computer Shopper 275 / DPCS0111DVD.ISO / Toolkit / Audio-Visual / VirtualDub / Source / VirtualDub-1.9.10-src.7z / src / Riza / source / opengl.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2009-09-14  |  24.3 KB  |  951 lines

  1. //    VirtualDub - Video processing and capture application
  2. //    A/V interface library
  3. //    Copyright (C) 1998-2006 Avery Lee
  4. //
  5. //    This program is free software; you can redistribute it and/or modify
  6. //    it under the terms of the GNU General Public License as published by
  7. //    the Free Software Foundation; either version 2 of the License, or
  8. //    (at your option) any later version.
  9. //
  10. //    This program is distributed in the hope that it will be useful,
  11. //    but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. //    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13. //    GNU General Public License for more details.
  14. //
  15. //    You should have received a copy of the GNU General Public License
  16. //    along with this program; if not, write to the Free Software
  17. //    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  18.  
  19. #include <vd2/system/vdtypes.h>
  20. #include <vd2/Riza/opengl.h>
  21. #include <windows.h>
  22.  
  23. namespace {
  24.     static const char *const kWGLFunctions[]={
  25.         "wglCreateContext",
  26.         "wglDeleteContext",
  27.         "wglMakeCurrent",
  28.         "wglGetProcAddress",
  29.         "wglSwapBuffers",
  30.         "wglUseFontBitmapsA",
  31.     };
  32.  
  33.     static const char *const kGLFunctions[]={
  34.         "glAlphaFunc",
  35.         "glBegin",
  36.         "glBindTexture",
  37.         "glBlendFunc",
  38.         "glCallList",
  39.         "glClear",
  40.         "glClearColor",
  41.         "glColor4d",
  42.         "glColor4f",
  43.         "glColor4ub",
  44.         "glColorMask",
  45.         "glCopyTexSubImage2D",
  46.         "glDeleteLists",
  47.         "glDeleteTextures",
  48.         "glDepthFunc",
  49.         "glDepthMask",
  50.         "glDisable",
  51.         "glDrawBuffer",
  52.         "glEnable",
  53.         "glEnd",
  54.         "glEndList",
  55.         "glFeedbackBuffer",
  56.         "glFinish",
  57.         "glFlush",
  58.         "glFrontFace",
  59.         "glGetError",
  60.         "glGetFloatv",
  61.         "glGetIntegerv",
  62.         "glGetTexLevelParameteriv",
  63.         "glGenLists",
  64.         "glGetString",
  65.         "glGenTextures",
  66.         "glLoadIdentity",
  67.         "glLoadMatrixd",
  68.         "glMatrixMode",
  69.         "glNewList",
  70.         "glOrtho",
  71.         "glPixelStorei",
  72.         "glPopAttrib",
  73.         "glPushAttrib",
  74.         "glReadBuffer",
  75.         "glReadPixels",
  76.         "glRenderMode",
  77.         "glTexCoord2d",
  78.         "glTexCoord2f",
  79.         "glTexCoord2fv",
  80.         "glTexEnvf",
  81.         "glTexEnvi",
  82.         "glTexImage1D",
  83.         "glTexImage2D",
  84.         "glTexParameterfv",
  85.         "glTexParameteri",
  86.         "glTexSubImage1D",
  87.         "glTexSubImage2D",
  88.         "glVertex2d",
  89.         "glVertex2f",
  90.         "glVertex2i",
  91.         "glVertex3fv",
  92.         "glViewport",
  93.     };
  94.  
  95.     static const char *const kGLExtFunctions[]={
  96.         // ARB_multitexture
  97.         "glActiveTextureARB",
  98.         "glMultiTexCoord2fARB",
  99.  
  100.         // ARB_vertex_buffer_object (EXT_pixel_buffer_object/ARB_pixel_buffer_object)
  101.         "glBindBufferARB",
  102.         "glDeleteBuffersARB",
  103.         "glGenBuffersARB",
  104.         "glIsBufferARB",
  105.         "glBufferDataARB",
  106.         "glBufferSubDataARB",
  107.         "glGetBufferSubDataARB",
  108.         "glMapBufferARB",
  109.         "glUnmapBufferARB",
  110.         "glGetBufferParameterivARB",
  111.         "glGetBufferPointervARB",
  112.  
  113.         // NV_register_combiners
  114.         "glCombinerParameterfvNV",
  115.         "glCombinerParameterivNV",
  116.         "glCombinerParameterfNV",
  117.         "glCombinerParameteriNV",
  118.         "glCombinerInputNV",
  119.         "glCombinerOutputNV",
  120.         "glFinalCombinerInputNV",
  121.         "glGetCombinerInputParameterfvNV",
  122.         "glGetCombinerInputParameterivNV",
  123.         "glGetCombinerOutputParameterfvNV",
  124.         "glGetCombinerOutputParameterivNV",
  125.         "glGetFinalCombinerInputParameterfvNV",
  126.         "glGetFinalCombinerInputParameterivNV",
  127.  
  128.         // NV_register_combiners2
  129.         "glCombinerStageParameterfvNV",
  130.  
  131.         // ATI_fragment_shader
  132.         "glGenFragmentShadersATI",
  133.         "glBindFragmentShaderATI",
  134.         "glDeleteFragmentShaderATI",
  135.         "glBeginFragmentShaderATI",
  136.         "glEndFragmentShaderATI",
  137.         "glPassTexCoordATI",
  138.         "glSampleMapATI",
  139.         "glColorFragmentOp1ATI",
  140.         "glColorFragmentOp2ATI",
  141.         "glColorFragmentOp3ATI",
  142.         "glAlphaFragmentOp1ATI",
  143.         "glAlphaFragmentOp2ATI",
  144.         "glAlphaFragmentOp3ATI",
  145.         "glSetFragmentShaderConstantATI",
  146.  
  147.         // NV_occlusion_query
  148.         "glGenOcclusionQueriesNV",
  149.         "glDeleteOcclusionQueriesNV",
  150.         "glIsOcclusionQueryNV",
  151.         "glBeginOcclusionQueryNV",
  152.         "glEndOcclusionQueryNV",
  153.         "glGetOcclusionQueryivNV",
  154.         "glGetOcclusionQueryuivNV",
  155.  
  156.         // EXT_framebuffer_object
  157.         "glIsRenderbufferEXT",
  158.         "glBindRenderbufferEXT",
  159.         "glDeleteRenderbuffersEXT",
  160.         "glGenRenderbuffersEXT",
  161.         "glRenderbufferStorageEXT",
  162.         "glGetRenderbufferParameterivEXT",
  163.         "glIsFramebufferEXT",
  164.         "glBindFramebufferEXT",
  165.         "glDeleteFramebuffersEXT",
  166.         "glGenFramebuffersEXT",
  167.         "glCheckFramebufferStatusEXT",
  168.         "glFramebufferTexture1DEXT",
  169.         "glFramebufferTexture2DEXT",
  170.         "glFramebufferTexture3DEXT",
  171.         "glFramebufferRenderbufferEXT",
  172.         "glGetFramebufferAttachmentParameterivEXT",
  173.         "glGenerateMipmapEXT",
  174.  
  175.         // ARB_vertex_program
  176.         "glVertexAttrib1sARB",
  177.         "glVertexAttrib1fARB",
  178.         "glVertexAttrib1dARB",
  179.         "glVertexAttrib2sARB",
  180.         "glVertexAttrib2fARB",
  181.         "glVertexAttrib2dARB",
  182.         "glVertexAttrib3sARB",
  183.         "glVertexAttrib3fARB",
  184.         "glVertexAttrib3dARB",
  185.         "glVertexAttrib4sARB",
  186.         "glVertexAttrib4fARB",
  187.         "glVertexAttrib4dARB",
  188.         "glVertexAttrib4NubARB",
  189.         "glVertexAttrib1svARB",
  190.         "glVertexAttrib1fvARB",
  191.         "glVertexAttrib1dvARB",
  192.         "glVertexAttrib2svARB",
  193.         "glVertexAttrib2fvARB",
  194.         "glVertexAttrib2dvARB",
  195.         "glVertexAttrib3svARB",
  196.         "glVertexAttrib3fvARB",
  197.         "glVertexAttrib3dvARB",
  198.         "glVertexAttrib4bvARB",
  199.         "glVertexAttrib4svARB",
  200.         "glVertexAttrib4ivARB",
  201.         "glVertexAttrib4ubvARB",
  202.         "glVertexAttrib4usvARB",
  203.         "glVertexAttrib4uivARB",
  204.         "glVertexAttrib4fvARB",
  205.         "glVertexAttrib4dvARB",
  206.         "glVertexAttrib4NbvARB",
  207.         "glVertexAttrib4NsvARB",
  208.         "glVertexAttrib4NivARB",
  209.         "glVertexAttrib4NubvARB",
  210.         "glVertexAttrib4NusvARB",
  211.         "glVertexAttrib4NuivARB",
  212.         "glVertexAttribPointerARB",
  213.         "glEnableVertexAttribArrayARB",
  214.         "glDisableVertexAttribArrayARB",
  215.         "glProgramStringARB",
  216.         "glBindProgramARB",
  217.         "glDeleteProgramsARB",
  218.         "glGenProgramsARB",
  219.         "glProgramEnvParameter4dARB",
  220.         "glProgramEnvParameter4dvARB",
  221.         "glProgramEnvParameter4fARB",
  222.         "glProgramEnvParameter4fvARB",
  223.         "glProgramLocalParameter4dARB",
  224.         "glProgramLocalParameter4dvARB",
  225.         "glProgramLocalParameter4fARB",
  226.         "glProgramLocalParameter4fvARB",
  227.         "glGetProgramEnvParameterdvARB",
  228.         "glGetProgramEnvParameterfvARB",
  229.         "glGetProgramLocalParameterdvARB",
  230.         "glGetProgramLocalParameterfvARB",
  231.         "glGetProgramivARB",
  232.         "glGetProgramStringARB",
  233.         "glGetVertexAttribdvARB",
  234.         "glGetVertexAttribfvARB",
  235.         "glGetVertexAttribivARB",
  236.         "glGetVertexAttribPointervARB",
  237.         "glIsProgramARB",
  238.  
  239.         // EXT_blend_minmax
  240.         "glBlendEquationEXT",
  241.  
  242.         // EXT_secondary_color
  243.         "glSecondaryColor3ubEXT",
  244.  
  245.         // WGL_ARB_extensions_string
  246.         "wglGetExtensionsStringARB",
  247.  
  248.         // WGL_EXT_extensions_string
  249.         "wglGetExtensionsStringEXT",
  250.  
  251.         // WGL_ARB_make_current_read
  252.         "wglMakeContextCurrentARB",
  253.         "wglGetCurrentReadDCARB",
  254.  
  255.         // WGL_EXT_swap_control
  256.         "wglSwapIntervalEXT",
  257.         "wglGetSwapIntervalEXT",
  258.     };
  259. }
  260.  
  261. VDOpenGLBinding::VDOpenGLBinding()
  262.     : mhmodOGL(NULL)
  263.     , mhdc(NULL)
  264.     , mhglrc(NULL)
  265. {
  266. }
  267.  
  268. VDOpenGLBinding::~VDOpenGLBinding() {
  269. }
  270.  
  271. bool VDOpenGLBinding::Init() {
  272.     mhmodOGL = LoadLibrary("opengl32");
  273.     if (!mhmodOGL)
  274.         return false;
  275.  
  276.     // pull wgl functions
  277.     for(int i=0; i<sizeof(kWGLFunctions)/sizeof(kWGLFunctions[0]); ++i) {
  278.         void *p = (void *)GetProcAddress(mhmodOGL, kWGLFunctions[i]);
  279.  
  280.         if (!p) {
  281.             Shutdown();
  282.             return false;
  283.         }
  284.  
  285.         ((void **)static_cast<VDAPITableWGL *>(this))[i] = p;
  286.     }
  287.  
  288.     return true;
  289. }
  290.  
  291. void VDOpenGLBinding::Shutdown() {
  292.     End();
  293.     Detach();
  294.  
  295.     if (mhmodOGL) {
  296.         FreeLibrary(mhmodOGL);
  297.         mhmodOGL = NULL;
  298.     }
  299. }
  300.  
  301. bool VDOpenGLBinding::Attach(HDC hdc, int minColorBits, int minAlphaBits, int minDepthBits, int minStencilBits, bool doubleBuffer) {
  302.     PIXELFORMATDESCRIPTOR pfd={};
  303.  
  304.     pfd.nSize            = sizeof(PIXELFORMATDESCRIPTOR);
  305.     pfd.nVersion        = 1;
  306.     pfd.dwFlags            = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL;
  307.     if (doubleBuffer)
  308.         pfd.dwFlags |= PFD_DOUBLEBUFFER;
  309.     pfd.iPixelType        = PFD_TYPE_RGBA;
  310.     pfd.cColorBits        = minColorBits;
  311.     pfd.cAlphaBits        = minAlphaBits;
  312.     pfd.cDepthBits        = minDepthBits;
  313.     pfd.cStencilBits    = minStencilBits;
  314.     pfd.iLayerType        = PFD_MAIN_PLANE;
  315.  
  316.     int pf = ChoosePixelFormat(hdc, &pfd);
  317.     if (!pf) {
  318.         Detach();
  319.         return false;
  320.     }
  321.  
  322.     if (!SetPixelFormat(hdc, pf, &pfd)) {
  323.         Detach();
  324.         return false;
  325.     }
  326.  
  327.     mhglrc = wglCreateContext(hdc);
  328.     if (!mhglrc)
  329.         return false;
  330.  
  331.     if (!Begin(hdc)) {
  332.         Detach();
  333.         return false;
  334.     }
  335.  
  336.     for(int i=0; i<sizeof(kGLFunctions)/sizeof(kGLFunctions[0]); ++i) {
  337.         void *p = (void *)GetProcAddress(mhmodOGL, kGLFunctions[i]);
  338.  
  339.         if (!p) {
  340.             Detach();
  341.             return false;
  342.         }
  343.  
  344.         ((void **)static_cast<VDAPITableOpenGL *>(this))[i] = p;
  345.     }
  346.  
  347.     for(int i=0; i<sizeof(kGLExtFunctions)/sizeof(kGLExtFunctions[0]); ++i) {
  348.         void *p = (void *)wglGetProcAddress(kGLExtFunctions[i]);
  349.  
  350.         ((void **)static_cast<VDAPITableOpenGLEXT *>(this))[i] = p;
  351.     }
  352.  
  353.     const char *ext = (const char *)glGetString(GL_EXTENSIONS);
  354.  
  355.     ARB_fragment_program = false;
  356.     ARB_multitexture = false;
  357.     ARB_pixel_buffer_object = false;
  358.     ARB_vertex_program = false;
  359.     ATI_fragment_shader = false;
  360.     EXT_blend_minmax = false;
  361.     EXT_blend_subtract = false;
  362.     EXT_framebuffer_object = false;
  363.     EXT_pixel_buffer_object = false;
  364.     EXT_texture_env_combine = false;
  365.     EXT_texture_edge_clamp = false;
  366.     NV_occlusion_query = false;
  367.     NV_register_combiners = false;
  368.     NV_register_combiners2 = false;
  369.  
  370.     if (ext) {
  371.         for(;;) {
  372.             while(*ext == ' ')
  373.                 ++ext;
  374.  
  375.             if (!*ext)
  376.                 break;
  377.  
  378.             const char *start = ext;
  379.             while(*ext && *ext != ' ')
  380.                 ++ext;
  381.  
  382.             int len = ext - start;
  383.  
  384.             switch(len) {
  385.             case 19:
  386.                 if (!memcmp(start, "GL_ARB_multitexture", 19))
  387.                     ARB_multitexture = true;
  388.                 else if (!memcmp(start, "GL_EXT_blend_minmax", 19))
  389.                     EXT_blend_minmax = true;
  390.                 break;
  391.  
  392.             case 20:
  393.                 if (!memcmp(start, "GL_EXT_blend_subtract", 20))
  394.                     EXT_blend_subtract = true;
  395.                 break;
  396.  
  397.             case 21:
  398.                 if (!memcmp(start, "GL_NV_occlusion_query", 21))
  399.                     NV_occlusion_query = true;
  400.                 else if (!memcmp(start, "GL_ARB_vertex_program", 21))
  401.                     ARB_vertex_program = true;
  402.                 break;
  403.  
  404.             case 22:
  405.                 if (!memcmp(start, "GL_ATI_fragment_shader", 22))
  406.                     ATI_fragment_shader = true;
  407.                 else if (!memcmp(start, "GL_EXT_secondary_color", 22))
  408.                     EXT_secondary_color = true;
  409.                 break;
  410.  
  411.             case 23:
  412.                 if (!memcmp(start, "GL_ARB_fragment_program", 23))
  413.                     ARB_fragment_program = true;
  414.                 break;
  415.  
  416.             case 24:
  417.                 if (!memcmp(start, "GL_NV_register_combiners", 24))
  418.                     NV_register_combiners = true;
  419.                 break;
  420.             case 25:
  421.                 if (!memcmp(start, "GL_NV_register_combiners2", 25))
  422.                     NV_register_combiners2 = true;
  423.                 else if (!memcmp(start, "GL_EXT_framebuffer_object", 25))
  424.                     EXT_framebuffer_object = true;
  425.                 else if (!memcmp(start, "GL_EXT_texture_edge_clamp", 25))
  426.                     EXT_texture_edge_clamp = true;
  427.                 break;
  428.             case 26:
  429.                 if (!memcmp(start, "GL_EXT_pixel_buffer_object", 26))
  430.                     EXT_pixel_buffer_object = true;
  431.                 else if (!memcmp(start, "GL_ARB_pixel_buffer_object", 26))
  432.                     EXT_pixel_buffer_object = ARB_pixel_buffer_object = true;
  433.                 else if (!memcmp(start, "GL_EXT_texture_env_combine", 26))
  434.                     EXT_texture_env_combine = true;
  435.                 else if (!memcmp(start, "GL_ARB_texture_env_combine", 26))
  436.                     EXT_texture_env_combine = true;
  437.                 break;
  438.             }
  439.         }
  440.     }
  441.  
  442.     ext = NULL;
  443.     if (wglGetExtensionsStringARB)
  444.         ext = wglGetExtensionsStringARB(hdc);
  445.     else if (wglGetExtensionsStringEXT)
  446.         ext = wglGetExtensionsStringEXT();
  447.  
  448.     EXT_swap_control = false;
  449.     ARB_make_current_read = false;
  450.     if (ext) {
  451.         for(;;) {
  452.             while(*ext == ' ')
  453.                 ++ext;
  454.  
  455.             if (!*ext)
  456.                 break;
  457.  
  458.             const char *start = ext;
  459.             while(*ext && *ext != ' ')
  460.                 ++ext;
  461.  
  462.             int len = ext - start;
  463.  
  464.             switch(len) {
  465.             case 20:
  466.                 if (!memcmp(start, "WGL_EXT_swap_control", 20))
  467.                     EXT_swap_control = true;
  468.                 break;
  469.             case 25:
  470.                 if (!memcmp(start, "WGL_ARB_make_current_read", 25))
  471.                     ARB_make_current_read = true;
  472.                 break;
  473.             }
  474.         }
  475.     }
  476.  
  477.     End();
  478.  
  479.     return true;
  480. }
  481.  
  482. bool VDOpenGLBinding::AttachAux(HDC hdc, int minColorBits, int minAlphaBits, int minDepthBits, int minStencilBits, bool doubleBuffer) {
  483.     PIXELFORMATDESCRIPTOR pfd={};
  484.  
  485.     pfd.nSize            = sizeof(PIXELFORMATDESCRIPTOR);
  486.     pfd.nVersion        = 1;
  487.     pfd.dwFlags            = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL;
  488.     if (doubleBuffer)
  489.         pfd.dwFlags |= PFD_DOUBLEBUFFER;
  490.     pfd.iPixelType        = PFD_TYPE_RGBA;
  491.     pfd.cColorBits        = minColorBits;
  492.     pfd.cAlphaBits        = minAlphaBits;
  493.     pfd.cDepthBits        = minDepthBits;
  494.     pfd.cStencilBits    = minStencilBits;
  495.     pfd.iLayerType        = PFD_MAIN_PLANE;
  496.  
  497.     int pf = ChoosePixelFormat(hdc, &pfd);
  498.     if (!pf)
  499.         return false;
  500.  
  501.     if (!SetPixelFormat(hdc, pf, &pfd))
  502.         return false;
  503.  
  504.     return true;
  505. }
  506.  
  507. void VDOpenGLBinding::Detach() {
  508.     if (mhglrc) {
  509.         wglDeleteContext(mhglrc);
  510.         mhglrc = NULL;
  511.     }
  512. }
  513.  
  514. bool VDOpenGLBinding::Begin(HDC hdc) {
  515.     if (!wglMakeCurrent(hdc, mhglrc))
  516.         return false;
  517.  
  518.     mhdc = hdc;
  519.     return true;
  520. }
  521.  
  522. void VDOpenGLBinding::End() {
  523.     if (mhdc) {
  524.         wglMakeCurrent(mhdc, NULL);
  525.         mhdc = NULL;
  526.     }
  527. }
  528.  
  529. namespace {
  530.     void CreateNVRegisterCombinerSetup(VDOpenGLBinding& gl, const VDOpenGLNVRegisterCombinerConfig& config, bool nvrc2) {
  531.         // load base constants
  532.         if (!nvrc2) {
  533.             for(int i=0; i<config.mConstantCount; ++i)
  534.                 gl.glCombinerParameterfvNV(GL_CONSTANT_COLOR0_NV + i, config.mpConstants[i]);
  535.         }
  536.  
  537.         static const GLenum kRegisterTable[16]={
  538.             GL_ZERO,
  539.             GL_DISCARD_NV,
  540.             GL_SPARE0_NV,
  541.             GL_SPARE1_NV,
  542.             GL_PRIMARY_COLOR_NV,
  543.             GL_SECONDARY_COLOR_NV,
  544.             GL_CONSTANT_COLOR0_NV,
  545.             GL_CONSTANT_COLOR1_NV,
  546.             GL_SPARE0_PLUS_SECONDARY_COLOR_NV,
  547.             GL_E_TIMES_F_NV,
  548.             GL_ZERO,
  549.             GL_ZERO,
  550.             GL_TEXTURE0_ARB,
  551.             GL_TEXTURE1_ARB,
  552.             GL_TEXTURE2_ARB,
  553.             GL_TEXTURE3_ARB,
  554.         };
  555.  
  556.         static const GLenum kScaleTable[4]={
  557.             GL_NONE,
  558.             GL_SCALE_BY_TWO_NV,
  559.             GL_SCALE_BY_FOUR_NV,
  560.             GL_SCALE_BY_ONE_HALF_NV,
  561.         };
  562.  
  563.         static const GLenum kSourceMappingTable[8]={
  564.             GL_UNSIGNED_IDENTITY_NV,
  565.             GL_UNSIGNED_INVERT_NV,
  566.             GL_SIGNED_IDENTITY_NV,
  567.             GL_SIGNED_NEGATE_NV,
  568.             GL_EXPAND_NORMAL_NV,
  569.             GL_EXPAND_NEGATE_NV,
  570.             GL_HALF_BIAS_NORMAL_NV,
  571.             GL_HALF_BIAS_NEGATE_NV
  572.         };
  573.  
  574.         // create combiner stages
  575.         const uint8 *src = config.mpByteCode;
  576.         for(int stage=0; stage<config.mGeneralCombinerCount; ++stage) {
  577.             GLenum stageToken = GL_COMBINER0_NV + stage;
  578.  
  579.             // load per-stage colors
  580.             if (nvrc2) {
  581.                 uint8 c0 = src[0];
  582.                 uint8 c1 = src[1];
  583.                 src += 2;
  584.  
  585.                 if (c0 != 0xff)
  586.                     gl.glCombinerStageParameterfvNV(GL_COMBINER0_NV + stage, GL_CONSTANT_COLOR0_NV, config.mpConstants[c0]);
  587.                 if (c1 != 0xff)
  588.                     gl.glCombinerStageParameterfvNV(GL_COMBINER0_NV + stage, GL_CONSTANT_COLOR1_NV, config.mpConstants[c1]);
  589.                 VDASSERT(!gl.glGetError());
  590.             }
  591.  
  592.             // load combiner halves
  593.             for(int half=0; half<2; ++half) {
  594.                 GLenum portionToken = half ? GL_ALPHA : GL_RGB;
  595.  
  596.                 // decode output
  597.                 GLenum dst0 = kRegisterTable[src[0] >> 4];
  598.                 GLenum dst1 = kRegisterTable[src[1] & 15];
  599.                 GLenum dst2 = kRegisterTable[src[1] >> 4];
  600.                 GLenum dstscale = kScaleTable[src[0] & 3];
  601.                 GLenum dstbias = src[0] & 4 ? GL_BIAS_BY_NEGATIVE_ONE_HALF_NV : GL_NONE;
  602.                 GLenum dstDotAB = src[2] & 1 ? GL_TRUE : GL_FALSE;
  603.                 GLenum dstDotCD = src[2] & 2 ? GL_TRUE : GL_FALSE;
  604.                 GLenum dstMux = src[2] & 4 ? GL_TRUE : GL_FALSE;
  605.                 src += 3;
  606.  
  607.                 gl.glCombinerOutputNV(stageToken, portionToken, dst0, dst1, dst2, dstscale, dstbias, dstDotAB, dstDotCD, dstMux);
  608.                 VDASSERT(!gl.glGetError());
  609.  
  610.                 // decode sources
  611.                 for(int i=0; i<4; ++i) {
  612.                     uint8 c = *src++;
  613.                     GLenum srcreg = kRegisterTable[c & 15];
  614.                     GLenum srcmap = kSourceMappingTable[(c >> 4) & 7];
  615.                     GLenum srcportion = c & 0x80 ? GL_ALPHA : half ? GL_BLUE : GL_RGB;
  616.  
  617.                     gl.glCombinerInputNV(stageToken, portionToken, GL_VARIABLE_A_NV + i, srcreg, srcmap, srcportion);
  618.                     VDASSERT(!gl.glGetError());
  619.                 }
  620.             }
  621.         }
  622.  
  623.         gl.glCombinerParameteriNV(GL_NUM_GENERAL_COMBINERS_NV, config.mGeneralCombinerCount);
  624.  
  625.         // load final combiner
  626.         if (nvrc2) {
  627.             uint8 c0 = src[0];
  628.             uint8 c1 = src[1];
  629.             src += 2;
  630.  
  631.             if (c0 != 0xff)
  632.                 gl.glCombinerParameterfvNV(GL_CONSTANT_COLOR0_NV, config.mpConstants[c0]);
  633.             if (c1 != 0xff)
  634.                 gl.glCombinerParameterfvNV(GL_CONSTANT_COLOR1_NV, config.mpConstants[c1]);
  635.             VDASSERT(!gl.glGetError());
  636.         }
  637.  
  638.         for(int i=0; i<7; ++i) {
  639.             uint8 c = *src++;
  640.             GLenum srcreg = kRegisterTable[c & 15];
  641.             GLenum srcmap = kSourceMappingTable[(c >> 4) & 7];
  642.             GLenum srcportion = c & 0x80 ? GL_ALPHA : i == 6 ? GL_BLUE : GL_RGB;
  643.  
  644.             gl.glFinalCombinerInputNV(GL_VARIABLE_A_NV + i, srcreg, srcmap, srcportion);
  645.             VDASSERT(!gl.glGetError());
  646.         }
  647.     }
  648.  
  649.     void CreateATIFragmentShader(VDOpenGLBinding& gl, const VDOpenGLATIFragmentShaderConfig& config) {
  650.         enum {
  651.             kTexAddrT0            = 0x00,
  652.             kTexAddrT1            = 0x01,
  653.             kTexAddrT2            = 0x02,
  654.             kTexAddrT3            = 0x03,
  655.             kTexAddrT4            = 0x04,
  656.             kTexAddrT5            = 0x05,
  657.             kTexAddrR0            = 0x08,
  658.             kTexAddrR1            = 0x09,
  659.             kTexAddrR2            = 0x0A,
  660.             kTexAddrR3            = 0x0B,
  661.             kTexAddrR4            = 0x0C,
  662.             kTexAddrR5            = 0x0D,
  663.             kTexSwizzleXYZ        = 0x00,
  664.             kTexSwizzleXYW        = 0x10,
  665.             kTexSwizzleXYZ_DZ    = 0x20,
  666.             kTexSwizzleXYW_DW    = 0x30,
  667.             kTexSwizzleMask        = 0x30,
  668.             kTexModeTexcrd        = 0x40,
  669.             kTexModeTexld        = 0x80,
  670.             kTexModeMask        = 0xC0
  671.         };
  672.  
  673.         enum {
  674.             kChannelOpAdd,
  675.             kChannelOpSub,
  676.             kChannelOpMul,
  677.             kChannelOpMad,
  678.             kChannelOpLerp,
  679.             kChannelOpMov,
  680.             kChannelOpCnd,
  681.             kChannelOpCnd0,
  682.             kChannelOpDot2Add,
  683.             kChannelOpDot3,
  684.             kChannelOpDot4,
  685.             kChannelOpTexcrd,
  686.             kChannelOpTexld,
  687.             kChannelOpMask            = 0x0F,
  688.             kChannelOpModScaleMask    = 0x70,
  689.             kChannelOpModScaleX2    = 0x10,
  690.             kChannelOpModScaleX4    = 0x20,
  691.             kChannelOpModScaleX8    = 0x30,
  692.             kChannelOpModScaleD2    = 0x40,
  693.             kChannelOpModScaleD4    = 0x50,
  694.             kChannelOpModScaleD8    = 0x60,
  695.             kChannelOpModSaturate    = 0x80
  696.         };
  697.  
  698.         enum {
  699.             kChanRegR0,
  700.             kChanRegR1,
  701.             kChanRegR2,
  702.             kChanRegR3,
  703.             kChanRegR4,
  704.             kChanRegR5,
  705.             kChanRegC0,
  706.             kChanRegC1,
  707.             kChanRegC2,
  708.             kChanRegC3,
  709.             kChanRegC4,
  710.             kChanRegC5,
  711.             kChanRegC6,
  712.             kChanRegC7,
  713.             kChanRegZero,
  714.             kChanRegOne,
  715.             kChanRegV0,
  716.             kChanRegV1,
  717.             kChanSrcMod2X        = 0x01,
  718.             kChanSrcModComp        = 0x02,
  719.             kChanSrcModNegate    = 0x04,
  720.             kChanSrcModBias        = 0x08,
  721.             kChanSrcSwizzleRed        = 0x10,
  722.             kChanSrcSwizzleGreen    = 0x20,
  723.             kChanSrcSwizzleBlue        = 0x30,
  724.             kChanSrcSwizzleAlpha    = 0x40,
  725.             kChanDstMaskRed        = 0x10,
  726.             kChanDstMaskGreen    = 0x20,
  727.             kChanDstMaskBlue    = 0x40,
  728.             kChanDstMaskAlpha    = 0x80
  729.         };
  730.  
  731.         VDASSERT(!gl.glGetError());
  732.         gl.glBeginFragmentShaderATI();
  733.  
  734.         // load constants
  735.         for(uint8 i=0; i<config.mConstantCount; ++i)
  736.             gl.glSetFragmentShaderConstantATI(GL_CON_0_ATI + i, config.mpConstants[i]);
  737.         VDASSERT(!gl.glGetError());
  738.  
  739.         // create passes
  740.         const uint8 *src = config.mpByteCode;
  741.         while(uint8 opCount = *src++) {
  742.             // set up texture interpolators
  743.             for(int i=0; i<6; ++i) {
  744.                 uint8 texOp = *src++;
  745.  
  746.                 if (!texOp)
  747.                     continue;
  748.  
  749.                 static const GLenum kTexSwizzleMode[4]={
  750.                     GL_SWIZZLE_STR_ATI,
  751.                     GL_SWIZZLE_STQ_ATI,
  752.                     GL_SWIZZLE_STR_DR_ATI,
  753.                     GL_SWIZZLE_STQ_DQ_ATI
  754.                 };
  755.  
  756.                 GLenum dst = GL_REG_0_ATI + i;
  757.                 GLenum src = (texOp & 8 ? GL_REG_0_ATI : GL_TEXTURE0_ARB) + (texOp & 7);
  758.                 GLenum swizzle = kTexSwizzleMode[(texOp >> 4) & 3];
  759.  
  760.                 switch(texOp & kTexModeMask) {
  761.                     case kTexModeTexcrd:
  762.                         gl.glPassTexCoordATI(dst, src, swizzle);
  763.                         break;
  764.                     case kTexModeTexld:
  765.                         gl.glSampleMapATI(dst, src, swizzle);
  766.                         break;
  767.                 }
  768.             }
  769.             VDASSERT(!gl.glGetError());
  770.  
  771.             // set up alu ops
  772.             while(opCount--) {
  773.                 static const GLenum kOpTable[][2]={
  774.                     { GL_ADD_ATI, 2 },
  775.                     { GL_SUB_ATI, 2 },
  776.                     { GL_MUL_ATI, 2 },
  777.                     { GL_MAD_ATI, 3 },
  778.                     { GL_LERP_ATI, 3 },
  779.                     { GL_MOV_ATI, 1 },
  780.                     { GL_CND_ATI, 3 },
  781.                     { GL_CND0_ATI, 3 },
  782.                     { GL_DOT2_ADD_ATI, 3 },
  783.                     { GL_DOT3_ATI, 2 },
  784.                     { GL_DOT4_ATI, 2 },
  785.                 };
  786.  
  787.                 static const GLuint kDstModTable[16]={
  788.                     GL_NONE,
  789.                     GL_2X_BIT_ATI,
  790.                     GL_4X_BIT_ATI,
  791.                     GL_8X_BIT_ATI,
  792.                     GL_HALF_BIT_ATI,
  793.                     GL_QUARTER_BIT_ATI,
  794.                     GL_EIGHTH_BIT_ATI,
  795.                     GL_NONE,
  796.                     GL_SATURATE_BIT_ATI,
  797.                     GL_SATURATE_BIT_ATI | GL_2X_BIT_ATI,
  798.                     GL_SATURATE_BIT_ATI | GL_4X_BIT_ATI,
  799.                     GL_SATURATE_BIT_ATI | GL_8X_BIT_ATI,
  800.                     GL_SATURATE_BIT_ATI | GL_HALF_BIT_ATI,
  801.                     GL_SATURATE_BIT_ATI | GL_QUARTER_BIT_ATI,
  802.                     GL_SATURATE_BIT_ATI | GL_EIGHTH_BIT_ATI,
  803.                     GL_SATURATE_BIT_ATI,
  804.                 };
  805.  
  806.                 static const GLenum kRegTable[]={
  807.                     GL_REG_0_ATI,
  808.                     GL_REG_1_ATI,
  809.                     GL_REG_2_ATI,
  810.                     GL_REG_3_ATI,
  811.                     GL_REG_4_ATI,
  812.                     GL_REG_5_ATI,
  813.                     GL_CON_0_ATI,
  814.                     GL_CON_1_ATI,
  815.                     GL_CON_2_ATI,
  816.                     GL_CON_3_ATI,
  817.                     GL_CON_4_ATI,
  818.                     GL_CON_5_ATI,
  819.                     GL_CON_6_ATI,
  820.                     GL_CON_7_ATI,
  821.                     GL_ZERO,
  822.                     GL_ONE,
  823.                     GL_PRIMARY_COLOR_ARB,
  824.                     GL_SECONDARY_INTERPOLATOR_ATI
  825.                 };
  826.  
  827.                 static const GLenum kRepTable[]={
  828.                     GL_NONE,
  829.                     GL_RED,
  830.                     GL_GREEN,
  831.                     GL_BLUE,
  832.                     GL_ALPHA
  833.                 };
  834.  
  835.                 const uint8 opcode = *src++;
  836.                 const uint8 dstarg = *src++;
  837.  
  838.                 GLenum op = kOpTable[opcode & 15][0];
  839.                 GLenum dstMod = kDstModTable[opcode >> 4];
  840.                 GLenum dstReg = kRegTable[dstarg & 15];
  841.                 GLuint rgbMask = (dstarg >> 4) & 7;
  842.                 bool alphaMask = (dstarg & 0x80) != 0;
  843.  
  844.                 int srcCount = kOpTable[opcode & 15][1];
  845.                 GLenum srcReg[3];
  846.                 GLenum srcRep[3];
  847.                 GLuint srcMod[3];
  848.                 for(int i=0; i<srcCount; ++i) {
  849.                     const uint8 mod = src[1];
  850.  
  851.                     srcReg[i] = kRegTable[src[0]];
  852.                     srcRep[i] = kRepTable[mod >> 4];
  853.                     srcMod[i] = mod & 15;
  854.                     src += 2;
  855.                 }
  856.  
  857.                 switch(srcCount) {
  858.                     case 1:
  859.                         if (rgbMask)
  860.                             gl.glColorFragmentOp1ATI(op, dstReg, rgbMask, dstMod, srcReg[0], srcRep[0], srcMod[0]);
  861.                         if (alphaMask)
  862.                             gl.glAlphaFragmentOp1ATI(op, dstReg, dstMod, srcReg[0], srcRep[0], srcMod[0]);
  863.                         break;
  864.                     case 2:
  865.                         if (rgbMask)
  866.                             gl.glColorFragmentOp2ATI(op, dstReg, rgbMask, dstMod, srcReg[0], srcRep[0], srcMod[0], srcReg[1], srcRep[1], srcMod[1]);
  867.                         if (alphaMask)
  868.                             gl.glAlphaFragmentOp2ATI(op, dstReg, dstMod, srcReg[0], srcRep[0], srcMod[0], srcReg[1], srcRep[1], srcMod[1]);
  869.                         break;
  870.                     case 3:
  871.                         if (rgbMask)
  872.                             gl.glColorFragmentOp3ATI(op, dstReg, rgbMask, dstMod, srcReg[0], srcRep[0], srcMod[0], srcReg[1], srcRep[1], srcMod[1], srcReg[2], srcRep[2], srcMod[2]);
  873.                         if (alphaMask)
  874.                             gl.glAlphaFragmentOp3ATI(op, dstReg, dstMod, srcReg[0], srcRep[0], srcMod[0], srcReg[1], srcRep[1], srcMod[1], srcReg[2], srcRep[2], srcMod[2]);
  875.                         break;
  876.                 }
  877.                 VDASSERT(!gl.glGetError());
  878.  
  879.             }
  880.         }
  881.  
  882.         gl.glEndFragmentShaderATI();
  883.         VDASSERT(!gl.glGetError());
  884.     }
  885. }
  886.  
  887. GLenum VDOpenGLBinding::InitTechniques(const VDOpenGLTechnique *techniques, int techniqueCount) {
  888.     GLuint listBase = glGenLists(techniqueCount);
  889.  
  890.     for(int i=0; i<techniqueCount; ++i) {
  891.         const VDOpenGLTechnique& tech = techniques[i];
  892.         GLenum shader;
  893.  
  894.         switch(tech.mFragmentShaderMode) {
  895.         case kVDOpenGLFragmentShaderModeNVRC2:
  896.             if (!NV_register_combiners2)
  897.                 continue;
  898.             // fall through
  899.         case kVDOpenGLFragmentShaderModeNVRC:
  900.             if (!NV_register_combiners)
  901.                 continue;
  902.             break;
  903.         case kVDOpenGLFragmentShaderModeATIFS:
  904.             if (!ATI_fragment_shader)
  905.                 continue;
  906.             break;
  907.         }
  908.  
  909.         if (tech.mFragmentShaderMode == kVDOpenGLFragmentShaderModeATIFS) {
  910.             shader = glGenFragmentShadersATI(1);
  911.             glBindFragmentShaderATI(shader);
  912.             CreateATIFragmentShader(*this, *(const VDOpenGLATIFragmentShaderConfig *)tech.mpFragmentShader);
  913.             glBindFragmentShaderATI(0);
  914.         }
  915.  
  916.         glNewList(listBase + i, GL_COMPILE);
  917.         switch(tech.mFragmentShaderMode) {
  918.         case kVDOpenGLFragmentShaderModeNVRC:
  919.             glEnable(GL_REGISTER_COMBINERS_NV);
  920.             glDisable(GL_PER_STAGE_CONSTANTS_NV);
  921.             if (ATI_fragment_shader)
  922.                 glDisable(GL_FRAGMENT_SHADER_ATI);
  923.             CreateNVRegisterCombinerSetup(*this, *(const VDOpenGLNVRegisterCombinerConfig *)tech.mpFragmentShader, false);
  924.             break;
  925.         case kVDOpenGLFragmentShaderModeNVRC2:
  926.             glEnable(GL_REGISTER_COMBINERS_NV);
  927.             glEnable(GL_PER_STAGE_CONSTANTS_NV);
  928.             if (ATI_fragment_shader)
  929.                 glDisable(GL_FRAGMENT_SHADER_ATI);
  930.             CreateNVRegisterCombinerSetup(*this, *(const VDOpenGLNVRegisterCombinerConfig *)tech.mpFragmentShader, true);
  931.             break;
  932.         case kVDOpenGLFragmentShaderModeATIFS:
  933.             if (NV_register_combiners)
  934.                 glDisable(GL_REGISTER_COMBINERS_NV);
  935.             glEnable(GL_FRAGMENT_SHADER_ATI);
  936.             glBindFragmentShaderATI(shader);
  937.             break;
  938.         }
  939.         glEndList();
  940.     }
  941.  
  942.     return listBase;
  943. }
  944.  
  945. void VDOpenGLBinding::DisableFragmentShaders() {
  946.     if (NV_register_combiners)
  947.         glDisable(GL_REGISTER_COMBINERS_NV);
  948.     if (ATI_fragment_shader)
  949.         glDisable(GL_FRAGMENT_SHADER_ATI);
  950. }
  951.