And here comes the working OpenGL ES backend

This commit is contained in:
Martin Gräßlin 2010-11-28 16:21:12 +01:00 committed by Martin Gräßlin
parent f5dbeb8fab
commit 5804417acc
5 changed files with 167 additions and 25 deletions

View file

@ -438,7 +438,25 @@ bool GLTexture::load( const QPixmap& pixmap, GLenum target )
{
if( pixmap.isNull())
return false;
#ifdef KWIN_HAVE_OPENGLES
if( isNull() )
glGenTextures( 1, &mTexture );
mTarget = target;
bind();
const EGLint attribs[] = {
EGL_IMAGE_PRESERVED_KHR, EGL_TRUE,
EGL_NONE
};
EGLDisplay dpy = eglGetCurrentDisplay();
EGLImageKHR image = eglCreateImageKHR(dpy, EGL_NO_CONTEXT, EGL_NATIVE_PIXMAP_KHR,
(EGLClientBuffer)pixmap.handle(), attribs);
glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, (GLeglImageOES)image);
eglDestroyImageKHR(dpy, image);
unbind();
return true;
#else
return load( pixmap.toImage(), target );
#endif
}
bool GLTexture::load( const QString& fileName )
@ -1020,6 +1038,7 @@ float GLShader::textureWidth()
void GLShader::bindAttributeLocation(int index, const char* name)
{
glBindAttribLocation(mProgram, index, name);
// TODO: relink the shader
}
/*** GLRenderTarget ***/
@ -1247,26 +1266,32 @@ void GLVertexBufferPrivate::corePainting( const QRegion& region, GLenum primitiv
glEnableVertexAttribArray( 0 );
glEnableVertexAttribArray( 1 );
// TODO: have this information available somewhere useable
GLint currentProgram;
glGetIntegerv( GL_CURRENT_PROGRAM, &currentProgram );
GLint vertexAttrib = glGetAttribLocation( currentProgram, "vertex" );
GLint texAttrib = glGetAttribLocation( currentProgram, "texCoord" );
glBindBuffer( GL_ARRAY_BUFFER, buffers[ 0 ] );
glVertexAttribPointer( 0, dimension, GL_FLOAT, GL_FALSE, 0, 0 );
glVertexAttribPointer( vertexAttrib, dimension, GL_FLOAT, GL_FALSE, 0, 0 );
glBindBuffer( GL_ARRAY_BUFFER, buffers[ 1 ] );
glVertexAttribPointer( 1, 2, GL_FLOAT, GL_FALSE, 0, 0 );
glVertexAttribPointer( texAttrib, 2, GL_FLOAT, GL_FALSE, 0, 0 );
// TODO: reenable paint clipper
// Clip using scissoring
PaintClipper pc( region );
/*PaintClipper pc( region );
for( PaintClipper::Iterator iterator;
!iterator.isDone();
iterator.next())
{
{*/
glDrawArrays( primitiveMode, 0, numberVertices );
}
//}
glBindBuffer( GL_ARRAY_BUFFER, 0 );
glDisableVertexAttribArray( 1 );
glDisableVertexAttribArray( 2 );
glDisableVertexAttribArray( 0 );
}
//*********************************

View file

@ -1,3 +1,6 @@
#ifdef GL_ES
precision highp float;
#endif
uniform sampler2D sample;
uniform float textureWidth;
uniform float textureHeight;
@ -6,9 +9,9 @@ uniform float brightness;
uniform float saturation;
uniform int debug;
varying in vec2 varyingTexCoords;
varying vec2 varyingTexCoords;
varying out vec4 color;
//varying vec4 color;
// Converts pixel coordinates to texture coordinates
vec2 pix2tex( vec2 pix )
@ -25,9 +28,9 @@ void main() {
}
tex.rgb = tex.rgb * opacity * brightness;
tex.a = tex.a * opacity;
if (debug != 0) {
/*if (debug != 0) {
tex.g += 0.5;
}
}*/
color = tex;
gl_FragColor = tex;
}

View file

