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