nux-1.16.0
GpuDeviceVertex.cpp
00001 /*
00002  * Copyright 2010 Inalogic® Inc.
00003  *
00004  * This program is free software: you can redistribute it and/or modify it
00005  * under the terms of the GNU Lesser General Public License, as
00006  * published by the  Free Software Foundation; either version 2.1 or 3.0
00007  * of the License.
00008  *
00009  * This program is distributed in the hope that it will be useful, but
00010  * WITHOUT ANY WARRANTY; without even the implied warranties of
00011  * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR
00012  * PURPOSE.  See the applicable version of the GNU Lesser General Public
00013  * License for more details.
00014  *
00015  * You should have received a copy of both the GNU Lesser General Public
00016  * License along with this program. If not, see <http://www.gnu.org/licenses/>
00017  *
00018  * Authored by: Jay Taoko <jaytaoko@inalogic.com>
00019  *
00020  */
00021 
00022 
00023 #include "GLResource.h"
00024 #include "GpuDevice.h"
00025 #include "GLDeviceObjects.h"
00026 #include "GLResourceManager.h"
00027 
00028 #include "GLTextureResourceManager.h"
00029 #include "GLVertexResourceManager.h"
00030 #include "GLDeviceFrameBufferObject.h"
00031 #include "GLTemplatePrimitiveBuffer.h"
00032 #include "GraphicsEngine.h"
00033 
00034 namespace nux
00035 {
00036 
00037   static STREAMSOURCE _StreamSource[MAX_NUM_STREAM];
00038 
00039   ObjectPtr<IOpenGLVertexBuffer> GpuDevice::CreateVertexBuffer (int Length,
00040       VBO_USAGE Usage)
00041   {
00042     IOpenGLVertexBuffer *ptr;
00043     CreateVertexBuffer (Length, Usage, (IOpenGLVertexBuffer **) &ptr);
00044     ObjectPtr<IOpenGLVertexBuffer> h = ObjectPtr<IOpenGLVertexBuffer> (ptr);
00045     ptr->UnReference ();
00046     return h;
00047   }
00048 
00049   int GpuDevice::CreateVertexBuffer (unsigned int Length,
00050       VBO_USAGE Usage,
00051       IOpenGLVertexBuffer **ppVertexBuffer)
00052   {
00053     *ppVertexBuffer = new IOpenGLVertexBuffer (Length, Usage, NUX_TRACKER_LOCATION);
00054 
00055     return OGL_OK;
00056   }
00057 
00058   ObjectPtr<IOpenGLIndexBuffer> GpuDevice::CreateIndexBuffer (
00059     int Length
00060     , VBO_USAGE Usage    // Dynamic or WriteOnly
00061     , INDEX_FORMAT Format)
00062   {
00063     IOpenGLIndexBuffer *ptr;
00064     CreateIndexBuffer (Length, Usage, Format, (IOpenGLIndexBuffer **) &ptr);
00065     ObjectPtr<IOpenGLIndexBuffer> h = ObjectPtr<IOpenGLIndexBuffer> (ptr);
00066     ptr->UnReference ();
00067     return h;
00068   }
00069 
00070   int GpuDevice::CreateIndexBuffer (unsigned int Length,
00071                                           VBO_USAGE Usage,
00072                                           INDEX_FORMAT Format,
00073                                           IOpenGLIndexBuffer **ppIndexBuffer)
00074   {
00075     *ppIndexBuffer = new IOpenGLIndexBuffer (Length, Usage, Format, NUX_TRACKER_LOCATION);
00076 
00077     return OGL_OK;
00078   }
00079 
00080   ObjectPtr<IOpenGLPixelBufferObject> GpuDevice::CreatePixelBufferObject (int Size, VBO_USAGE Usage)
00081   {
00082     IOpenGLPixelBufferObject *ptr;
00083     CreatePixelBufferObject (Size, Usage, (IOpenGLPixelBufferObject **) &ptr);
00084     ObjectPtr<IOpenGLPixelBufferObject> h = ObjectPtr<IOpenGLPixelBufferObject> (ptr);
00085     ptr->UnReference ();
00086     return h;
00087   }
00088 
00089   int GpuDevice::CreatePixelBufferObject (int Size, VBO_USAGE Usage,
00090       IOpenGLPixelBufferObject **ppPixelBufferObject)
00091   {
00092     *ppPixelBufferObject = new IOpenGLPixelBufferObject (Size, Usage, NUX_TRACKER_LOCATION);
00093 
00094     return OGL_OK;
00095   }
00096 
00097   ObjectPtr<IOpenGLVertexDeclaration> GpuDevice::CreateVertexDeclaration (
00098     const VERTEXELEMENT *pVertexElements)
00099   {
00100     IOpenGLVertexDeclaration *ptr;
00101     CreateVertexDeclaration (pVertexElements, (IOpenGLVertexDeclaration **) &ptr);
00102     ObjectPtr<IOpenGLVertexDeclaration> h = ObjectPtr<IOpenGLVertexDeclaration> (ptr);
00103     ptr->UnReference ();
00104     return h;
00105   }
00106 
00107   int GpuDevice::CreateVertexDeclaration (const VERTEXELEMENT *pVertexElements,
00108       IOpenGLVertexDeclaration **ppDecl)
00109   {
00110     *ppDecl = new IOpenGLVertexDeclaration (pVertexElements);
00111 
00112     return OGL_OK;
00113   }
00114 
00115   void GpuDevice::InvalidateVertexBuffer()
00116   {
00117     CHECKGL (glBindBufferARB (GL_ARRAY_BUFFER_ARB, 0) );
00118   }
00119 
00120   void GpuDevice::InvalidateIndexBuffer()
00121   {
00122     CHECKGL (glBindBufferARB (GL_ELEMENT_ARRAY_BUFFER_ARB, 0) );
00123   }
00124 
00125   int GpuDevice::DrawIndexedPrimitive(ObjectPtr<IOpenGLIndexBuffer> IndexBuffer,
00126       ObjectPtr<IOpenGLVertexDeclaration> VertexDeclaration,
00127       PRIMITIVE_TYPE PrimitiveType,
00128       int index_count)
00129   {
00130     nuxAssert (VertexDeclaration.IsValid() );
00131 
00132     if (!VertexDeclaration.IsValid() )
00133       return OGL_ERROR;
00134 
00135     int decl = 0;
00136 
00137     for (int i = 0; i < 16; i++)
00138     {
00139       VertexDeclaration->_valid_vertex_input[i] = 0;
00140     }
00141 
00142     while(VertexDeclaration->_declarations_array[decl].Stream != 0xFF)
00143     {
00144       VERTEXELEMENT vtxelement = VertexDeclaration->_declarations_array[decl];
00145 
00146       int shader_attribute_location = VertexDeclaration->GetVertexShaderAttributeLocation(decl);
00147       
00148       if(shader_attribute_location == -1)
00149       {
00150         ++decl;
00151         continue;
00152       }
00153 
00154       VertexDeclaration->GetVertexBuffer(vtxelement.Stream)->BindVertexBuffer();
00155 
00156       glEnableVertexAttribArrayARB(shader_attribute_location);
00157       
00158       CHECKGL(glVertexAttribPointer(shader_attribute_location,
00159         vtxelement.NumComponent,
00160         vtxelement.Type,
00161         GL_FALSE,
00162         vtxelement.stride_,
00163         (void*)vtxelement.Offset));
00164 
00165       VertexDeclaration->_valid_vertex_input[shader_attribute_location] = 1;
00166       ++decl;
00167     }
00168 
00169     {
00170       IndexBuffer->BindIndexBuffer();
00171 
00172       GLenum primitive = PrimitiveType;
00173       GLenum index_format = GL_UNSIGNED_SHORT;
00174 
00175       if (IndexBuffer->GetStride() == 4)
00176         index_format = GL_UNSIGNED_INT;
00177 
00178 //       switch (PrimitiveType)
00179 //       {
00180 //         case PRIMITIVE_TYPE_POINTLIST:
00181 //           ElementCount = PrimitiveCount;
00182 //           break;
00183 // 
00184 //         case PRIMITIVE_TYPE_LINELIST:
00185 //           ElementCount = PrimitiveCount * 2;
00186 //           break;
00187 // 
00188 //         case PRIMITIVE_TYPE_LINESTRIP:
00189 //           ElementCount = PrimitiveCount + 1;
00190 //           break;
00191 // 
00192 //         case PRIMITIVE_TYPE_TRIANGLELIST:
00193 //           ElementCount = PrimitiveCount * 3;
00194 //           break;
00195 // 
00196 //         case PRIMITIVE_TYPE_TRIANGLEFAN:
00197 //         case PRIMITIVE_TYPE_TRIANGLESTRIP:
00198 //           ElementCount = PrimitiveCount + 2;
00199 //           break;
00200 //         default:
00201 //           // Unknown primitive type. This should not happen.
00202 //           nuxAssertMsg (0, TEXT ("[GpuDevice::DrawIndexedPrimitive] Unknown Primitive Type.") );
00203 //       }
00204 
00205       CHECKGL(glDrawElements (primitive,
00206                                 index_count,
00207                                 index_format,
00208                                 0));
00209     }
00210 
00211     {
00212       for(int index = 0; index < 16; index++)
00213       {
00214         if(VertexDeclaration->_valid_vertex_input[index])
00215           glDisableVertexAttribArrayARB(index);
00216       }
00217 
00218       InvalidateVertexBuffer();
00219       InvalidateIndexBuffer();
00220     }
00221 
00222     //    for(int i = 0; i < 8; i++)
00223     //    {
00224     //        CHECKGL(glClientActiveTexture(GL_TEXTURE0 + i));
00225     //        CHECKGL(glDisable(GL_TEXTURE_3D));
00226     //        CHECKGL(glDisable(GL_TEXTURE_2D));
00227     //        CHECKGL(glDisable(GL_TEXTURE_1D));
00228     //        CHECKGL(glDisable(GL_TEXTURE_CUBE_MAP_ARB));
00229     //        CHECKGL(glEnable(GL_TEXTURE_2D));
00230     //        CHECKGL(glBindTexture(GL_TEXTURE_2D, 0));
00231     //    }
00232     return OGL_OK;
00233   }
00234 
00235 
00236 // Draw Primitive without index buffer
00237   int GpuDevice::DrawPrimitive (ObjectPtr<IOpenGLVertexDeclaration> VertexDeclaration,
00238                                       PRIMITIVE_TYPE PrimitiveType,
00239                                       unsigned vtx_start_,
00240                                       unsigned PrimitiveCount)
00241   {
00242 //     return OGL_OK;
00243 //     glDisable (GL_CULL_FACE);
00244 //     glPolygonMode (GL_FRONT_AND_BACK, GL_LINE);
00245 // 
00246 //     // Maps a vertex declaration usage to a vertex shader input index.
00247 //     // I want to make this a static array defined outside of this function but their seems to be a problem
00248 //     // with initialization...
00249 //     /*static*/
00250 //     int sVertexInputMap[] =
00251 //     {
00252 //       0,   // ATTRIB_USAGE_DECL_POSITION
00253 //       14,  // ATTRIB_USAGE_DECL_BLENDWEIGHT
00254 //       15,  // ATTRIB_USAGE_DECL_BLENDINDICES
00255 //       1,   // ATTRIB_USAGE_DECL_NORMAL
00256 //       4,   // ATTRIB_USAGE_DECL_COLOR, ATTRIB_USAGE_DECL_COLOR0
00257 //       5,   // ATTRIB_USAGE_DECL_COLOR1
00258 //       6,   // ATTRIB_USAGE_DECL_FOGCOORD
00259 //       7,   // ATTRIB_USAGE_DECL_PSIZE
00260 //       8,   // ATTRIB_USAGE_DECL_TEXCOORD, ATTRIB_USAGE_DECL_TEXCOORD0
00261 //       9,   // ATTRIB_USAGE_DECL_TEXCOORD1
00262 //       10,  // ATTRIB_USAGE_DECL_TEXCOORD2
00263 //       11,  // ATTRIB_USAGE_DECL_TEXCOORD3
00264 //       12,  // ATTRIB_USAGE_DECL_TEXCOORD4
00265 //       13,  // ATTRIB_USAGE_DECL_TEXCOORD5
00266 //       14,  // ATTRIB_USAGE_DECL_TEXCOORD6
00267 //       15,  // ATTRIB_USAGE_DECL_TEXCOORD7
00268 //       2,   // ATTRIB_USAGE_DECL_TANGENT
00269 //       3,   // ATTRIB_USAGE_DECL_BINORMAL
00270 //     };
00271 // 
00272 //     nuxAssert (VertexDeclaration.IsValid() );
00273 // 
00274 //     if (!VertexDeclaration.IsValid() )
00275 //       return OGL_ERROR;
00276 // 
00277 //     int decl = 0;
00278 // 
00279 //     for (int i = 0; i < 16; i++)
00280 //       VertexDeclaration->_valid_vertex_input[i] = 0;
00281 // 
00282 //     while (VertexDeclaration->_declarations_array[decl].Stream != 0xFF)
00283 //     {
00284 //       VERTEXELEMENT vtxelement = VertexDeclaration->_declarations_array[decl];
00285 //       int vtxInput = sVertexInputMap[vtxelement.Usage + vtxelement.UsageIndex];
00286 // 
00287 //       nuxAssert (vtxInput < GetGpuInfo().GetMaxFboAttachment());
00288 //       // Eneble the vertex attribute (0 to 10)
00289 //       glEnableVertexAttribArrayARB ( vtxInput );
00290 //       // Bind the vertex buffer
00291 //       _StreamSource[vtxelement.Stream].VertexBuffer->BindVertexBuffer();
00292 // 
00293 //       CHECKGL ( glVertexAttribPointer (vtxInput,
00294 //                                        vtxelement.NumComponent,
00295 //                                        vtxelement.Type,
00296 //                                        GL_FALSE,
00297 //                                        _StreamSource[vtxelement.Stream].StreamStride,
00298 //                                        (GLvoid *) (&_StreamSource[vtxelement.Stream].StreamOffset + vtxelement.Offset) ) );
00299 // 
00300 //       VertexDeclaration->_valid_vertex_input[sVertexInputMap[vtxelement.Usage + vtxelement.UsageIndex]] = 1;
00301 //       decl++;
00302 //     }
00303 // 
00304 //     {
00305 //       InvalidateIndexBuffer();
00306 // 
00307 //       GLenum primitive = PrimitiveType;
00308 //       int ElementCount = 0;
00309 // 
00310 //       switch (PrimitiveType)
00311 //       {
00312 //         case PRIMITIVE_TYPE_POINTLIST:
00313 //           ElementCount = PrimitiveCount;
00314 //           break;
00315 // 
00316 //         case PRIMITIVE_TYPE_LINELIST:
00317 //           ElementCount = PrimitiveCount * 2;
00318 //           break;
00319 // 
00320 //         case PRIMITIVE_TYPE_LINESTRIP:
00321 //           ElementCount = PrimitiveCount + 1;
00322 //           break;
00323 // 
00324 //         case PRIMITIVE_TYPE_TRIANGLELIST:
00325 //           ElementCount = PrimitiveCount * 3;
00326 //           break;
00327 // 
00328 //         case PRIMITIVE_TYPE_TRIANGLEFAN:
00329 //         case PRIMITIVE_TYPE_TRIANGLESTRIP:
00330 //           ElementCount = PrimitiveCount + 2;
00331 //           break;
00332 //         default:
00333 //           // Unknown primitive type. This should not happen.
00334 //           nuxAssertMsg (0, TEXT ("[GpuDevice::DrawPrimitive] Unknown Primitive Type.") );
00335 //           return OGL_ERROR;
00336 //       }
00337 // 
00338 //       CHECKGL ( glDrawArrays (primitive,
00339 //                               ElementCount,
00340 //                               vtx_start_) );
00341 //     }
00342 // 
00343 //     {
00344 //       for (int index = 0; index < 16; index++)
00345 //       {
00346 //         if (VertexDeclaration->_valid_vertex_input[index])
00347 //           glDisableVertexAttribArrayARB ( index );
00348 //       }
00349 // 
00350 //       InvalidateVertexBuffer();
00351 //       InvalidateIndexBuffer();
00352 //     }
00353 // 
00354 //     //    for(int i = 0; i < 8; i++)
00355 //     //    {
00356 //     //        CHECKGL(glClientActiveTexture(GL_TEXTURE0 + i));
00357 //     //        CHECKGL(glDisable(GL_TEXTURE_3D));
00358 //     //        CHECKGL(glDisable(GL_TEXTURE_2D));
00359 //     //        CHECKGL(glDisable(GL_TEXTURE_1D));
00360 //     //        CHECKGL(glDisable(GL_TEXTURE_CUBE_MAP_ARB));
00361 //     //        CHECKGL(glEnable(GL_TEXTURE_2D));
00362 //     //        CHECKGL(glBindTexture(GL_TEXTURE_2D, 0));
00363 //     //    }
00364     return OGL_OK;
00365   }
00366 
00367 // Draw Primitive without index buffer, and use a user pointer for the source of the stream.
00368   int GpuDevice::DrawPrimitiveUP (ObjectPtr<IOpenGLVertexDeclaration> VertexDeclaration,
00369                                         PRIMITIVE_TYPE PrimitiveType,
00370                                         unsigned int PrimitiveCount,
00371                                         const void *pVertexStreamZeroData,
00372                                         unsigned int VertexStreamZeroStride)
00373   {
00374 //     nuxAssertMsg (VertexDeclaration->IsUsingMoreThanStreamZero(), TEXT ("[GpuDevice::DrawPrimitiveUP] Declaration is using more than stream 0.") );
00375 //     VERTEXELEMENT vtxelement = VertexDeclaration->GetUsage (ATTRIB_USAGE_DECL_POSITION);
00376 //     int Stream = vtxelement.Stream;
00377 // 
00378 //     if (Stream != 0xFF)
00379 //     {
00380 //       glDisable (GL_CULL_FACE);
00381 //       glPolygonMode (GL_FRONT_AND_BACK, GL_LINE);
00382 // 
00383 //       InvalidateVertexBuffer();
00384 //       InvalidateVertexBuffer();
00385 // 
00386 //       t_size ptr = * (t_size *) pVertexStreamZeroData + _StreamSource[vtxelement.Stream].StreamOffset;
00387 //       CHECKGL ( glEnableClientState (GL_VERTEX_ARRAY) );
00388 //       CHECKGL ( glVertexPointer ( vtxelement.NumComponent,
00389 //                                   vtxelement.Type,
00390 //                                   VertexStreamZeroStride,
00391 //                                   (GLvoid *) &ptr) );
00392 // 
00393 //       InvalidateIndexBuffer();
00394 // 
00395 //       GLenum primitive = PrimitiveType;
00396 //       int ElementCount = 0;
00397 // 
00398 //       switch (PrimitiveType)
00399 //       {
00400 //         case PRIMITIVE_TYPE_POINTLIST:
00401 //           ElementCount = PrimitiveCount;
00402 //           break;
00403 // 
00404 //         case PRIMITIVE_TYPE_LINELIST:
00405 //           ElementCount = PrimitiveCount * 2;
00406 //           break;
00407 // 
00408 //         case PRIMITIVE_TYPE_LINESTRIP:
00409 //           ElementCount = PrimitiveCount + 1;
00410 //           break;
00411 // 
00412 //         case PRIMITIVE_TYPE_TRIANGLELIST:
00413 //           ElementCount = PrimitiveCount * 3;
00414 //           break;
00415 // 
00416 //         case PRIMITIVE_TYPE_TRIANGLEFAN:
00417 //         case PRIMITIVE_TYPE_TRIANGLESTRIP:
00418 //           ElementCount = PrimitiveCount + 2;
00419 //           break;
00420 //         default:
00421 //           // Unknown primitive type. This should not happen.
00422 //           nuxAssertMsg (0, TEXT ("[GpuDevice::DrawPrimitiveUP] Unknown Primitive Type.") );
00423 //           return OGL_ERROR;
00424 //       }
00425 // 
00426 //       CHECKGL ( glDrawArrays (primitive,
00427 //                               ElementCount,
00428 //                               0) );
00429 // 
00430 //       CHECKGL ( glDisableClientState (GL_VERTEX_ARRAY) );
00431 // 
00432 //     }
00433 // 
00434 //     //    for(int i = 0; i < 8; i++)
00435 //     //    {
00436 //     //        CHECKGL(glClientActiveTexture(GL_TEXTURE0 + i));
00437 //     //        CHECKGL(glDisable(GL_TEXTURE_3D));
00438 //     //        CHECKGL(glDisable(GL_TEXTURE_2D));
00439 //     //        CHECKGL(glDisable(GL_TEXTURE_1D));
00440 //     //        CHECKGL(glDisable(GL_TEXTURE_CUBE_MAP_ARB));
00441 //     //        CHECKGL(glEnable(GL_TEXTURE_2D));
00442 //     //        CHECKGL(glBindTexture(GL_TEXTURE_2D, 0));
00443 //     //    }
00444     return OGL_OK;
00445   }
00446 
00447 // //    DirectX Matrix
00448 // //    |   2/W     0       0       -(W+1)/W    |
00449 // //    |   0       -2/H    0       (H+1)/H     |
00450 // //    |   0       0       1       0           |
00451 // //    |   0       0       0       1           |
00452 // //
00453 // //    Screen Quad(0, 0, W, H)
00454 // //                  Normalized Coord       (Xn+1)/2 * W         Screen Coord
00455 // //        X: 0 ---> -(1+1/W)                --->                -0.5
00456 // //        X: W ---> 1-1/W                   --->                W-0.5
00457 // //                                          -(Yn-1)/2 * H
00458 // //        Y: 0 ---> (1+1/H)                 --->                -0.5
00459 // //        Y: W ---> -1-1/H                  --->                H-0.5
00460 // //
00461 // //    The Matrix above is good to do quad on screen in DirectX. DirectX requires that the vertex coordinates be shifted
00462 // //    by (-0.5,-0.5) in order for the center of texel to be located at the center of pixel.
00463 // //    Note: OpenGL maps integral texture coordinates to the texel center
00464 // //          whereas Direct3D maps  integral texture coordinates to the upper, left texel corner.
00465 // 
00466 // //    In OpenGL we will use this matrix instead:
00467 // //    |   2/W     0       0         -1  |
00468 // //    |   0       -2/H    0         1   |
00469 // //    |   0       0       1         0   |
00470 // //    |   0       0       0         1   |
00471 // //
00472 // //    Screen Quad(0, 0, W, H)
00473 // //                  Normalized Coord     (Xn+1)/2 * W         Screen Coord
00474 // //        X: 0 ---> -1                      --->                0.0
00475 // //        X: W ---> 1                       --->                W
00476 // //                                       -(Yn-1)/2 * H
00477 // //        Y: 0 ---> 1                       --->                0.0
00478 // //        Y: W ---> -1
00479 
00480 
00481   int GpuDevice::SetStreamSource (
00482     unsigned int StreamNumber,
00483     ObjectPtr<IOpenGLVertexBuffer> pStreamData,
00484     unsigned int OffsetInBytes,
00485     unsigned int Stride)
00486   {
00487     nuxAssert (StreamNumber < MAX_NUM_STREAM);
00488 
00489     _StreamSource[StreamNumber].Stream = StreamNumber;
00490     _StreamSource[StreamNumber].StreamOffset = OffsetInBytes;
00491     _StreamSource[StreamNumber].VertexBuffer = pStreamData;
00492     _StreamSource[StreamNumber].StreamStride = Stride;
00493 
00494     return OGL_OK;
00495   }
00496 
00497 }
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends