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