00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #include "wglGraphicsBuffer.h"
00016 #include "wglGraphicsPipe.h"
00017 #include "config_wgldisplay.h"
00018 #include "glgsg.h"
00019 #include "pStatTimer.h"
00020
00021 #include <wingdi.h>
00022
00023 TypeHandle wglGraphicsBuffer::_type_handle;
00024
00025
00026
00027
00028
00029
00030
00031 wglGraphicsBuffer::
00032 wglGraphicsBuffer(GraphicsEngine *engine, GraphicsPipe *pipe,
00033 const string &name,
00034 const FrameBufferProperties &fb_prop,
00035 const WindowProperties &win_prop,
00036 int flags,
00037 GraphicsStateGuardian *gsg,
00038 GraphicsOutput *host) :
00039 GraphicsBuffer(engine, pipe, name, fb_prop, win_prop, flags, gsg, host)
00040 {
00041 _pbuffer = (HPBUFFERARB)0;
00042 _pbuffer_dc = (HDC)0;
00043 release_pbuffer();
00044
00045
00046
00047 _screenshot_buffer_type = _draw_buffer_type;
00048 }
00049
00050
00051
00052
00053
00054
00055 wglGraphicsBuffer::
00056 ~wglGraphicsBuffer() {
00057 }
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068 bool wglGraphicsBuffer::
00069 begin_frame(FrameMode mode, Thread *current_thread) {
00070
00071 begin_frame_spam(mode);
00072 if (_gsg == (GraphicsStateGuardian *)NULL) {
00073 return false;
00074 }
00075
00076 wglGraphicsStateGuardian *wglgsg;
00077 DCAST_INTO_R(wglgsg, _gsg, false);
00078
00079 HGLRC context = wglgsg->get_context(_pbuffer_dc);
00080 if (context == 0) {
00081 return false;
00082 }
00083
00084 if (_fb_properties.is_single_buffered()) {
00085 wglgsg->_wglReleaseTexImageARB(_pbuffer, WGL_FRONT_LEFT_ARB);
00086 } else {
00087 wglgsg->_wglReleaseTexImageARB(_pbuffer, WGL_BACK_LEFT_ARB);
00088 }
00089
00090 if (!rebuild_bitplanes()) {
00091 wglGraphicsPipe::wgl_make_current(0, 0, &_make_current_pcollector);
00092 return false;
00093 }
00094
00095 wglGraphicsPipe::wgl_make_current(_pbuffer_dc, context,
00096 &_make_current_pcollector);
00097
00098 if (mode == FM_render) {
00099 CDLockedReader cdata(_cycler);
00100 for (size_t i = 0; i != cdata->_textures.size(); ++i) {
00101 const RenderTexture &rt = cdata->_textures[i];
00102 RenderTextureMode rtm_mode = rt._rtm_mode;
00103 RenderTexturePlane plane = rt._plane;
00104 if (rtm_mode == RTM_bind_or_copy && plane != RTP_color) {
00105 CDWriter cdataw(_cycler, cdata, false);
00106 nassertr(cdata->_textures.size() == cdataw->_textures.size(), false);
00107 cdataw->_textures[i]._rtm_mode = RTM_copy_texture;
00108 }
00109 }
00110 clear_cube_map_selection();
00111 }
00112
00113 _gsg->set_current_properties(&get_fb_properties());
00114 return _gsg->begin_frame(current_thread);
00115 }
00116
00117
00118
00119
00120
00121
00122
00123
00124 void wglGraphicsBuffer::
00125 end_frame(FrameMode mode, Thread *current_thread) {
00126 end_frame_spam(mode);
00127 nassertv(_gsg != (GraphicsStateGuardian *)NULL);
00128
00129 if (mode == FM_render) {
00130 copy_to_textures();
00131 bind_texture_to_pbuffer();
00132 }
00133
00134 _gsg->end_frame(current_thread);
00135
00136 if (mode == FM_render) {
00137 trigger_flip();
00138 clear_cube_map_selection();
00139 }
00140 }
00141
00142
00143
00144
00145
00146
00147
00148 void wglGraphicsBuffer::
00149 bind_texture_to_pbuffer() {
00150 wglGraphicsStateGuardian *wglgsg;
00151 DCAST_INTO_V(wglgsg, _gsg);
00152
00153
00154
00155
00156 int tex_index = -1;
00157 CDLockedReader cdata(_cycler);
00158 for (size_t i = 0; i != cdata->_textures.size(); ++i) {
00159 const RenderTexture &rt = cdata->_textures[i];
00160 RenderTexturePlane plane = rt._plane;
00161 if (plane == RTP_color) {
00162 tex_index = i;
00163 break;
00164 }
00165 }
00166
00167 if (tex_index >= 0) {
00168 const RenderTexture &rt = cdata->_textures[tex_index];
00169 Texture *tex = rt._texture;
00170 if ((_pbuffer_bound != 0)&&(_pbuffer_bound != tex)) {
00171 _pbuffer_bound->release(wglgsg->get_prepared_objects());
00172 _pbuffer_bound = 0;
00173 }
00174 tex->set_size_padded(_x_size, _y_size);
00175 if (tex->get_match_framebuffer_format()) {
00176 if (_fb_properties.get_alpha_bits()) {
00177 tex->set_format(Texture::F_rgba);
00178 } else {
00179 tex->set_format(Texture::F_rgb);
00180 }
00181 }
00182 TextureContext *tc = tex->prepare_now(0, _gsg->get_prepared_objects(), _gsg);
00183 nassertv(tc != (TextureContext *)NULL);
00184 CLP(TextureContext) *gtc = DCAST(CLP(TextureContext), tc);
00185 GLenum target = wglgsg->get_texture_target(tex->get_texture_type());
00186 if (target == GL_NONE) {
00187 CDWriter cdataw(_cycler, cdata, false);
00188 nassertv(cdata->_textures.size() == cdataw->_textures.size());
00189 cdataw->_textures[tex_index]._rtm_mode = RTM_copy_texture;
00190 return;
00191 }
00192 GLP(BindTexture)(target, gtc->_index);
00193 if (_fb_properties.is_single_buffered()) {
00194 wglgsg->_wglBindTexImageARB(_pbuffer, WGL_FRONT_LEFT_ARB);
00195 } else {
00196 wglgsg->_wglBindTexImageARB(_pbuffer, WGL_BACK_LEFT_ARB);
00197 }
00198 _pbuffer_bound = tex;
00199 } else {
00200 if (_pbuffer_bound != 0) {
00201 _pbuffer_bound->release(wglgsg->get_prepared_objects());
00202 _pbuffer_bound = 0;
00203 }
00204 }
00205 }
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216 void wglGraphicsBuffer::
00217 select_cube_map(int cube_map_index) {
00218 wglGraphicsStateGuardian *wglgsg;
00219 DCAST_INTO_V(wglgsg, _gsg);
00220
00221 nassertv(wglgsg->_wglSetPbufferAttribARB != NULL);
00222
00223 static const int max_attrib_list = 64;
00224 int iattrib_list[max_attrib_list];
00225 int ni = 0;
00226
00227 iattrib_list[ni++] = WGL_CUBE_MAP_FACE_ARB;
00228 iattrib_list[ni++] = WGL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB + cube_map_index;
00229
00230
00231 nassertv(ni <= max_attrib_list);
00232 iattrib_list[ni] = 0;
00233
00234 wglgsg->_wglSetPbufferAttribARB(_pbuffer, iattrib_list);
00235 }
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247 void wglGraphicsBuffer::
00248 process_events() {
00249 GraphicsBuffer::process_events();
00250
00251 MSG msg;
00252
00253
00254
00255
00256 while (PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE)) {
00257 process_1_event();
00258 }
00259 }
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269 bool wglGraphicsBuffer::
00270 get_supports_render_texture() const {
00271 if (_gsg == (GraphicsStateGuardian *)NULL) {
00272 return false;
00273 }
00274
00275 wglGraphicsStateGuardian *wglgsg;
00276 DCAST_INTO_R(wglgsg, _gsg, false);
00277 return wglgsg->get_supports_wgl_render_texture();
00278 }
00279
00280
00281
00282
00283
00284
00285
00286 void wglGraphicsBuffer::
00287 close_buffer() {
00288 if (_gsg != (GraphicsStateGuardian *)NULL) {
00289 wglGraphicsStateGuardian *wglgsg;
00290 DCAST_INTO_V(wglgsg, _gsg);
00291
00292 _gsg.clear();
00293 }
00294
00295 release_pbuffer();
00296
00297 _is_valid = false;
00298 }
00299
00300
00301
00302
00303
00304
00305
00306
00307 bool wglGraphicsBuffer::
00308 open_buffer() {
00309
00310
00311
00312
00313
00314 _fb_properties.set_back_buffers(0);
00315 _draw_buffer_type = RenderBuffer::T_front;
00316 _screenshot_buffer_type = RenderBuffer::T_front;
00317
00318
00319
00320 wglGraphicsStateGuardian *wglgsg;
00321 if (_gsg == 0) {
00322
00323 wglgsg = new wglGraphicsStateGuardian(_engine, _pipe, NULL);
00324 wglgsg->choose_pixel_format(_fb_properties, true);
00325 _gsg = wglgsg;
00326 } else {
00327
00328
00329 DCAST_INTO_R(wglgsg, _gsg, false);
00330 if ((!wglgsg->get_fb_properties().subsumes(_fb_properties))||
00331 (!wglgsg->get_fb_properties().is_single_buffered())||
00332 (!wglgsg->pfnum_supports_pbuffer())) {
00333 wglgsg = new wglGraphicsStateGuardian(_engine, _pipe, wglgsg);
00334 wglgsg->choose_pixel_format(_fb_properties, true);
00335 _gsg = wglgsg;
00336 }
00337 }
00338
00339
00340
00341 HDC twindow_dc = wglgsg->get_twindow_dc();
00342 if (twindow_dc == 0) {
00343
00344 _gsg = NULL;
00345 return false;
00346 }
00347 HGLRC context = wglgsg->get_context(twindow_dc);
00348 if (context == 0) {
00349 _gsg = NULL;
00350 return false;
00351 }
00352 wglGraphicsPipe::wgl_make_current(twindow_dc, context,
00353 &_make_current_pcollector);
00354 wglgsg->reset_if_new();
00355 wglgsg->report_my_gl_errors();
00356 if (!wglgsg->get_fb_properties().verify_hardware_software
00357 (_fb_properties,wglgsg->get_gl_renderer())) {
00358 _gsg = NULL;
00359 return false;
00360 }
00361 _fb_properties = wglgsg->get_fb_properties();
00362
00363
00364
00365
00366
00367 if (!rebuild_bitplanes()) {
00368 wglGraphicsPipe::wgl_make_current(0, 0, &_make_current_pcollector);
00369 _gsg = NULL;
00370 return false;
00371 }
00372
00373 _is_valid = true;
00374
00375 return true;
00376 }
00377
00378
00379
00380
00381
00382
00383
00384
00385 void wglGraphicsBuffer::
00386 release_pbuffer() {
00387 if (_gsg == 0) {
00388 return;
00389 }
00390
00391 wglGraphicsStateGuardian *wglgsg;
00392 DCAST_INTO_V(wglgsg, _gsg);
00393
00394 if (_pbuffer_bound != 0) {
00395 _pbuffer_bound->release(wglgsg->get_prepared_objects());
00396 _pbuffer_bound = 0;
00397 }
00398 wglGraphicsPipe::wgl_make_current(0, 0, NULL);
00399 if (_pbuffer_dc) {
00400 wglgsg->_wglReleasePbufferDCARB(_pbuffer, _pbuffer_dc);
00401 }
00402 if (_pbuffer) {
00403 wglgsg->_wglDestroyPbufferARB(_pbuffer);
00404 }
00405 _pbuffer = (HPBUFFERARB)0;
00406 _pbuffer_dc = (HDC)0;
00407 _pbuffer_mipmap = false;
00408 _pbuffer_sizex = 0;
00409 _pbuffer_sizey = 0;
00410 _pbuffer_type = Texture::TT_2d_texture;
00411 }
00412
00413
00414
00415
00416
00417
00418
00419
00420
00421 bool wglGraphicsBuffer::
00422 rebuild_bitplanes() {
00423 wglGraphicsStateGuardian *wglgsg;
00424 DCAST_INTO_R(wglgsg, _gsg, false);
00425
00426 if (!wglgsg->_supports_pbuffer) {
00427 wgldisplay_cat.info()
00428 << "PBuffers not supported by GL implementation.\n";
00429 return false;
00430 }
00431
00432
00433 Texture *bindtexture = NULL;
00434 for (int i=0; i<count_textures(); i++) {
00435 if ((get_rtm_mode(i) == RTM_bind_or_copy)&&
00436 (get_texture(i)->get_format() != Texture::F_depth_stencil)) {
00437 bindtexture = get_texture(i);
00438 break;
00439 }
00440 }
00441
00442
00443
00444
00445 if (_pbuffer_dc) {
00446 int flag = 0;
00447 wglgsg->_wglQueryPbufferARB(_pbuffer, WGL_PBUFFER_LOST_ARB, &flag);
00448 if (flag != 0) {
00449 release_pbuffer();
00450 }
00451 }
00452
00453
00454
00455
00456 if ((_host != 0)&&(_creation_flags & GraphicsPipe::BF_size_track_host)) {
00457 if ((_host->get_x_size() != _x_size)||
00458 (_host->get_y_size() != _y_size)) {
00459 set_size_and_recalc(_host->get_x_size(),
00460 _host->get_y_size());
00461 }
00462 }
00463 int desired_x = _x_size;
00464 int desired_y = _y_size;
00465 if ((bindtexture != 0)&&(Texture::get_textures_power_2() != ATS_none)) {
00466 desired_x = Texture::up_to_power_2(desired_x);
00467 desired_y = Texture::up_to_power_2(desired_y);
00468 }
00469 bool desired_mipmap = false;
00470 Texture::TextureType desired_type = Texture::TT_2d_texture;
00471 if (bindtexture != 0) {
00472 desired_mipmap = bindtexture->uses_mipmaps();
00473 desired_type = bindtexture->get_texture_type();
00474 }
00475
00476 if ((_pbuffer != 0)&&
00477 (_pbuffer_sizex == desired_x)&&
00478 (_pbuffer_sizey == desired_y)&&
00479 (_pbuffer_mipmap == desired_mipmap)&&
00480 (_pbuffer_type == desired_type)) {
00481
00482 return true;
00483 }
00484
00485
00486
00487 release_pbuffer();
00488
00489
00490
00491 int pfnum = wglgsg->get_pfnum();
00492
00493 static const int max_attrib_list = 64;
00494 int iattrib_list[max_attrib_list];
00495 int ni = 0;
00496
00497 if (_fb_properties.get_alpha_bits()) {
00498 iattrib_list[ni++] = WGL_TEXTURE_FORMAT_ARB;
00499 iattrib_list[ni++] = WGL_TEXTURE_RGBA_ARB;
00500 } else {
00501 iattrib_list[ni++] = WGL_TEXTURE_FORMAT_ARB;
00502 iattrib_list[ni++] = WGL_TEXTURE_RGB_ARB;
00503 }
00504
00505 if (desired_mipmap) {
00506 iattrib_list[ni++] = WGL_MIPMAP_TEXTURE_ARB;
00507 iattrib_list[ni++] = 1;
00508 }
00509
00510 switch (desired_type) {
00511 case Texture::TT_cube_map:
00512 iattrib_list[ni++] = WGL_TEXTURE_TARGET_ARB;
00513 iattrib_list[ni++] = WGL_TEXTURE_CUBE_MAP_ARB;
00514 break;
00515
00516 case Texture::TT_1d_texture:
00517 iattrib_list[ni++] = WGL_TEXTURE_TARGET_ARB;
00518 iattrib_list[ni++] = WGL_TEXTURE_1D_ARB;
00519 break;
00520
00521 default:
00522 iattrib_list[ni++] = WGL_TEXTURE_TARGET_ARB;
00523 iattrib_list[ni++] = WGL_TEXTURE_2D_ARB;
00524 }
00525
00526
00527 nassertr(ni <= max_attrib_list, false);
00528 iattrib_list[ni] = 0;
00529
00530 HDC twindow_dc = wglgsg->get_twindow_dc();
00531 if (twindow_dc == 0) {
00532 return false;
00533 }
00534
00535 HGLRC context = wglgsg->get_context(twindow_dc);
00536 if (context == 0) {
00537 return false;
00538 }
00539 wglGraphicsPipe::wgl_make_current(twindow_dc, context,
00540 &_make_current_pcollector);
00541
00542 _pbuffer = wglgsg->_wglCreatePbufferARB(twindow_dc, pfnum,
00543 desired_x, desired_y, iattrib_list);
00544
00545 if (_pbuffer == 0) {
00546 wgldisplay_cat.info()
00547 << "Attempt to create pbuffer failed.\n";
00548 return false;
00549 }
00550
00551 _pbuffer_dc = wglgsg->_wglGetPbufferDCARB(_pbuffer);
00552 _pbuffer_mipmap = desired_mipmap;
00553 _pbuffer_type = desired_type;
00554 _pbuffer_sizex = desired_x;
00555 _pbuffer_sizey = desired_y;
00556
00557 return true;
00558 }
00559
00560
00561
00562
00563
00564
00565 void wglGraphicsBuffer::
00566 process_1_event() {
00567 MSG msg;
00568
00569 if (!GetMessage(&msg, NULL, 0, 0)) {
00570
00571
00572 exit(msg.wParam);
00573 }
00574
00575
00576 TranslateMessage(&msg);
00577
00578 DispatchMessage(&msg);
00579 }
00580
00581