@ -1,17 +1,20 @@
#ifdef GL_ES
precision highp float;
#endif
// size of the complete display in pixels, x==width, y==height
uniform vec2 displaySize;
// geometry of the window/texture to be rendered: x, y, width, height in display geometry
uniform vec4 geometry;
// passed in vertex - only x and y are used
in vec4 vertex;
attribute vec4 vertex;
// passed in texCoords - to be forwarded
in vec2 texCoord;
attribute vec2 texCoord;
// texCoords passed to fragment shader
varying out vec2 varyingTexCoords;
varying vec2 varyingTexCoords;
void main() {
varyingTexCoords = texCoord;
gl_Position.xy = 2*vec2(geometry.x + vertex.x, displaySize.y - vertex.y - geometry.y)/displaySize - vertex.ww;
gl_Position.xy = 2.0*vec2(geometry.x + vertex.x, displaySize.y - vertex.y - geometry.y)/displaySize - vertex.ww;
}

View file

@ -368,12 +368,14 @@ SceneOpenGL::Window::~Window()
// Bind the window pixmap to an OpenGL texture.
bool SceneOpenGL::Window::bindTexture()
{
#ifndef KWIN_HAVE_OPENGLES
if( texture.texture() != None && toplevel->damage().isEmpty())
{
// texture doesn't need updating, just bind it
glBindTexture( texture.target(), texture.texture());
return true;
}
#endif
// Get the pixmap with the window contents
Pixmap pix = toplevel->windowPixmap();
if( pix == None )
@ -1113,7 +1115,6 @@ void SceneOpenGL::EffectFrame::render( QRegion region, double opacity, double fr
{
shader = static_cast<SceneOpenGL*>(scene)->m_sceneShader;
sceneShader = true;
kDebug(1212) << "using scene shader";
}
if( shader )
{
@ -1274,7 +1275,6 @@ void SceneOpenGL::EffectFrame::render( QRegion region, double opacity, double fr
}
#endif
m_unstyledTexture->unbind();
checkGLError("unstyled texture");
}
else if( m_effectFrame->style() == EffectFrameStyled )
{

View file

@ -19,6 +19,13 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
*********************************************************************/
// This file is included in scene_opengl.cpp
//#include "scene_opengl.h"
#include <QX11Info>
EGLDisplay dpy;
EGLConfig config;
EGLSurface surface;
EGLContext ctx;
SceneOpenGL::SceneOpenGL( Workspace* ws )
: Scene( ws )
@ -26,8 +33,10 @@ SceneOpenGL::SceneOpenGL( Workspace* ws )
, selfCheckDone( true )
, m_sceneShader( NULL )
{
// TODO: EGL
if( !initRenderingContext() )
return;
initGL();
debug = qstrcmp( qgetenv( "KWIN_GL_DEBUG" ), "1" ) == 0;
m_sceneShader = new GLShader( ":/resources/scene-vertex.glsl", ":/resources/scene-fragment.glsl" );
@ -37,8 +46,6 @@ SceneOpenGL::SceneOpenGL( Workspace* ws )
m_sceneShader->setUniform( "sample", 0 );
m_sceneShader->setUniform( "displaySize", QVector2D(displayWidth(), displayHeight()));
m_sceneShader->setUniform( "debug", debug ? 1 : 0 );
m_sceneShader->bindAttributeLocation( 0, "vertex" );
m_sceneShader->bindAttributeLocation( 1, "texCoord" );
m_sceneShader->unbind();
kDebug(1212) << "Scene Shader is valid";
}
@ -62,6 +69,12 @@ SceneOpenGL::~SceneOpenGL()
{
foreach( Window* w, windows )
delete w;
// do cleanup after initBuffer()
eglMakeCurrent( dpy, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT );
eglDestroyContext( dpy, ctx );
eglDestroySurface( dpy, surface );
eglTerminate( dpy );
eglReleaseThread();
delete m_sceneShader;
SceneOpenGL::EffectFrame::cleanup();
checkGLError( "Cleanup" );
@ -74,7 +87,39 @@ bool SceneOpenGL::initTfp()
bool SceneOpenGL::initRenderingContext()
{
return false;
dpy = eglGetDisplay( display() );
if( dpy == EGL_NO_DISPLAY )
return false;
EGLint major, minor;
if( eglInitialize( dpy, &major, &minor ) == EGL_FALSE )
return false;
eglBindAPI( EGL_OPENGL_ES_API );
initBufferConfigs();
if( !wspace->createOverlay() )
{
kError( 1212 ) << "Could not get overlay window";
return false;
}
surface = eglCreateWindowSurface( dpy, config, wspace->overlayWindow(), 0 );
const EGLint context_attribs[] = {
EGL_CONTEXT_CLIENT_VERSION, 2,
EGL_NONE
};
ctx = eglCreateContext( dpy, config, EGL_NO_CONTEXT, context_attribs );
if( ctx == EGL_NO_CONTEXT )
return false;
if( eglMakeCurrent( dpy, surface, surface, ctx ) == EGL_FALSE )
return false;
kDebug( 1212 ) << "EGL version: " << major << "." << minor;
EGLint error = eglGetError();
if( error != EGL_SUCCESS )
{
kWarning( 1212 ) << "Error occurred while creating context " << error;
return false;
}
return true;
}
bool SceneOpenGL::initBuffer()
@ -84,7 +129,35 @@ bool SceneOpenGL::initBuffer()
bool SceneOpenGL::initBufferConfigs()
{
return false;
const EGLint config_attribs[] = {
EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
EGL_RED_SIZE, 1,
EGL_GREEN_SIZE, 1,
EGL_BLUE_SIZE, 1,
EGL_ALPHA_SIZE, 0,
EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
EGL_CONFIG_CAVEAT, EGL_NONE,
EGL_NONE,
};
EGLint count;
EGLConfig configs[1024];
eglChooseConfig(dpy, config_attribs, configs, 1024, &count);
EGLint visualId = XVisualIDFromVisual((Visual*)QX11Info::appVisual());
config = configs[0];
for (int i = 0; i < count; i++)
{
EGLint val;
eglGetConfigAttrib(dpy, configs[i], EGL_NATIVE_VISUAL_ID, &val);
if (visualId == val)
{
config = configs[i];
break;
}
}
return true;
}
bool SceneOpenGL::initDrawableConfigs()
@ -112,8 +185,12 @@ void SceneOpenGL::paint( QRegion damage, ToplevelList toplevels )
assert( windows.contains( c ));
stacking_order.append( windows[ c ] );
}
grabXServer();
int mask = 0;
paintScreen( &mask, &damage ); // call generic implementation
ungrabXServer(); // ungrab before flushBuffer(), it may wait for vsync
if( wspace->overlayWindow()) // show the window only after the first pass, since
wspace->showOverlay(); // that pass may take long
lastRenderTime = t.elapsed();
flushBuffer( mask, damage );
// do cleanup
@ -128,7 +205,19 @@ void SceneOpenGL::waitSync()
void SceneOpenGL::flushBuffer( int mask, QRegion damage )
{
// TODO: implement me
glFlush();
if( mask & PAINT_SCREEN_REGION )
{
// TODO: implement me properly
eglSwapBuffers( dpy, surface );
}
else
{
eglSwapBuffers( dpy, surface );
}
eglWaitGL();
// TODO: remove for wayland
XFlush( display());
}
void SceneOpenGL::paintGenericScreen( int mask, ScreenPaintData data )
@ -140,6 +229,8 @@ void SceneOpenGL::paintGenericScreen( int mask, ScreenPaintData data )
void SceneOpenGL::paintBackground( QRegion region )
{
// TODO: implement me
glClearColor(0, 0, 0, 1);
glClear(GL_COLOR_BUFFER_BIT);
}
//****************************************
@ -149,10 +240,12 @@ void SceneOpenGL::paintBackground( QRegion region )
void SceneOpenGL::Texture::init()
{
damaged = true;
findTarget();
}
void SceneOpenGL::Texture::release()
{
mTexture = None;
}
void SceneOpenGL::Texture::findTarget()
@ -163,8 +256,26 @@ void SceneOpenGL::Texture::findTarget()
bool SceneOpenGL::Texture::load( const Pixmap& pix, const QSize& size,
int depth, QRegion region )
{
// TODO: implement proper
return GLTexture::load(QPixmap::fromX11Pixmap(pix));
if( mTexture == None )
{
createTexture();
bind();
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
const EGLint attribs[] = {
EGL_IMAGE_PRESERVED_KHR, EGL_TRUE,
EGL_NONE
};
EGLImageKHR image = eglCreateImageKHR(dpy, EGL_NO_CONTEXT, EGL_NATIVE_PIXMAP_KHR,
(EGLClientBuffer)pix, attribs);
glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, (GLeglImageOES)image);
eglDestroyImageKHR( dpy, image );
unbind();
checkGLError("load texture");
}
return true;
}
void SceneOpenGL::Texture::bind()