1 /***************************************************************************
3 * Copyright 2010,2011 BMW Car IT GmbH
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
10 * http://www.apache.org/licenses/LICENSE-2.0
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
18 ****************************************************************************/
20 #include "GraphicSystems/GLXGraphicsystem.h"
22 #include "TextureBinders/X11CopyGLX.h"
23 #include "TextureBinders/X11TextureFromPixmap.h"
24 #include "Transformation/ViewportTransform.h"
28 GLXGraphicsystem::GLXGraphicsystem(int WindowWidth, int WindowHeight)
29 : m_windowWidth(WindowWidth)
30 , m_windowHeight(WindowHeight)
38 LOG_DEBUG("GLXGraphicsystem", "creating GLXGraphicsystem");
41 GLXGraphicsystem::~GLXGraphicsystem()
49 XVisualInfo* GLXGraphicsystem::GetMatchingVisual(Display *dpy)
51 int screen = DefaultScreen(dpy);
65 visinfo = glXChooseVisual(dpy, screen, attribs);
68 LOG_ERROR("GLXGraphicsystem", "Unable to find RGB, double-buffered visual");
72 bool GLXGraphicsystem::CheckConfigMask(Display *curDisplay,GLXFBConfig currentConfig, int attribute, int expectedValue)
75 int returnedValue = 0;
77 glXGetFBConfigAttrib(curDisplay,currentConfig,attribute,&returnedValue);
78 if (!(returnedValue & expectedValue))
85 bool GLXGraphicsystem::CheckConfigValue(Display *curDisplay,GLXFBConfig currentConfig, int attribute, int expectedValue)
88 int returnedValue = 0;
90 glXGetFBConfigAttrib(curDisplay,currentConfig,attribute,&returnedValue);
91 if ((returnedValue != expectedValue))
98 void GLXGraphicsystem::activateGraphicContext()
100 glXMakeCurrent(m_x11display, m_window, m_context);
103 void GLXGraphicsystem::releaseGraphicContext()
105 glXMakeCurrent(m_x11display, None, NULL);
108 GLXFBConfig* GLXGraphicsystem::GetMatchingPixmapConfig(Display *curDisplay)
110 int neededMaskAttribute[] =
112 GLX_DRAWABLE_TYPE,GLX_PIXMAP_BIT,
113 GLX_DRAWABLE_TYPE,GLX_WINDOW_BIT,
114 GLX_BIND_TO_TEXTURE_TARGETS_EXT,GLX_TEXTURE_2D_BIT_EXT,
117 int neededValueAttribute[] =
121 GLX_BIND_TO_TEXTURE_RGBA_EXT,True,
124 LOG_DEBUG("GLXGraphicsystem", "Choose pixmap GL configuration");
125 int screen = DefaultScreen(curDisplay);
126 GLXFBConfig *currentFBconfigs;
131 currentFBconfigs = glXGetFBConfigs(curDisplay, screen, &nConfigs);
132 for (i = 0; i < nConfigs; i++)
134 GLXFBConfig config = currentFBconfigs[i];
136 /* check first all mask values */
138 while ( neededMaskAttribute[j] != None && result == true )
140 result = CheckConfigMask(curDisplay,config, neededMaskAttribute[j], neededMaskAttribute[j+1]);
143 /* no matching found in needed mask attribute, skip config take next */
144 if (result == false )
148 /* check all fixed values */
150 /* reset attribute counter */
152 /* check all fixed values */
153 while ( neededValueAttribute[j] != None && result == true )
155 result = CheckConfigValue(curDisplay,config, neededValueAttribute[j], neededValueAttribute[j+1]);
158 /* no matching found in needed fixed value attribute, skip config take next */
160 if (result == false )
169 LOG_ERROR("GLXGraphicsystem", "Unable to find FBconfig for texturing");
173 LOG_DEBUG("GLXGraphicsystem", "Done choosing GL Pixmap configuration");
174 return ¤tFBconfigs[i];
177 bool GLXGraphicsystem::init(Display* x11Display, Window x11Window)
179 LOG_DEBUG("GLXGraphicsystem", "init");
180 m_x11display = x11Display;
181 m_window = x11Window;
185 LOG_ERROR("GLXGraphicsystem", "given display is null");
191 LOG_ERROR("GLXGraphicsystem", "given windowid is 0");
195 XVisualInfo* windowVis = GetMatchingVisual(m_x11display);
197 LOG_DEBUG("GLXGraphicsystem", "Initialising opengl");
198 m_context = glXCreateContext(m_x11display, windowVis, 0, GL_TRUE);
201 LOG_ERROR("GLXGraphicsystem", "Couldn't create GLX context!");
204 LOG_DEBUG("GLXGraphicsystem", "Make GLX Context current");
205 glXMakeCurrent(m_x11display, m_window, m_context);
207 glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
208 glClearColor(0.0, 0.0, 0.0, 1.0);
209 glEnable(GL_TEXTURE_2D);
210 glMatrixMode(GL_MODELVIEW);
212 ext = glXQueryExtensionsString(m_x11display, 0);
213 if (!strstr(ext, "GLX_EXT_texture_from_pixmap") )
222 LOG_DEBUG("GLXGraphicsystem", "Initialised");
227 void GLXGraphicsystem::clearBackground()
229 glClear(GL_COLOR_BUFFER_BIT);
232 void GLXGraphicsystem::swapBuffers()
234 glXSwapBuffers(m_x11display, m_window);
237 void GLXGraphicsystem::beginLayer(Layer* currentLayer)
239 m_currentLayer = currentLayer;
241 /* Load Identity Matrix for each Layer */
244 /* set layer Transformations */
245 /* const Rectangle& layerDestination = m_currentLayer->getDestinationRegion(); */
246 // TODO: unused? const Rectangle& layerSource = m_currentLayer->getSourceRegion();
248 /* glTranslatef(layerDestination.x, layerDestination.y, 0.0); */
251 void GLXGraphicsystem::checkRenderLayer()
253 SurfaceList surfaces = m_currentLayer->getAllSurfaces();
255 m_currentLayer->damaged = false;
257 if (!m_baseWindowSystem->m_forceComposition && (!m_baseWindowSystem->m_damaged || m_currentLayer->getLayerType() == Hardware))
259 if (m_currentLayer->renderPropertyChanged)
261 m_currentLayer->damaged = true;
263 else if ((m_currentLayer)->visibility && (m_currentLayer)->opacity > 0.0)
265 for(std::list<Surface*>::const_iterator currentS = surfaces.begin(); currentS != surfaces.end(); currentS++)
267 if ((*currentS)->renderPropertyChanged)
269 m_currentLayer->damaged = true;
272 else if ((*currentS)->hasNativeContent() && (*currentS)->damaged && (*currentS)->visibility && (*currentS)->opacity>0.0f)
274 m_currentLayer->damaged = true;
280 // Preseve m_currentLayer->damaged for HW layers so that they can be updated independently
281 if (m_currentLayer->damaged && m_currentLayer->getLayerType() != Hardware)
283 m_baseWindowSystem->m_damaged = true;
284 m_currentLayer->damaged = false;
288 for(std::list<Surface*>::const_iterator currentS = surfaces.begin(); currentS != surfaces.end(); currentS++)
290 (*currentS)->damaged = false;
291 (*currentS)->renderPropertyChanged = false;
294 m_currentLayer->renderPropertyChanged = false;
297 void GLXGraphicsystem::renderSWLayer()
299 if ( (m_currentLayer)->visibility && (m_currentLayer)->opacity > 0.0 )
301 SurfaceList surfaces = m_currentLayer->getAllSurfaces();
302 for(std::list<Surface*>::const_iterator currentS = surfaces.begin(); currentS != surfaces.end(); currentS++)
304 if ((*currentS)->hasNativeContent() && (*currentS)->visibility && (*currentS)->opacity>0.0f)
306 Surface* currentSurface = (Surface*)*currentS;
307 renderSurface(currentSurface);
313 void GLXGraphicsystem::endLayer()
315 m_currentLayer = NULL;
318 void GLXGraphicsystem::renderSurface(Surface* currentSurface)
320 // LOG_DEBUG("GLXGraphicsystem", "renderSurface " << currentSurface->getID() );
321 GLenum glErrorCode = GL_NO_ERROR;
323 // check if surface is cropped completely, if so then skip rendering
324 if (ViewportTransform::isFullyCropped(currentSurface->getDestinationRegion(), m_currentLayer->getSourceRegion() ) )
325 return; // skip rendering of this surface, because it is cropped by layer source region
327 const FloatRectangle layerSourceRegion = m_currentLayer->getSourceRegion();
328 const FloatRectangle layerDestinationRegion = m_currentLayer->getDestinationRegion();
330 FloatRectangle targetSurfaceSource = currentSurface->getSourceRegion();
331 FloatRectangle targetSurfaceDestination = currentSurface->getDestinationRegion();
333 ViewportTransform::applyLayerSource(layerSourceRegion, targetSurfaceSource, targetSurfaceDestination);
334 ViewportTransform::applyLayerDestination(layerDestinationRegion, layerSourceRegion, targetSurfaceDestination);
335 float textureCoordinates[4];
336 ViewportTransform::transformRectangleToTextureCoordinates(targetSurfaceSource, currentSurface->OriginalSourceWidth, currentSurface->OriginalSourceHeight, textureCoordinates);
339 if (false == m_binder->bindSurfaceTexture(currentSurface))
341 /* skip render surface if not bind successfully */
345 glColor4f(1.0f,1.0f,1.0f,currentSurface->opacity*(m_currentLayer)->opacity);
349 // LOG_DEBUG("GLXGraphicsystem","rendersurface: src" << src.x << " " << src.y << " " << src.width << " " << src.height );
350 // LOG_DEBUG("GLXGraphicsystem","rendersurface: dest" << dest.x << " " << dest.y << " " << dest.width << " " << dest.height );
351 // LOG_DEBUG("GLXGraphicsystem","orig: " << currentSurface->OriginalSourceWidth << " " << currentSurface->OriginalSourceHeight );
352 // LOG_DEBUG("GLXGraphicsystem","window: " << m_windowWidth << " " << m_windowHeight );
355 glTexCoord2d(textureCoordinates[0],textureCoordinates[3]);
356 glVertex2d((float)targetSurfaceDestination.x/m_windowWidth*2-1, 1-(float)(targetSurfaceDestination.y+targetSurfaceDestination.height)/m_windowHeight*2);
359 glTexCoord2f(textureCoordinates[2],textureCoordinates[3]);
360 glVertex2d( (float)(targetSurfaceDestination.x+targetSurfaceDestination.width)/m_windowWidth*2-1, 1-(float)(targetSurfaceDestination.y+targetSurfaceDestination.height)/m_windowHeight*2);
363 glTexCoord2f(textureCoordinates[2], textureCoordinates[1]);
364 glVertex2d((float)(targetSurfaceDestination.x+targetSurfaceDestination.width)/m_windowWidth*2-1, 1-(float)targetSurfaceDestination.y/m_windowHeight*2);
367 glTexCoord2f(textureCoordinates[0], textureCoordinates[1]);
368 glVertex2d((float)targetSurfaceDestination.x/m_windowWidth*2-1 , 1-(float)targetSurfaceDestination.y/m_windowHeight*2);
371 m_binder->unbindSurfaceTexture(currentSurface);
373 glErrorCode = glGetError();
374 if ( GL_NO_ERROR != glErrorCode )
376 LOG_ERROR("GLXGraphicsystem", "GL Error occured :" << glErrorCode );
378 currentSurface->frameCounter++;
379 currentSurface->drawCounter++;
382 void GLXGraphicsystem::saveScreenShotOfFramebuffer(std::string fileToSave)
384 LOG_DEBUG("GLXGraphicsystem","taking screenshot and saving it to:" << fileToSave);
387 glGetIntegerv(GL_VIEWPORT,viewport); // x,y,width,height
389 int WINDOW_WIDTH= viewport[2];
390 int WINDOW_HEIGHT= viewport[3];
391 LOG_DEBUG("GLXGraphicsystem","Screenshot: " << WINDOW_WIDTH << " * " << WINDOW_HEIGHT);
392 char *buffer = (char *)malloc(WINDOW_WIDTH * WINDOW_HEIGHT * 3 * sizeof(unsigned char));
393 glReadPixels(0,0,WINDOW_WIDTH,WINDOW_HEIGHT,GL_BGR,GL_UNSIGNED_BYTE, buffer);
395 writeBitmap(fileToSave,buffer,WINDOW_WIDTH,WINDOW_HEIGHT);
397 LOG_DEBUG("GLXGraphicsystem","done taking screenshot");