2 Copyright (C) 2009 Red Hat, Inc.
4 This library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Lesser General Public
6 License as published by the Free Software Foundation; either
7 version 2.1 of the License, or (at your option) any later version.
9 This library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 Lesser General Public License for more details.
14 You should have received a copy of the GNU Lesser General Public
15 License along with this library; if not, see <http://www.gnu.org/licenses/>.
25 #include "common/gl_utils.h"
28 #include "red_pixmap_gl.h"
31 #include "pixels_source_p.h"
32 #include "x_platform.h"
33 #include "red_window_p.h"
36 RedPixmapGL::RedPixmapGL(int width, int height, RedDrawable::Format format,
37 bool top_bottom, RedWindow *win,
38 RenderType rendertype)
39 : RedPixmap(width, height, format, top_bottom)
43 GLuint stencil_tex = 0;
45 //GLint max_texture_size;
47 ASSERT(format == RedDrawable::ARGB32 || format == RedDrawable::RGB32 || format == RedDrawable::A1);
48 ASSERT(sizeof(RedDrawable_p) <= PIXELES_SOURCE_OPAQUE_SIZE);
50 ((PixelsSource_p*)get_opaque())->type = PIXELS_SOURCE_TYPE_GL_TEXTURE;
52 _glcont = win->create_context_gl();
54 THROW("glXCreateContext failed");
57 win->set_gl_context(_glcont);
59 xwin = ((RedWindow_p*)win)->get_window();
61 /*glGetIntegerv(GL_MAX_TEXTURE_SIZE, &max_texture_size);
62 if (width > max_texture_size || height > max_texture_size) {
63 throw Exception(fmt("%s: unsuported max %|| width %|| height %||")
70 if (rendertype == RENDER_TYPE_FBO) {
71 glXMakeCurrent(XPlatform::get_display(), xwin, _glcont);
72 if (!gluCheckExtension((GLubyte *)"GL_EXT_framebuffer_object",
73 glGetString(GL_EXTENSIONS))) {
74 glXMakeCurrent(XPlatform::get_display(), 0, 0);
75 glXDestroyContext(XPlatform::get_display(), _glcont);
76 THROW("no GL_EXT_framebuffer_object extension");
78 glEnable(GL_TEXTURE_2D);
79 glGenFramebuffersEXT(1, &fbo);
80 glGenTextures(1, &tex);
81 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo);
83 glBindTexture(GL_TEXTURE_2D, tex);
85 glTexImage2D(GL_TEXTURE_2D, 0, 4, gl_get_to_power_two(width),
86 gl_get_to_power_two(height), 0, GL_BGRA, GL_UNSIGNED_BYTE,
89 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
90 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
92 glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
93 GL_TEXTURE_2D, tex, 0);
96 glGenTextures(1, &stencil_tex);
97 glBindTexture(GL_TEXTURE_2D, stencil_tex);
98 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
99 glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_STENCIL_EXT,
100 gl_get_to_power_two(width), gl_get_to_power_two(height), 0,
101 GL_DEPTH_STENCIL_EXT, GL_UNSIGNED_INT_24_8_EXT, NULL);
102 glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT,
103 GL_DEPTH_ATTACHMENT_EXT,
104 GL_TEXTURE_2D, stencil_tex, 0);
105 glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT,
106 GL_STENCIL_ATTACHMENT_EXT,
107 GL_TEXTURE_2D, stencil_tex, 0);
108 glBindTexture(GL_TEXTURE_2D, 0);
110 ((PixelsSource_p*)get_opaque())->gl.fbo = fbo;
111 win->set_render_fbo(fbo);
115 pbuff = win->create_pbuff(gl_get_to_power_two(width),
116 gl_get_to_power_two(height));
118 glXDestroyContext(XPlatform::get_display(), _glcont);
119 THROW("pbuff creation failed");
121 glXMakeCurrent(XPlatform::get_display(), pbuff, _glcont);
122 glEnable(GL_TEXTURE_2D);
123 glGenTextures(1, &tex);
124 glBindTexture(GL_TEXTURE_2D, tex);
126 glTexImage2D(GL_TEXTURE_2D, 0, 4, gl_get_to_power_two(width),
127 gl_get_to_power_two(height), 0, GL_BGRA, GL_UNSIGNED_BYTE,
130 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
131 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
133 glBindTexture(GL_TEXTURE_2D, 0);
134 ((PixelsSource_p*)get_opaque())->gl.pbuff = pbuff;
135 win->set_render_pbuff(pbuff);
138 ((PixelsSource_p*)get_opaque())->gl.stencil_tex = stencil_tex;
139 ((PixelsSource_p*)get_opaque())->gl.tex = tex;
140 ((PixelsSource_p*)get_opaque())->gl.width = width;
141 ((PixelsSource_p*)get_opaque())->gl.height = height;
142 ((PixelsSource_p*)get_opaque())->gl.width_powed = gl_get_to_power_two(width);
143 ((PixelsSource_p*)get_opaque())->gl.height_powed = gl_get_to_power_two(height);
144 ((PixelsSource_p*)get_opaque())->gl.win = xwin;
145 ((PixelsSource_p*)get_opaque())->gl.rendertype = rendertype;
146 ((PixelsSource_p*)get_opaque())->gl.context = _glcont;
148 _textures_lost = false;
150 GLC_ERROR_TEST_FINISH;
153 void RedPixmapGL::textures_lost()
155 _textures_lost = true;
158 void RedPixmapGL::touch_context()
162 RenderType rendertype;
164 rendertype = ((PixelsSource_p*)get_opaque())->gl.rendertype;
165 if (rendertype == RENDER_TYPE_FBO) {
166 win = ((PixelsSource_p*)get_opaque())->gl.win;
168 glXMakeCurrent(XPlatform::get_display(), win, _glcont);
171 pbuff = ((PixelsSource_p*)get_opaque())->gl.pbuff;
172 glXMakeCurrent(XPlatform::get_display(), pbuff, _glcont);
174 GLC_ERROR_TEST_FLUSH;
177 void RedPixmapGL::update_texture(const SpiceRect *bbox)
179 RenderType rendertype;
183 rendertype = ((PixelsSource_p*)get_opaque())->gl.rendertype;
185 if (rendertype == RENDER_TYPE_PBUFF) {
187 int vertex_x1, vertex_x2;
188 int vertex_y1, vertex_y2;
192 height = ((PixelsSource_p*)get_opaque())->gl.height;
194 tex = ((PixelsSource_p*)get_opaque())->gl.tex;
197 tex_y = height - bbox->bottom;
198 vertex_x1 = bbox->left;
199 vertex_y1 = height - bbox->bottom;
200 vertex_x2 = vertex_x1 + (bbox->right - bbox->left);
201 vertex_y2 = vertex_y1 + (bbox->bottom - bbox->top);
203 is_enabled = glIsEnabled(GL_TEXTURE_2D);
205 glEnable(GL_TEXTURE_2D);
207 glGetIntegerv(GL_TEXTURE_BINDING_2D, &prev_tex);
209 glBindTexture(GL_TEXTURE_2D, tex);
210 glCopyTexSubImage2D(GL_TEXTURE_2D, 0, tex_x, tex_y, vertex_x1,
211 vertex_y1, vertex_x2 - vertex_x1,
212 vertex_y2 - vertex_y1);
214 glBindTexture(GL_TEXTURE_2D, 0);
215 glDisable(GL_TEXTURE_2D);
217 glBindTexture(GL_TEXTURE_2D, prev_tex);
220 GLC_ERROR_TEST_FLUSH;
223 void RedPixmapGL::pre_copy()
227 glPushAttrib(GL_ENABLE_BIT | GL_COLOR_BUFFER_BIT | GL_TEXTURE_BIT |
230 glMatrixMode(GL_TEXTURE);
234 glMatrixMode(GL_PROJECTION);
237 gluOrtho2D(0, ((PixelsSource_p*)get_opaque())->gl.width, 0,
238 ((PixelsSource_p*)get_opaque())->gl.height);
240 glMatrixMode(GL_MODELVIEW);
243 glViewport(0, 0, ((PixelsSource_p*)get_opaque())->gl.width,
244 ((PixelsSource_p*)get_opaque())->gl.height);
247 glDisable(GL_TEXTURE_GEN_S);
248 glDisable(GL_TEXTURE_GEN_T);
250 glDisable(GL_ALPHA_TEST);
251 glDisable(GL_COLOR_LOGIC_OP);
256 void RedPixmapGL::past_copy()
258 glMatrixMode(GL_MODELVIEW);
260 glMatrixMode(GL_PROJECTION);
262 glMatrixMode(GL_TEXTURE);
269 RedPixmapGL::~RedPixmapGL()
273 RenderType rendertype;
278 * GL textures might be destroyed by res change.
280 if (!_textures_lost) {
281 tex = ((PixelsSource_p*)get_opaque())->gl.tex;
282 stencil_tex = ((PixelsSource_p*)get_opaque())->gl.stencil_tex;
284 glDeleteTextures(1, &tex);
287 glDeleteTextures(1, &stencil_tex);
290 glXDestroyContext(XPlatform::get_display(), _glcont);
294 rendertype = ((PixelsSource_p*)get_opaque())->gl.rendertype;
295 if (rendertype == RENDER_TYPE_FBO) {
296 fbo = ((PixelsSource_p*)get_opaque())->gl.fbo;
298 glDeleteFramebuffersEXT(1, &fbo);
301 pbuff = ((PixelsSource_p*)get_opaque())->gl.pbuff;
302 glXDestroyPbuffer(XPlatform::get_display(), pbuff);
306 * Both tex and stenctil_tex are textures and therefore they are destroyed
307 * when the context is gone, so we dont free them here as they might have
308 * already been destroyed.
310 GLC_ERROR_TEST_FINISH;