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