Back to index

nux  3.0.0
GpuDeviceVertex.cpp
Go to the documentation of this file.
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, "[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 #ifndef NUX_OPENGLES_20
00237 // Draw Primitive without index buffer
00238   int GpuDevice::DrawPrimitive(ObjectPtr<IOpenGLVertexDeclaration> VertexDeclaration,
00239                                       PRIMITIVE_TYPE PrimitiveType,
00240                                       unsigned vtx_start_,
00241                                       unsigned PrimitiveCount)
00242   {
00243 //     return OGL_OK;
00244 //     glDisable(GL_CULL_FACE);
00245 //     glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
00246 // 
00247 //     // Maps a vertex declaration usage to a vertex shader input index.
00248 //     // I want to make this a static array defined outside of this function but their seems to be a problem
00249 //     // with initialization...
00250 //     /*static*/
00251 //     int sVertexInputMap[] =
00252 //     {
00253 //       0,   // ATTRIB_USAGE_DECL_POSITION
00254 //       14,  // ATTRIB_USAGE_DECL_BLENDWEIGHT
00255 //       15,  // ATTRIB_USAGE_DECL_BLENDINDICES
00256 //       1,   // ATTRIB_USAGE_DECL_NORMAL
00257 //       4,   // ATTRIB_USAGE_DECL_COLOR, ATTRIB_USAGE_DECL_COLOR0
00258 //       5,   // ATTRIB_USAGE_DECL_COLOR1
00259 //       6,   // ATTRIB_USAGE_DECL_FOGCOORD
00260 //       7,   // ATTRIB_USAGE_DECL_PSIZE
00261 //       8,   // ATTRIB_USAGE_DECL_TEXCOORD, ATTRIB_USAGE_DECL_TEXCOORD0
00262 //       9,   // ATTRIB_USAGE_DECL_TEXCOORD1
00263 //       10,  // ATTRIB_USAGE_DECL_TEXCOORD2
00264 //       11,  // ATTRIB_USAGE_DECL_TEXCOORD3
00265 //       12,  // ATTRIB_USAGE_DECL_TEXCOORD4
00266 //       13,  // ATTRIB_USAGE_DECL_TEXCOORD5
00267 //       14,  // ATTRIB_USAGE_DECL_TEXCOORD6
00268 //       15,  // ATTRIB_USAGE_DECL_TEXCOORD7
00269 //       2,   // ATTRIB_USAGE_DECL_TANGENT
00270 //       3,   // ATTRIB_USAGE_DECL_BINORMAL
00271 //     };
00272 // 
00273 //     nuxAssert(VertexDeclaration.IsValid());
00274 // 
00275 //     if (!VertexDeclaration.IsValid())
00276 //       return OGL_ERROR;
00277 // 
00278 //     int decl = 0;
00279 // 
00280 //     for (int i = 0; i < 16; i++)
00281 //       VertexDeclaration->_valid_vertex_input[i] = 0;
00282 // 
00283 //     while (VertexDeclaration->_declarations_array[decl].Stream != 0xFF)
00284 //     {
00285 //       VERTEXELEMENT vtxelement = VertexDeclaration->_declarations_array[decl];
00286 //       int vtxInput = sVertexInputMap[vtxelement.Usage + vtxelement.UsageIndex];
00287 // 
00288 //       nuxAssert(vtxInput < GetGpuInfo().GetMaxFboAttachment());
00289 //       // Eneble the vertex attribute(0 to 10)
00290 //       glEnableVertexAttribArrayARB( vtxInput );
00291 //       // Bind the vertex buffer
00292 //       _StreamSource[vtxelement.Stream].VertexBuffer->BindVertexBuffer();
00293 // 
00294 //       CHECKGL(glVertexAttribPointer(vtxInput,
00295 //                                        vtxelement.NumComponent,
00296 //                                        vtxelement.Type,
00297 //                                        GL_FALSE,
00298 //                                        _StreamSource[vtxelement.Stream].StreamStride,
00299 //                                        (GLvoid *) (&_StreamSource[vtxelement.Stream].StreamOffset + vtxelement.Offset)));
00300 // 
00301 //       VertexDeclaration->_valid_vertex_input[sVertexInputMap[vtxelement.Usage + vtxelement.UsageIndex]] = 1;
00302 //       decl++;
00303 //     }
00304 // 
00305 //     {
00306 //       InvalidateIndexBuffer();
00307 // 
00308 //       GLenum primitive = PrimitiveType;
00309 //       int ElementCount = 0;
00310 // 
00311 //       switch(PrimitiveType)
00312 //       {
00313 //         case PRIMITIVE_TYPE_POINTLIST:
00314 //           ElementCount = PrimitiveCount;
00315 //           break;
00316 // 
00317 //         case PRIMITIVE_TYPE_LINELIST:
00318 //           ElementCount = PrimitiveCount * 2;
00319 //           break;
00320 // 
00321 //         case PRIMITIVE_TYPE_LINESTRIP:
00322 //           ElementCount = PrimitiveCount + 1;
00323 //           break;
00324 // 
00325 //         case PRIMITIVE_TYPE_TRIANGLELIST:
00326 //           ElementCount = PrimitiveCount * 3;
00327 //           break;
00328 // 
00329 //         case PRIMITIVE_TYPE_TRIANGLEFAN:
00330 //         case PRIMITIVE_TYPE_TRIANGLESTRIP:
00331 //           ElementCount = PrimitiveCount + 2;
00332 //           break;
00333 //         default:
00334 //           // Unknown primitive type. This should not happen.
00335 //           nuxAssertMsg(0, "[GpuDevice::DrawPrimitive] Unknown Primitive Type.");
00336 //           return OGL_ERROR;
00337 //       }
00338 // 
00339 //       CHECKGL(glDrawArrays(primitive,
00340 //                               ElementCount,
00341 //                               vtx_start_));
00342 //     }
00343 // 
00344 //     {
00345 //       for (int index = 0; index < 16; index++)
00346 //       {
00347 //         if (VertexDeclaration->_valid_vertex_input[index])
00348 //           glDisableVertexAttribArrayARB( index );
00349 //       }
00350 // 
00351 //       InvalidateVertexBuffer();
00352 //       InvalidateIndexBuffer();
00353 //     }
00354 // 
00355 //     //    for (int i = 0; i < 8; i++)
00356 //     //    {
00357 //     //        CHECKGL(glClientActiveTexture(GL_TEXTURE0 + i));
00358 //     //        CHECKGL(glDisable(GL_TEXTURE_3D));
00359 //     //        CHECKGL(glDisable(GL_TEXTURE_2D));
00360 //     //        CHECKGL(glDisable(GL_TEXTURE_1D));
00361 //     //        CHECKGL(glDisable(GL_TEXTURE_CUBE_MAP_ARB));
00362 //     //        CHECKGL(glEnable(GL_TEXTURE_2D));
00363 //     //        CHECKGL(glBindTexture(GL_TEXTURE_2D, 0));
00364 //     //    }
00365     return OGL_OK;
00366   }
00367 
00368 // Draw Primitive without index buffer, and use a user pointer for the source of the stream.
00369   int GpuDevice::DrawPrimitiveUP(ObjectPtr<IOpenGLVertexDeclaration> VertexDeclaration,
00370                                         PRIMITIVE_TYPE PrimitiveType,
00371                                         unsigned int PrimitiveCount,
00372                                         const void *pVertexStreamZeroData,
00373                                         unsigned int VertexStreamZeroStride)
00374   {
00375 //     nuxAssertMsg(VertexDeclaration->IsUsingMoreThanStreamZero(), "[GpuDevice::DrawPrimitiveUP] Declaration is using more than stream 0.");
00376 //     VERTEXELEMENT vtxelement = VertexDeclaration->GetUsage(ATTRIB_USAGE_DECL_POSITION);
00377 //     int Stream = vtxelement.Stream;
00378 // 
00379 //     if (Stream != 0xFF)
00380 //     {
00381 //       glDisable(GL_CULL_FACE);
00382 //       glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
00383 // 
00384 //       InvalidateVertexBuffer();
00385 //       InvalidateVertexBuffer();
00386 // 
00387 //       size_t ptr = * (size_t *) pVertexStreamZeroData + _StreamSource[vtxelement.Stream].StreamOffset;
00388 //       CHECKGL(glEnableClientState(GL_VERTEX_ARRAY));
00389 //       CHECKGL(glVertexPointer( vtxelement.NumComponent,
00390 //                                   vtxelement.Type,
00391 //                                   VertexStreamZeroStride,
00392 //                                   (GLvoid *) &ptr));
00393 // 
00394 //       InvalidateIndexBuffer();
00395 // 
00396 //       GLenum primitive = PrimitiveType;
00397 //       int ElementCount = 0;
00398 // 
00399 //       switch(PrimitiveType)
00400 //       {
00401 //         case PRIMITIVE_TYPE_POINTLIST:
00402 //           ElementCount = PrimitiveCount;
00403 //           break;
00404 // 
00405 //         case PRIMITIVE_TYPE_LINELIST:
00406 //           ElementCount = PrimitiveCount * 2;
00407 //           break;
00408 // 
00409 //         case PRIMITIVE_TYPE_LINESTRIP:
00410 //           ElementCount = PrimitiveCount + 1;
00411 //           break;
00412 // 
00413 //         case PRIMITIVE_TYPE_TRIANGLELIST:
00414 //           ElementCount = PrimitiveCount * 3;
00415 //           break;
00416 // 
00417 //         case PRIMITIVE_TYPE_TRIANGLEFAN:
00418 //         case PRIMITIVE_TYPE_TRIANGLESTRIP:
00419 //           ElementCount = PrimitiveCount + 2;
00420 //           break;
00421 //         default:
00422 //           // Unknown primitive type. This should not happen.
00423 //           nuxAssertMsg(0, "[GpuDevice::DrawPrimitiveUP] Unknown Primitive Type.");
00424 //           return OGL_ERROR;
00425 //       }
00426 // 
00427 //       CHECKGL(glDrawArrays(primitive,
00428 //                               ElementCount,
00429 //                               0));
00430 // 
00431 //       CHECKGL(glDisableClientState(GL_VERTEX_ARRAY));
00432 // 
00433 //     }
00434 // 
00435 //     //    for (int i = 0; i < 8; i++)
00436 //     //    {
00437 //     //        CHECKGL(glClientActiveTexture(GL_TEXTURE0 + i));
00438 //     //        CHECKGL(glDisable(GL_TEXTURE_3D));
00439 //     //        CHECKGL(glDisable(GL_TEXTURE_2D));
00440 //     //        CHECKGL(glDisable(GL_TEXTURE_1D));
00441 //     //        CHECKGL(glDisable(GL_TEXTURE_CUBE_MAP_ARB));
00442 //     //        CHECKGL(glEnable(GL_TEXTURE_2D));
00443 //     //        CHECKGL(glBindTexture(GL_TEXTURE_2D, 0));
00444 //     //    }
00445     return OGL_OK;
00446   }
00447 #endif
00448 
00449 // //    DirectX Matrix
00450 // //    |   2/W     0       0       -(W+1)/W    |
00451 // //    |   0       -2/H    0       (H+1)/H     |
00452 // //    |   0       0       1       0           |
00453 // //    |   0       0       0       1           |
00454 // //
00455 // //    Screen Quad(0, 0, W, H)
00456 // //                  Normalized Coord       (Xn+1)/2 * W         Screen Coord
00457 // //        X: 0 ---> -(1+1/W)                --->                -0.5
00458 // //        X: W ---> 1-1/W                   --->                W-0.5
00459 // //                                          -(Yn-1)/2 * H
00460 // //        Y: 0 ---> (1+1/H)                 --->                -0.5
00461 // //        Y: W ---> -1-1/H                  --->                H-0.5
00462 // //
00463 // //    The Matrix above is good to do quad on screen in DirectX. DirectX requires that the vertex coordinates be shifted
00464 // //    by(-0.5,-0.5) in order for the center of texel to be located at the center of pixel.
00465 // //    Note: OpenGL maps integral texture coordinates to the texel center
00466 // //          whereas Direct3D maps  integral texture coordinates to the upper, left texel corner.
00467 // 
00468 // //    In OpenGL we will use this matrix instead:
00469 // //    |   2/W     0       0         -1  |
00470 // //    |   0       -2/H    0         1   |
00471 // //    |   0       0       1         0   |
00472 // //    |   0       0       0         1   |
00473 // //
00474 // //    Screen Quad(0, 0, W, H)
00475 // //                  Normalized Coord     (Xn+1)/2 * W         Screen Coord
00476 // //        X: 0 ---> -1                      --->                0.0
00477 // //        X: W ---> 1                       --->                W
00478 // //                                       -(Yn-1)/2 * H
00479 // //        Y: 0 ---> 1                       --->                0.0
00480 // //        Y: W ---> -1
00481 
00482 
00483   int GpuDevice::SetStreamSource(
00484     unsigned int StreamNumber,
00485     ObjectPtr<IOpenGLVertexBuffer> pStreamData,
00486     unsigned int OffsetInBytes,
00487     unsigned int Stride)
00488   {
00489     nuxAssert(StreamNumber < MAX_NUM_STREAM);
00490 
00491     _StreamSource[StreamNumber].Stream = StreamNumber;
00492     _StreamSource[StreamNumber].StreamOffset = OffsetInBytes;
00493     _StreamSource[StreamNumber].VertexBuffer = pStreamData;
00494     _StreamSource[StreamNumber].StreamStride = Stride;
00495 
00496     return OGL_OK;
00497   }
00498 
00499 }