RenderInterfaceDirectx10.cpp 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482
  1. #include "RenderInterfaceDirectX10.h"
  2. #include <Rocket/Core.h>
  3. #include "D3D10Effect.h"
  4. //RocketD3D10 Texture, this contains the actual texture and the resource view
  5. //for sending it to the effect
  6. struct RocketD3D10Texture
  7. {
  8. ID3D10ShaderResourceView * textureView;
  9. ID3D10Texture2D * texture2D;
  10. };
  11. // This structure is created for each set of geometry that Rocket compiles. It stores the vertex and index buffers and
  12. // the texture associated with the geometry, if one was specified.
  13. struct RocketD310DCompiledGeometry
  14. {
  15. //Vertex Buffer
  16. ID3D10Buffer * vertices;
  17. DWORD num_vertices;
  18. //Index buffer
  19. ID3D10Buffer * indices;
  20. DWORD num_primitives;
  21. //Texture
  22. RocketD3D10Texture * texture;
  23. };
  24. // The internal format of the vertex we use for rendering Rocket geometry. We could optimise space by having a second
  25. // untextured vertex for use when rendering coloured borders and backgrounds.
  26. struct RocketD3D10Vertex
  27. {
  28. FLOAT x, y, z;
  29. D3DXCOLOR colour;
  30. FLOAT u, v;
  31. };
  32. //The layout of the vertices
  33. const D3D10_INPUT_ELEMENT_DESC layout[] =
  34. {
  35. { "POSITION",0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D10_INPUT_PER_VERTEX_DATA, 0 },
  36. { "COLOR",0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 12, D3D10_INPUT_PER_VERTEX_DATA, 0},
  37. {"TEXCOORD",0,DXGI_FORMAT_R32G32_FLOAT,0,28,D3D10_INPUT_PER_VERTEX_DATA,0},
  38. };
  39. //The constructor of the render
  40. RenderInterfaceDirectX10::RenderInterfaceDirectX10(void)
  41. {
  42. m_rocket_context = NULL;
  43. m_pD3D10Device = NULL;
  44. m_pEffect = NULL;
  45. m_pTechnique = NULL;
  46. m_pVertexLayout = NULL;
  47. m_pSwapChain = NULL;
  48. m_pRenderTargetView = NULL;
  49. m_pProjectionMatrixVariable = NULL;
  50. m_pWorldMatrixVariable = NULL;
  51. m_pDiffuseTextureVariable = NULL;
  52. m_pScissorTestDisable = NULL;
  53. m_pScissorTestEnable = NULL;
  54. }
  55. //Loads the effect from memory and retrieves initial variables from the effect
  56. void RenderInterfaceDirectX10::setupEffect()
  57. {
  58. //The pass we are going to use
  59. ID3D10EffectPass *pass=NULL;
  60. DWORD dwShaderFlags = 0;
  61. #if defined( DEBUG ) || defined( _DEBUG )
  62. // Set the D3D10_SHADER_DEBUG flag to embed debug information in the shaders.
  63. // Setting this flag improves the shader debugging experience, but still allows
  64. // the shaders to be optimized and to run exactly the way they will run in
  65. // the release configuration of this program. - BMD
  66. dwShaderFlags |= D3D10_SHADER_DEBUG;
  67. #endif
  68. //Create our effect from Memory
  69. if (FAILED(D3DX10CreateEffectFromMemory((void*)pEffectData,strlen(pEffectData),"DefaultEffect",NULL,NULL,"fx_4_0",dwShaderFlags,0,m_pD3D10Device,NULL,NULL,&m_pEffect,NULL,NULL)))
  70. {
  71. //Log error
  72. Rocket::Core::Log::Message(Rocket::Core::Log::LT_ERROR, "Can't create default effect for rendering, graphics card may not support Shader Model 4");
  73. }
  74. //Number of elements in the layout - BMD
  75. UINT numElements = sizeof(layout)/sizeof(D3D10_INPUT_ELEMENT_DESC);
  76. //Get the pass description so we can get some info about the input signature of the vertices
  77. D3D10_PASS_DESC passDesc;
  78. m_pTechnique=m_pEffect->GetTechniqueByName("Render");
  79. pass=m_pTechnique->GetPassByName("P0");
  80. pass->GetDesc(&passDesc);
  81. //create input layout, to allow us to map our vertex structure to the one held in the effect
  82. if (FAILED(m_pD3D10Device->CreateInputLayout(layout, numElements, passDesc.pIAInputSignature, passDesc.IAInputSignatureSize, &m_pVertexLayout)))
  83. {
  84. Rocket::Core::Log::Message(Rocket::Core::Log::LT_ERROR, "Unable to create input layout");
  85. }
  86. //grab effect variables
  87. m_pWorldMatrixVariable=m_pEffect->GetVariableByName("matWorld")->AsMatrix();
  88. m_pProjectionMatrixVariable=m_pEffect->GetVariableByName("matProjection")->AsMatrix();
  89. //grab texture variable
  90. m_pDiffuseTextureVariable=m_pEffect->GetVariableByName("diffuseMap")->AsShaderResource();
  91. }
  92. RenderInterfaceDirectX10::~RenderInterfaceDirectX10()
  93. {
  94. if (m_pVertexLayout)
  95. {
  96. m_pVertexLayout->Release();
  97. m_pVertexLayout = NULL;
  98. }
  99. if (m_pEffect)
  100. {
  101. m_pEffect->Release();
  102. m_pEffect = NULL;
  103. }
  104. if (m_pScissorTestDisable){
  105. m_pScissorTestDisable->Release();
  106. m_pScissorTestDisable = NULL;
  107. }
  108. if (m_pScissorTestEnable){
  109. m_pScissorTestEnable->Release();
  110. m_pScissorTestEnable = NULL;
  111. }
  112. }
  113. // Called by Rocket when it wants to render geometry that it does not wish to optimise.
  114. void RenderInterfaceDirectX10::RenderGeometry(Rocket::Core::Vertex* vertices, int num_vertices, int* indices, int num_indices, const Rocket::Core::TextureHandle texture, const Rocket::Core::Vector2f& translation)
  115. {
  116. // @TODO We've chosen to not support non-compiled geometry in the DirectX renderer. If you wanted to render non-compiled
  117. // geometry, for example for very small sections of geometry, you could use DrawIndexedPrimitiveUP or write to a
  118. // dynamic vertex buffer which is flushed when either the texture changes or compiled geometry is drawn.
  119. /// @TODO, HACK, just use the compiled geometry framework for now, this is inefficient but better than absolutely nothing
  120. /// for the time being
  121. Rocket::Core::CompiledGeometryHandle geom = this->CompileGeometry(vertices, num_vertices, indices, num_indices, texture);
  122. this->RenderCompiledGeometry(geom, translation);
  123. this->ReleaseCompiledGeometry(geom);
  124. }
  125. // Called by Rocket when it wants to compile geometry it believes will be static for the forseeable future.
  126. Rocket::Core::CompiledGeometryHandle RenderInterfaceDirectX10::CompileGeometry(Rocket::Core::Vertex* vertices, int num_vertices, int* indices, int num_indices, Rocket::Core::TextureHandle texture)
  127. {
  128. //Create instance of geometry
  129. RocketD310DCompiledGeometry * geometry =new RocketD310DCompiledGeometry();
  130. //Vertex Buffer description
  131. D3D10_BUFFER_DESC bd;
  132. bd.Usage = D3D10_USAGE_DEFAULT;
  133. //Set the size of the buffer
  134. bd.ByteWidth = sizeof(RocketD3D10Vertex) * num_vertices;
  135. //This is a vertex buffer
  136. bd.BindFlags = D3D10_BIND_VERTEX_BUFFER;
  137. bd.CPUAccessFlags = 0;
  138. bd.MiscFlags = 0;
  139. //copy vertices into buffer
  140. RocketD3D10Vertex * pD3D10Vertices=new RocketD3D10Vertex[num_vertices];
  141. for (int i=0;i<num_vertices;++i)
  142. {
  143. pD3D10Vertices[i].x = vertices[i].position.x;
  144. pD3D10Vertices[i].y = vertices[i].position.y;
  145. pD3D10Vertices[i].z = 0;
  146. pD3D10Vertices[i].colour=D3DXCOLOR((float)(vertices[i].colour.red/255), (float)(vertices[i].colour.green/255), (float)(vertices[i].colour.blue/255),
  147. (float)(vertices[i].colour.alpha/255));
  148. pD3D10Vertices[i].u = vertices[i].tex_coord[0];
  149. pD3D10Vertices[i].v = vertices[i].tex_coord[1];
  150. }
  151. D3D10_SUBRESOURCE_DATA InitData;
  152. InitData.pSysMem = pD3D10Vertices;
  153. //Create VB
  154. if (FAILED(m_pD3D10Device->CreateBuffer(
  155. &bd,
  156. &InitData,
  157. &geometry->vertices))){
  158. Rocket::Core::Log::Message(Rocket::Core::Log::LT_ERROR, "Undable to create vertex buffer for geometry");
  159. return false;
  160. }
  161. delete pD3D10Vertices;
  162. //Index buffer desc
  163. bd.Usage = D3D10_USAGE_DEFAULT;
  164. bd.ByteWidth = sizeof( UINT ) * num_indices;
  165. bd.BindFlags = D3D10_BIND_INDEX_BUFFER;
  166. bd.CPUAccessFlags = 0;
  167. bd.MiscFlags = 0;
  168. //Index values
  169. InitData.pSysMem = indices;
  170. //Fill and create buffer
  171. if (FAILED(m_pD3D10Device->CreateBuffer(
  172. &bd,
  173. &InitData,
  174. &geometry->indices))){
  175. Rocket::Core::Log::Message(Rocket::Core::Log::LT_ERROR, "Undable to create index buffer for geometry");
  176. return false;
  177. }
  178. //save some info in the instance of the structure
  179. geometry->num_vertices = (DWORD) num_vertices;
  180. geometry->num_primitives = (DWORD) num_indices / 3;
  181. geometry->texture = texture == NULL ? NULL : (RocketD3D10Texture *) texture;
  182. return (Rocket::Core::CompiledGeometryHandle)geometry;
  183. }
  184. // Called by Rocket when it wants to render application-compiled geometry.
  185. void RenderInterfaceDirectX10::RenderCompiledGeometry(Rocket::Core::CompiledGeometryHandle geometry, const Rocket::Core::Vector2f& translation)
  186. {
  187. //Cast to D3D10 geometry
  188. RocketD310DCompiledGeometry* d3d10_geometry = (RocketD310DCompiledGeometry*) geometry;
  189. //if we have a texture then send it, notice we are sending the view(Shader resource) to the
  190. //effect
  191. if (d3d10_geometry->texture)
  192. m_pDiffuseTextureVariable->SetResource(d3d10_geometry->texture->textureView);
  193. else
  194. m_pDiffuseTextureVariable->SetResource(NULL);
  195. //build and send the world matrix
  196. D3DXMatrixTranslation(&m_matWorld, translation.x, translation.y, 0);
  197. m_pWorldMatrixVariable->SetMatrix((float*)m_matWorld);
  198. //Set the layout of the vertices that are held in the VB
  199. m_pD3D10Device->IASetInputLayout(m_pVertexLayout);
  200. //Get the stride(size) of the a vertex, we need this to tell the pipeline the size of one vertex
  201. UINT stride = sizeof(RocketD3D10Vertex);
  202. //The offset from start of the buffer to where our vertices are located
  203. UINT offset = 0;
  204. //Set the VB we are using
  205. m_pD3D10Device->IASetVertexBuffers(
  206. 0,
  207. 1,
  208. &d3d10_geometry->vertices,
  209. &stride,
  210. &offset );
  211. //Set the IB we are using
  212. m_pD3D10Device->IASetIndexBuffer(d3d10_geometry->indices,DXGI_FORMAT_R32_UINT,0);
  213. D3D10_TECHNIQUE_DESC techDesc;
  214. m_pTechnique->GetDesc( &techDesc );
  215. //Loop through the passes in the technique
  216. for( UINT p = 0; p < techDesc.Passes; ++p )
  217. {
  218. //Get a pass at current index and apply it
  219. m_pTechnique->GetPassByIndex( p )->Apply( 0 );
  220. //We are drawing trangle lists
  221. m_pD3D10Device->IASetPrimitiveTopology( D3D10_PRIMITIVE_TOPOLOGY_TRIANGLELIST );
  222. //Draw call
  223. m_pD3D10Device->DrawIndexed(d3d10_geometry->num_primitives*3,0,0);
  224. }
  225. }
  226. // Called by Rocket when it wants to release application-compiled geometry.
  227. void RenderInterfaceDirectX10::ReleaseCompiledGeometry(Rocket::Core::CompiledGeometryHandle geometry)
  228. {
  229. //Clean up after ourselves
  230. RocketD310DCompiledGeometry* d3d10_geometry=(RocketD310DCompiledGeometry*)geometry;
  231. if (d3d10_geometry->vertices){
  232. d3d10_geometry->vertices->Release();
  233. d3d10_geometry->vertices = NULL;
  234. }
  235. if (d3d10_geometry->indices){
  236. d3d10_geometry->indices->Release();
  237. d3d10_geometry->indices = NULL;
  238. }
  239. delete d3d10_geometry;
  240. }
  241. // Called by Rocket when it wants to enable or disable scissoring to clip content.
  242. void RenderInterfaceDirectX10::EnableScissorRegion(bool enable)
  243. {
  244. //Is the scissor test enabled?
  245. enable ? m_pD3D10Device->RSSetState(m_pScissorTestEnable) : m_pD3D10Device->RSSetState(m_pScissorTestDisable);
  246. }
  247. // Called by Rocket when it wants to change the scissor region.
  248. void RenderInterfaceDirectX10::SetScissorRegion(int x, int y, int width, int height)
  249. {
  250. //The scissor rect
  251. D3D10_RECT rect;
  252. rect.left=x;
  253. rect.right=x+width;
  254. rect.top=y;
  255. rect.bottom=y+height;
  256. m_pD3D10Device->RSSetScissorRects(1,&rect);
  257. }
  258. // Set to byte packing, or the compiler will expand our struct, which means it won't read correctly from file
  259. #pragma pack(1)
  260. struct TGAHeader
  261. {
  262. char idLength;
  263. char colourMapType;
  264. char dataType;
  265. short int colourMapOrigin;
  266. short int colourMapLength;
  267. char colourMapDepth;
  268. short int xOrigin;
  269. short int yOrigin;
  270. short int width;
  271. short int height;
  272. char bitsPerPixel;
  273. char imageDescriptor;
  274. };
  275. // Restore packing
  276. #pragma pack()
  277. // Called by Rocket when a texture is required by the library.
  278. bool RenderInterfaceDirectX10::LoadTexture(Rocket::Core::TextureHandle& texture_handle, Rocket::Core::Vector2i& texture_dimensions, const Rocket::Core::String& source)
  279. {
  280. Rocket::Core::FileInterface* file_interface = Rocket::Core::GetFileInterface();
  281. Rocket::Core::FileHandle file_handle = file_interface->Open(source);
  282. if (file_handle == NULL)
  283. return false;
  284. file_interface->Seek(file_handle, 0, SEEK_END);
  285. size_t buffer_size = file_interface->Tell(file_handle);
  286. file_interface->Seek(file_handle, 0, SEEK_SET);
  287. char* buffer = new char[buffer_size];
  288. file_interface->Read(buffer, buffer_size, file_handle);
  289. file_interface->Close(file_handle);
  290. TGAHeader header;
  291. memcpy(&header, buffer, sizeof(TGAHeader));
  292. int color_mode = header.bitsPerPixel / 8;
  293. int image_size = header.width * header.height * 4; // We always make 32bit textures
  294. if (header.dataType != 2)
  295. {
  296. Rocket::Core::Log::Message(Rocket::Core::Log::LT_ERROR, "Only 24/32bit uncompressed TGAs are supported.");
  297. return false;
  298. }
  299. // Ensure we have at least 3 colors
  300. if (color_mode < 3)
  301. {
  302. Rocket::Core::Log::Message(Rocket::Core::Log::LT_ERROR, "Only 24 and 32bit textures are supported");
  303. return false;
  304. }
  305. const char* image_src = buffer + sizeof(TGAHeader);
  306. unsigned char* image_dest = new unsigned char[image_size];
  307. // Targa is BGR, swap to RGB and flip Y axis
  308. for (long y = 0; y < header.height; y++)
  309. {
  310. long read_index = y * header.width * color_mode;
  311. long write_index = ((header.imageDescriptor & 32) != 0) ? read_index : (header.height - y - 1) * header.width * color_mode;
  312. for (long x = 0; x < header.width; x++)
  313. {
  314. image_dest[write_index] = image_src[read_index+2];
  315. image_dest[write_index+1] = image_src[read_index+1];
  316. image_dest[write_index+2] = image_src[read_index];
  317. if (color_mode == 4)
  318. image_dest[write_index+3] = image_src[read_index+3];
  319. else
  320. image_dest[write_index+3] = 255;
  321. write_index += 4;
  322. read_index += color_mode;
  323. }
  324. }
  325. texture_dimensions.x = header.width;
  326. texture_dimensions.y = header.height;
  327. bool success = GenerateTexture(texture_handle, image_dest, texture_dimensions);
  328. delete [] image_dest;
  329. delete [] buffer;
  330. return success;
  331. }
  332. // Called by Rocket when a texture is required to be built from an internally-generated sequence of pixels.
  333. bool RenderInterfaceDirectX10::GenerateTexture(Rocket::Core::TextureHandle& texture_handle, const byte* source, const Rocket::Core::Vector2i& source_dimensions)
  334. {
  335. //Create the instance of our texture
  336. RocketD3D10Texture * pTexture=new RocketD3D10Texture();
  337. //Texture description
  338. D3D10_TEXTURE2D_DESC textureDesc;
  339. //Width and height of the texture
  340. textureDesc.Width=source_dimensions.x;
  341. textureDesc.Height=source_dimensions.y;
  342. //Mip levels
  343. textureDesc.MipLevels=1;
  344. textureDesc.ArraySize = 1;
  345. //the format of the texture
  346. textureDesc.Format=DXGI_FORMAT_R8G8B8A8_UNORM;
  347. //The access and usage of the texture
  348. textureDesc.CPUAccessFlags=D3D10_CPU_ACCESS_WRITE;
  349. textureDesc.Usage=D3D10_USAGE_DYNAMIC;
  350. //Our are we going to bind this texture to the pipeline
  351. textureDesc.BindFlags= D3D10_BIND_SHADER_RESOURCE;
  352. textureDesc.MiscFlags=0;
  353. textureDesc.SampleDesc.Count=1;
  354. textureDesc.SampleDesc.Quality=0;
  355. //create our texture
  356. if (FAILED(m_pD3D10Device->CreateTexture2D(&textureDesc,NULL,&pTexture->texture2D))){
  357. Rocket::Core::Log::Message(Rocket::Core::Log::LT_ERROR, "Unable to create texture");
  358. return false;
  359. }
  360. //now lets fill it
  361. D3D10_MAPPED_TEXTURE2D mappedTex;
  362. pTexture->texture2D->Map(D3D10CalcSubresource(0,0,1),D3D10_MAP_WRITE_DISCARD,0,&mappedTex);
  363. for (int y = 0; y < source_dimensions.y; ++y)
  364. {
  365. for (int x = 0; x < source_dimensions.x; ++x)
  366. {
  367. const byte* source_pixel = source + (source_dimensions.x * 4 * y) + (x * 4);
  368. byte* destination_pixel = ((byte*) mappedTex.pData) + mappedTex.RowPitch * y + x * 4;
  369. destination_pixel[0] = source_pixel[0];
  370. destination_pixel[1] = source_pixel[1];
  371. destination_pixel[2] = source_pixel[2];
  372. destination_pixel[3] = source_pixel[3];
  373. }
  374. }
  375. pTexture->texture2D->Unmap(D3D10CalcSubresource(0,0,1));
  376. //Create the shader resoure view for our texture, we need this
  377. //to send the texture to the effect
  378. D3D10_SHADER_RESOURCE_VIEW_DESC srvDesc;
  379. srvDesc.Format=textureDesc.Format;
  380. srvDesc.ViewDimension=D3D10_SRV_DIMENSION_TEXTURE2D;
  381. srvDesc.Texture2D.MipLevels=textureDesc.MipLevels;
  382. srvDesc.Texture2D.MostDetailedMip=0;
  383. if (FAILED(m_pD3D10Device->CreateShaderResourceView(pTexture->texture2D, &srvDesc, &pTexture->textureView))){
  384. Rocket::Core::Log::Message(Rocket::Core::Log::LT_ERROR, "Unable to create texture view");
  385. return false;
  386. }
  387. texture_handle = (Rocket::Core::TextureHandle)pTexture;
  388. return true;
  389. }
  390. // Called by Rocket when a loaded texture is no longer required.
  391. void RenderInterfaceDirectX10::ReleaseTexture(Rocket::Core::TextureHandle texture_handle)
  392. {
  393. //clean up after ourselves
  394. RocketD3D10Texture * pTexture = (RocketD3D10Texture*)texture_handle;
  395. if (pTexture->texture2D){
  396. pTexture->texture2D->Release();
  397. pTexture->texture2D = NULL;
  398. }
  399. if (pTexture->textureView){
  400. pTexture->textureView->Release();
  401. pTexture->textureView = NULL;
  402. }
  403. delete pTexture;
  404. }
  405. // Returns the native horizontal texel offset for the renderer.
  406. float RenderInterfaceDirectX10::GetHorizontalTexelOffset()
  407. {
  408. return 0.0f;
  409. }
  410. // Returns the native vertical texel offset for the renderer.
  411. float RenderInterfaceDirectX10::GetVerticalTexelOffset()
  412. {
  413. return 0.0f;
  414. }