nux-1.16.0
|
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 }