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