00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #include "renderers/directx9GUIRenderer/d3d9renderer.h"
00027 #include "renderers/directx9GUIRenderer/d3d9texture.h"
00028 #include "CEGUIExceptions.h"
00029 #include "CEGUISystem.h"
00030
00031 #include <d3dx9.h>
00032 #include <dxerr9.h>
00033 #include <algorithm>
00034 #undef min
00035
00036
00037 namespace CEGUI
00038 {
00039
00040
00041
00042 const int DirectX9Renderer::VERTEX_PER_QUAD = 6;
00043 const int DirectX9Renderer::VERTEX_PER_TRIANGLE = 3;
00044 const int DirectX9Renderer::VERTEXBUFFER_CAPACITY = 4096;
00045 const ulong DirectX9Renderer::VERTEX_FVF = (D3DFVF_XYZRHW|D3DFVF_DIFFUSE|D3DFVF_TEX1);
00046
00047
00048
00049
00050
00051 DirectX9Renderer::DirectX9Renderer(LPDIRECT3DDEVICE9 device, uint max_quads)
00052 {
00053 d_device = device;
00054 Size size(getViewportSize());
00055
00056 constructor_impl(device, size);
00057 }
00058
00059
00060
00061
00062
00063 void DirectX9Renderer::constructor_impl(LPDIRECT3DDEVICE9 device, const Size& display_size)
00064 {
00065 d_device = device;
00066 d_queueing = true;
00067 d_currTexture = NULL;
00068 d_buffer = NULL;
00069 d_bufferPos = 0;
00070
00071
00072 d_display_area.d_left = 0;
00073 d_display_area.d_top = 0;
00074 d_display_area.setSize(display_size);
00075
00076
00077 if (FAILED(d_device->CreateVertexBuffer(
00078 (VERTEXBUFFER_CAPACITY * sizeof(QuadVertex)),
00079 D3DUSAGE_DYNAMIC|D3DUSAGE_WRITEONLY,
00080 VERTEX_FVF,
00081 D3DPOOL_DEFAULT,
00082 &d_buffer,
00083 NULL)))
00084 {
00085
00086
00087 throw std::exception("Creation of VertexBuffer for Renderer object failed");
00088 }
00089
00090
00091 D3DCAPS9 devCaps;
00092 if (FAILED(device->GetDeviceCaps(&devCaps)))
00093 {
00094
00095 d_buffer->Release();
00096 throw std::exception("Unable to retrieve device capabilities from Direct3DDevice9.");
00097 }
00098
00099
00100 d_maxTextureSize = ceguimin(devCaps.MaxTextureWidth, devCaps.MaxTextureHeight);
00101
00102 d_device->AddRef();
00103
00104
00105 d_identifierString = "CEGUI::DirectX81Renderer - Official Direct3D 9 based renderer module for CEGUI";
00106 }
00107
00108
00109
00110
00111
00112 DirectX9Renderer::~DirectX9Renderer(void)
00113 {
00114 if (d_buffer != NULL)
00115 {
00116 d_buffer->Release();
00117 }
00118
00119 destroyAllTextures();
00120
00121 if (d_device != NULL)
00122 {
00123 d_device->Release();
00124 }
00125 }
00126
00127
00128
00129
00130
00131 void DirectX9Renderer::addQuad(const Rect& dest_rect, float z, const Texture* tex, const Rect& texture_rect, const ColourRect& colours, QuadSplitMode quad_split_mode)
00132 {
00133
00134 if (!d_queueing)
00135 {
00136 renderQuadDirect(dest_rect, z, tex, texture_rect, colours, quad_split_mode);
00137 }
00138 else
00139 {
00140 QuadInfo quad;
00141
00142 quad.position = dest_rect;
00143 quad.z = z;
00144 quad.texture = ((DirectX9Texture*)tex)->getD3DTexture();
00145 quad.texPosition = texture_rect;
00146 quad.topLeftCol = colours.d_top_left.getARGB();
00147 quad.topRightCol = colours.d_top_right.getARGB();
00148 quad.bottomLeftCol = colours.d_bottom_left.getARGB();
00149 quad.bottomRightCol = colours.d_bottom_right.getARGB();
00150
00151
00152 quad.position.offset(Point(-0.5f, -0.5f));
00153
00154
00155 quad.splitMode = quad_split_mode;
00156
00157 d_quadlist.insert(quad);
00158 }
00159
00160 }
00161
00162
00163
00164
00165
00166 void DirectX9Renderer::doRender(void)
00167 {
00168 d_currTexture = NULL;
00169
00170 initPerFrameStates();
00171
00172 bool locked = false;
00173 QuadVertex* buffmem;
00174
00175
00176 for (QuadList::iterator i = d_quadlist.begin(); i != d_quadlist.end(); ++i)
00177 {
00178 const QuadInfo& quad = (*i);
00179
00180
00181 if (d_currTexture != quad.texture)
00182 {
00183 if (locked)
00184 {
00185 d_buffer->Unlock();
00186 locked = false;
00187 }
00188
00189
00190 renderVBuffer();
00191
00192
00193 d_device->SetTexture(0, quad.texture);
00194 d_currTexture = quad.texture;
00195 }
00196
00197 if (!locked)
00198 {
00199 if (FAILED(d_buffer->Lock(0, 0, (void**)&buffmem, D3DLOCK_DISCARD)))
00200 {
00201 return;
00202 }
00203
00204 locked = true;
00205 }
00206
00207
00208 buffmem->x = quad.position.d_left;
00209 buffmem->y = quad.position.d_top;
00210 buffmem->z = quad.z;
00211 buffmem->rhw = 1.0f;
00212 buffmem->diffuse = quad.topLeftCol;
00213 buffmem->tu1 = quad.texPosition.d_left;
00214 buffmem->tv1 = quad.texPosition.d_top;
00215 ++buffmem;
00216
00217
00218
00219
00220 if (quad.splitMode == TopLeftToBottomRight)
00221 {
00222 buffmem->x = quad.position.d_right;
00223 buffmem->y = quad.position.d_bottom;
00224 buffmem->z = quad.z;
00225 buffmem->rhw = 1.0f;
00226 buffmem->diffuse = quad.bottomRightCol;
00227 buffmem->tu1 = quad.texPosition.d_right;
00228 buffmem->tv1 = quad.texPosition.d_bottom;
00229 }
00230
00231 else
00232 {
00233 buffmem->x = quad.position.d_right;
00234 buffmem->y = quad.position.d_top;
00235 buffmem->z = quad.z;
00236 buffmem->rhw = 1.0f;
00237 buffmem->diffuse = quad.topRightCol;
00238 buffmem->tu1 = quad.texPosition.d_right;
00239 buffmem->tv1 = quad.texPosition.d_top;
00240 }
00241 ++buffmem;
00242
00243
00244 buffmem->x = quad.position.d_left;
00245 buffmem->y = quad.position.d_bottom;
00246 buffmem->z = quad.z;
00247 buffmem->rhw = 1.0f;
00248 buffmem->diffuse = quad.bottomLeftCol;
00249 buffmem->tu1 = quad.texPosition.d_left;
00250 buffmem->tv1 = quad.texPosition.d_bottom;
00251 ++buffmem;
00252
00253
00254 buffmem->x = quad.position.d_right;
00255 buffmem->y = quad.position.d_top;
00256 buffmem->z = quad.z;
00257 buffmem->rhw = 1.0f;
00258 buffmem->diffuse = quad.topRightCol;
00259 buffmem->tu1 = quad.texPosition.d_right;
00260 buffmem->tv1 = quad.texPosition.d_top;
00261 ++buffmem;
00262
00263
00264 buffmem->x = quad.position.d_right;
00265 buffmem->y = quad.position.d_bottom;
00266 buffmem->z = quad.z;
00267 buffmem->rhw = 1.0f;
00268 buffmem->diffuse = quad.bottomRightCol;
00269 buffmem->tu1 = quad.texPosition.d_right;
00270 buffmem->tv1 = quad.texPosition.d_bottom;
00271 ++buffmem;
00272
00273
00274
00275
00276 if (quad.splitMode == TopLeftToBottomRight)
00277 {
00278 buffmem->x = quad.position.d_left;
00279 buffmem->y = quad.position.d_top;
00280 buffmem->z = quad.z;
00281 buffmem->rhw = 1.0f;
00282 buffmem->diffuse = quad.topLeftCol;
00283 buffmem->tu1 = quad.texPosition.d_left;
00284 buffmem->tv1 = quad.texPosition.d_top;
00285 }
00286
00287 else
00288 {
00289 buffmem->x = quad.position.d_left;
00290 buffmem->y = quad.position.d_bottom;
00291 buffmem->z = quad.z;
00292 buffmem->rhw = 1.0f;
00293 buffmem->diffuse = quad.bottomLeftCol;
00294 buffmem->tu1 = quad.texPosition.d_left;
00295 buffmem->tv1 = quad.texPosition.d_bottom;
00296 }
00297 ++buffmem;
00298
00299
00300 d_bufferPos += VERTEX_PER_QUAD;
00301
00302
00303 if (d_bufferPos >= (VERTEXBUFFER_CAPACITY - VERTEX_PER_QUAD))
00304 {
00305 if (locked)
00306 {
00307 d_buffer->Unlock();
00308 locked = false;
00309 }
00310
00311 renderVBuffer();
00312 }
00313
00314 }
00315
00316 if (locked)
00317 {
00318 d_buffer->Unlock();
00319 locked = false;
00320 }
00321
00322 renderVBuffer();
00323 }
00324
00325
00326
00327
00328
00329 void DirectX9Renderer::clearRenderList(void)
00330 {
00331 d_quadlist.clear();
00332 }
00333
00334
00335
00336
00337
00338 Texture* DirectX9Renderer::createTexture(void)
00339 {
00340 DirectX9Texture* tex = new DirectX9Texture(this);
00341 d_texturelist.push_back(tex);
00342 return tex;
00343 }
00344
00345
00346
00347
00348
00349 Texture* DirectX9Renderer::createTexture(const String& filename, const String& resourceGroup)
00350 {
00351 DirectX9Texture* tex = (DirectX9Texture*)createTexture();
00352 tex->loadFromFile(filename, resourceGroup);
00353
00354 return tex;
00355 }
00356
00357
00358
00359
00360
00361 Texture* DirectX9Renderer::createTexture(float size)
00362 {
00363 DirectX9Texture* tex = (DirectX9Texture*)createTexture();
00364 tex->setD3DTextureSize((uint)size);
00365
00366 return tex;
00367 }
00368
00369
00370
00371
00372 void DirectX9Renderer::destroyTexture(Texture* texture)
00373 {
00374 if (texture != NULL)
00375 {
00376 DirectX9Texture* tex = (DirectX9Texture*)texture;
00377 d_texturelist.remove(tex);
00378 delete tex;
00379 }
00380
00381 }
00382
00383
00384
00385
00386
00387 void DirectX9Renderer::destroyAllTextures(void)
00388 {
00389 while (!d_texturelist.empty())
00390 {
00391 destroyTexture(*(d_texturelist.begin()));
00392 }
00393 }
00394
00395
00396
00397
00398
00399 void DirectX9Renderer::initPerFrameStates(void)
00400 {
00401
00402 d_device->SetStreamSource(0, d_buffer, 0, sizeof(QuadVertex));
00403 d_device->SetFVF(VERTEX_FVF);
00404 d_device->SetVertexShader( NULL );
00405 d_device->SetPixelShader( NULL );
00406
00407
00408 d_device->SetRenderState(D3DRS_ZENABLE, D3DZB_FALSE);
00409 d_device->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID);
00410 d_device->SetRenderState(D3DRS_ALPHATESTENABLE, FALSE);
00411 d_device->SetRenderState(D3DRS_ZWRITEENABLE, FALSE);
00412 d_device->SetRenderState(D3DRS_FOGENABLE, FALSE);
00413 d_device->SetRenderState(D3DRS_CULLMODE, D3DCULL_CCW);
00414
00415
00416
00417 d_device->SetSamplerState( 0, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP);
00418 d_device->SetSamplerState( 0, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP);
00419
00420
00421 d_device->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
00422 d_device->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_DIFFUSE);
00423 d_device->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE);
00424
00425
00426 d_device->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE);
00427 d_device->SetTextureStageState(0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE);
00428 d_device->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_MODULATE);
00429
00430
00431 d_device->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
00432 d_device->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
00433
00434
00435 d_device->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
00436 d_device->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
00437 d_device->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
00438 }
00439
00440
00441
00442
00443
00444 void DirectX9Renderer::renderVBuffer(void)
00445 {
00446
00447 if (d_bufferPos == 0)
00448 {
00449 return;
00450 }
00451
00452
00453 d_device->DrawPrimitive(D3DPT_TRIANGLELIST, 0, (d_bufferPos / VERTEX_PER_TRIANGLE));
00454
00455
00456 d_bufferPos = 0;
00457 }
00458
00459
00460
00461
00462
00463 void DirectX9Renderer::sortQuads(void)
00464 {
00465 }
00466
00467
00468
00469
00470
00471 void DirectX9Renderer::renderQuadDirect(const Rect& dest_rect, float z, const Texture* tex, const Rect& texture_rect, const ColourRect& colours, QuadSplitMode quad_split_mode)
00472 {
00473
00474 Rect final_rect(dest_rect);
00475 final_rect.offset(Point(-0.5f, -0.5f));
00476
00477 QuadVertex* buffmem;
00478
00479 initPerFrameStates();
00480 d_device->SetTexture(0, ((DirectX9Texture*)tex)->getD3DTexture());
00481
00482 if (SUCCEEDED(d_buffer->Lock(0, VERTEX_PER_QUAD * sizeof(QuadVertex), (void**)&buffmem, D3DLOCK_DISCARD)))
00483 {
00484
00485 buffmem->x = final_rect.d_left;
00486 buffmem->y = final_rect.d_top;
00487 buffmem->z = z;
00488 buffmem->rhw = 1.0f;
00489 buffmem->diffuse = colours.d_top_left.getARGB();
00490 buffmem->tu1 = texture_rect.d_left;
00491 buffmem->tv1 = texture_rect.d_top;
00492 ++buffmem;
00493
00494
00495
00496
00497 if (quad_split_mode == TopLeftToBottomRight)
00498 {
00499 buffmem->x = final_rect.d_right;
00500 buffmem->y = final_rect.d_bottom;
00501 buffmem->z = z;
00502 buffmem->rhw = 1.0f;
00503 buffmem->diffuse = colours.d_bottom_right.getARGB();
00504 buffmem->tu1 = texture_rect.d_right;
00505 buffmem->tv1 = texture_rect.d_bottom;
00506 }
00507
00508 else
00509 {
00510 buffmem->x = final_rect.d_right;
00511 buffmem->y = final_rect.d_top;
00512 buffmem->z = z;
00513 buffmem->rhw = 1.0f;
00514 buffmem->diffuse = colours.d_top_right.getARGB();
00515 buffmem->tu1 = texture_rect.d_right;
00516 buffmem->tv1 = texture_rect.d_top;
00517 }
00518 ++buffmem;
00519
00520
00521 buffmem->x = final_rect.d_left;
00522 buffmem->y = final_rect.d_bottom;
00523 buffmem->z = z;
00524 buffmem->rhw = 1.0f;
00525 buffmem->diffuse = colours.d_bottom_left.getARGB();
00526 buffmem->tu1 = texture_rect.d_left;
00527 buffmem->tv1 = texture_rect.d_bottom;
00528 ++buffmem;
00529
00530
00531 buffmem->x = final_rect.d_right;
00532 buffmem->y = final_rect.d_top;
00533 buffmem->z = z;
00534 buffmem->rhw = 1.0f;
00535 buffmem->diffuse = colours.d_top_right.getARGB();
00536 buffmem->tu1 = texture_rect.d_right;
00537 buffmem->tv1 = texture_rect.d_top;
00538 ++buffmem;
00539
00540
00541 buffmem->x = final_rect.d_right;
00542 buffmem->y = final_rect.d_bottom;
00543 buffmem->z = z;
00544 buffmem->rhw = 1.0f;
00545 buffmem->diffuse = colours.d_bottom_right.getARGB();
00546 buffmem->tu1 = texture_rect.d_right;
00547 buffmem->tv1 = texture_rect.d_bottom;
00548 ++buffmem;
00549
00550
00551
00552
00553 if (quad_split_mode == TopLeftToBottomRight)
00554 {
00555 buffmem->x = final_rect.d_left;
00556 buffmem->y = final_rect.d_top;
00557 buffmem->z = z;
00558 buffmem->rhw = 1.0f;
00559 buffmem->diffuse = colours.d_top_left.getARGB();
00560 buffmem->tu1 = texture_rect.d_left;
00561 buffmem->tv1 = texture_rect.d_top;
00562 }
00563
00564 else
00565 {
00566 buffmem->x = final_rect.d_left;
00567 buffmem->y = final_rect.d_bottom;
00568 buffmem->z = z;
00569 buffmem->rhw = 1.0f;
00570 buffmem->diffuse = colours.d_bottom_left.getARGB();
00571 buffmem->tu1 = texture_rect.d_left;
00572 buffmem->tv1 = texture_rect.d_bottom;
00573 }
00574
00575 d_buffer->Unlock();
00576 d_bufferPos = VERTEX_PER_QUAD;
00577
00578 renderVBuffer();
00579 }
00580
00581 }
00582
00583
00584
00585
00586
00587
00588 void DirectX9Renderer::preD3DReset(void)
00589 {
00590
00591 if (FAILED(d_buffer->Release()))
00592 {
00593 throw RendererException("DirectX9Renderer::preD3DReset - Failed to release the VertexBuffer used by the DirectX9Renderer object.");
00594 }
00595
00596 d_buffer = 0;
00597
00598
00599 std::list<DirectX9Texture*>::iterator ctex = d_texturelist.begin();
00600 std::list<DirectX9Texture*>::iterator endtex = d_texturelist.end();
00601
00602 for (; ctex != endtex; ++ctex)
00603 {
00604 (*ctex)->preD3DReset();
00605 }
00606
00607 }
00608
00609
00610
00611
00612
00613
00614 void DirectX9Renderer::postD3DReset(void)
00615 {
00616
00617 if (FAILED(d_device->CreateVertexBuffer((VERTEXBUFFER_CAPACITY * sizeof(QuadVertex)), D3DUSAGE_DYNAMIC|D3DUSAGE_WRITEONLY, VERTEX_FVF, D3DPOOL_DEFAULT, &d_buffer, NULL)))
00618 {
00619 throw RendererException("DirectX9Renderer::preD3DReset - Failed to create the VertexBuffer for use by the DirectX9Renderer object.");
00620 }
00621
00622
00623 std::list<DirectX9Texture*>::iterator ctex = d_texturelist.begin();
00624 std::list<DirectX9Texture*>::iterator endtex = d_texturelist.end();
00625
00626 for (; ctex != endtex; ++ctex)
00627 {
00628 (*ctex)->postD3DReset();
00629 }
00630
00631
00632 setDisplaySize(getViewportSize());
00633
00634
00635
00636 System::getSingleton().signalRedraw();
00637 }
00638
00639
00640
00641
00642 Size DirectX9Renderer::getViewportSize(void)
00643 {
00644
00645 D3DVIEWPORT9 vp;
00646
00647 if (FAILED(d_device->GetViewport(&vp)))
00648 {
00649 throw std::exception("Unable to access required view port information from Direct3DDevice9.");
00650 }
00651 else
00652 {
00653 return Size((float)vp.Width, (float)vp.Height);
00654 }
00655
00656 }
00657
00658
00659
00660
00661
00662 void DirectX9Renderer::setDisplaySize(const Size& sz)
00663 {
00664 if (d_display_area.getSize() != sz)
00665 {
00666 d_display_area.setSize(sz);
00667
00668 EventArgs args;
00669 fireEvent(EventDisplaySizeChanged, args, EventNamespace);
00670 }
00671
00672 }
00673
00674
00675 }
00676