00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #include "eglGraphicsPixmap.h"
00016 #include "eglGraphicsWindow.h"
00017 #include "eglGraphicsStateGuardian.h"
00018 #include "config_egldisplay.h"
00019 #include "eglGraphicsPipe.h"
00020
00021 #include "graphicsPipe.h"
00022 #include "pStatTimer.h"
00023
00024 TypeHandle eglGraphicsPixmap::_type_handle;
00025
00026
00027
00028
00029
00030
00031 eglGraphicsPixmap::
00032 eglGraphicsPixmap(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 eglGraphicsPipe *egl_pipe;
00042 DCAST_INTO_V(egl_pipe, _pipe);
00043 _display = egl_pipe->get_display();
00044 _egl_display = egl_pipe->_egl_display;
00045 _drawable = None;
00046 _x_pixmap = None;
00047 _egl_surface = EGL_NO_SURFACE;
00048
00049
00050
00051 _screenshot_buffer_type = _draw_buffer_type;
00052 }
00053
00054
00055
00056
00057
00058
00059 eglGraphicsPixmap::
00060 ~eglGraphicsPixmap() {
00061 nassertv(_x_pixmap == None && _egl_surface == EGL_NO_SURFACE);
00062 }
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073 bool eglGraphicsPixmap::
00074 begin_frame(FrameMode mode, Thread *current_thread) {
00075 PStatTimer timer(_make_current_pcollector, current_thread);
00076
00077 begin_frame_spam(mode);
00078 if (_gsg == (GraphicsStateGuardian *)NULL) {
00079 return false;
00080 }
00081
00082 eglGraphicsStateGuardian *eglgsg;
00083 DCAST_INTO_R(eglgsg, _gsg, false);
00084 if (!eglMakeCurrent(_egl_display, _egl_surface, _egl_surface, eglgsg->_context)) {
00085 egldisplay_cat.error() << "Failed to call eglMakeCurrent: "
00086 << get_egl_error_string(eglGetError()) << "\n";
00087 }
00088
00089
00090
00091
00092
00093 eglgsg->reset_if_new();
00094
00095 if (mode == FM_render) {
00096 CDLockedReader cdata(_cycler);
00097 for (size_t i = 0; i != cdata->_textures.size(); ++i) {
00098 const RenderTexture &rt = cdata->_textures[i];
00099 RenderTextureMode rtm_mode = rt._rtm_mode;
00100 if (rtm_mode == RTM_bind_or_copy) {
00101 CDWriter cdataw(_cycler, cdata, false);
00102 nassertr(cdata->_textures.size() == cdataw->_textures.size(), false);
00103 cdataw->_textures[i]._rtm_mode = RTM_copy_texture;
00104 }
00105 }
00106 clear_cube_map_selection();
00107 }
00108
00109 _gsg->set_current_properties(&get_fb_properties());
00110 return _gsg->begin_frame(current_thread);
00111 }
00112
00113
00114
00115
00116
00117
00118
00119
00120 void eglGraphicsPixmap::
00121 end_frame(FrameMode mode, Thread *current_thread) {
00122 end_frame_spam(mode);
00123 nassertv(_gsg != (GraphicsStateGuardian *)NULL);
00124
00125 if (mode == FM_render) {
00126 copy_to_textures();
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 eglGraphicsPixmap::
00144 close_buffer() {
00145 if (_gsg != (GraphicsStateGuardian *)NULL) {
00146 if (!eglMakeCurrent(_egl_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT)) {
00147 egldisplay_cat.error() << "Failed to call eglMakeCurrent: "
00148 << get_egl_error_string(eglGetError()) << "\n";
00149 }
00150 _gsg.clear();
00151 }
00152
00153 if (_egl_surface != EGL_NO_SURFACE) {
00154 if (!eglDestroySurface(_egl_display, _egl_surface)) {
00155 egldisplay_cat.error() << "Failed to destroy surface: "
00156 << get_egl_error_string(eglGetError()) << "\n";
00157 }
00158 _egl_surface = EGL_NO_SURFACE;
00159 }
00160
00161 if (_x_pixmap != None) {
00162 XFreePixmap(_display, _x_pixmap);
00163 _x_pixmap = None;
00164 }
00165
00166 _is_valid = false;
00167 }
00168
00169
00170
00171
00172
00173
00174
00175
00176 bool eglGraphicsPixmap::
00177 open_buffer() {
00178 eglGraphicsPipe *egl_pipe;
00179 DCAST_INTO_R(egl_pipe, _pipe, false);
00180
00181
00182 eglGraphicsStateGuardian *eglgsg;
00183 if (_gsg == 0) {
00184
00185 eglgsg = new eglGraphicsStateGuardian(_engine, _pipe, NULL);
00186 eglgsg->choose_pixel_format(_fb_properties, _display, egl_pipe->get_screen(), false, true);
00187 _gsg = eglgsg;
00188 } else {
00189
00190
00191 DCAST_INTO_R(eglgsg, _gsg, false);
00192 if (!eglgsg->get_fb_properties().subsumes(_fb_properties)) {
00193 eglgsg = new eglGraphicsStateGuardian(_engine, _pipe, eglgsg);
00194 eglgsg->choose_pixel_format(_fb_properties, _display, egl_pipe->get_screen(), false, true);
00195 _gsg = eglgsg;
00196 }
00197 }
00198
00199 if (eglgsg->_fbconfig == None) {
00200
00201
00202 return false;
00203 }
00204
00205 XVisualInfo *visual_info = eglgsg->_visual;
00206 if (visual_info == NULL) {
00207
00208 egldisplay_cat.error()
00209 << "No X visual: cannot create pixmap.\n";
00210 return false;
00211 }
00212
00213 _drawable = egl_pipe->get_root();
00214 if (_host != NULL) {
00215 if (_host->is_of_type(eglGraphicsWindow::get_class_type())) {
00216 eglGraphicsWindow *win = DCAST(eglGraphicsWindow, _host);
00217 _drawable = win->get_xwindow();
00218 } else if (_host->is_of_type(eglGraphicsPixmap::get_class_type())) {
00219 eglGraphicsPixmap *pix = DCAST(eglGraphicsPixmap, _host);
00220 _drawable = pix->_drawable;
00221 }
00222 }
00223
00224 _x_pixmap = XCreatePixmap(_display, _drawable,
00225 _x_size, _y_size, visual_info->depth);
00226 if (_x_pixmap == None) {
00227 egldisplay_cat.error()
00228 << "Failed to create X pixmap.\n";
00229 close_buffer();
00230 return false;
00231 }
00232
00233 nassertr(eglgsg->_fbconfig, false);
00234 _egl_surface = eglCreatePixmapSurface(_egl_display, eglgsg->_fbconfig, (NativePixmapType) _x_pixmap, NULL);
00235
00236 if (_egl_surface == EGL_NO_SURFACE) {
00237 egldisplay_cat.error()
00238 << "Failed to create EGL pixmap surface:"
00239 << get_egl_error_string(eglGetError()) << "\n";
00240 close_buffer();
00241 return false;
00242 }
00243
00244 eglMakeCurrent(_egl_display, _egl_surface, _egl_surface, eglgsg->_context);
00245 eglgsg->reset_if_new();
00246 if (!eglgsg->is_valid()) {
00247 close_buffer();
00248 return false;
00249 }
00250 if (!eglgsg->get_fb_properties().verify_hardware_software
00251 (_fb_properties, eglgsg->get_gl_renderer())) {
00252 close_buffer();
00253 return false;
00254 }
00255 _fb_properties = eglgsg->get_fb_properties();
00256
00257 _is_valid = true;
00258 return true;
00259 }