And here comes the working OpenGL ES backend
This commit is contained in:
parent
f5dbeb8fab
commit
5804417acc
5 changed files with 167 additions and 25 deletions
|
@ -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, ¤tProgram );
|
||||
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 );
|
||||
}
|
||||
|
||||
//*********************************
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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 )
|
||||
{
|
||||
|
|
|
@ -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()
|
||||
|
|
Loading…
Reference in a new issue