@ -163,7 +163,7 @@ glx_on_root_change(session_t *ps) {
// Initialize matrix, copied from dcompmgr
// Initialize matrix, copied from dcompmgr
glMatrixMode ( GL_PROJECTION ) ;
glMatrixMode ( GL_PROJECTION ) ;
glLoadIdentity ( ) ;
glLoadIdentity ( ) ;
glOrtho ( 0 , ps - > root_width , ps - > root_height , 0 , - 1 00.0, 1 00.0) ;
glOrtho ( 0 , ps - > root_width , 0 , ps - > root_height , - 1 0 00.0, 1 0 00.0) ;
glMatrixMode ( GL_MODELVIEW ) ;
glMatrixMode ( GL_MODELVIEW ) ;
glLoadIdentity ( ) ;
glLoadIdentity ( ) ;
}
}
@ -328,7 +328,6 @@ glx_bind_pixmap(session_t *ps, glx_texture_t **pptex, Pixmap pixmap,
return false ;
return false ;
}
}
const GLenum target = GL_TEXTURE_2D ;
glx_texture_t * ptex = * pptex ;
glx_texture_t * ptex = * pptex ;
bool need_release = true ;
bool need_release = true ;
@ -338,6 +337,7 @@ glx_bind_pixmap(session_t *ps, glx_texture_t **pptex, Pixmap pixmap,
. texture = 0 ,
. texture = 0 ,
. glpixmap = 0 ,
. glpixmap = 0 ,
. pixmap = 0 ,
. pixmap = 0 ,
. target = 0 ,
. width = 0 ,
. width = 0 ,
. height = 0 ,
. height = 0 ,
. depth = 0 ,
. depth = 0 ,
@ -350,37 +350,11 @@ glx_bind_pixmap(session_t *ps, glx_texture_t **pptex, Pixmap pixmap,
* pptex = ptex ;
* pptex = ptex ;
}
}
glEnable ( target ) ;
// Release pixmap if parameters are inconsistent
// Release pixmap if parameters are inconsistent
if ( ptex - > texture & & ptex - > pixmap ! = pixmap ) {
if ( ptex - > texture & & ptex - > pixmap ! = pixmap ) {
glx_release_pixmap ( ps , ptex ) ;
glx_release_pixmap ( ps , ptex ) ;
}
}
// Create texture
if ( ! ptex - > texture ) {
need_release = false ;
GLuint texture = 0 ;
glGenTextures ( 1 , & texture ) ;
glBindTexture ( target , texture ) ;
glTexParameteri ( target , GL_TEXTURE_MIN_FILTER , GL_NEAREST ) ;
glTexParameteri ( target , GL_TEXTURE_MAG_FILTER , GL_NEAREST ) ;
glTexParameteri ( target , GL_TEXTURE_WRAP_S , GL_CLAMP_TO_EDGE ) ;
glTexParameteri ( target , GL_TEXTURE_WRAP_T , GL_CLAMP_TO_EDGE ) ;
glBindTexture ( target , 0 ) ;
ptex - > texture = texture ;
}
if ( ! ptex - > texture ) {
printf_errf ( " (): Failed to allocate texture. " ) ;
return false ;
}
glBindTexture ( target , ptex - > texture ) ;
// Create GLX pixmap
// Create GLX pixmap
if ( ! ptex - > glpixmap ) {
if ( ! ptex - > glpixmap ) {
need_release = false ;
need_release = false ;
@ -409,7 +383,9 @@ glx_bind_pixmap(session_t *ps, glx_texture_t **pptex, Pixmap pixmap,
}
}
// Determine texture target, copied from compiz
// Determine texture target, copied from compiz
GLint tex_tgt = 0 ;
// The assumption we made here is the target never changes based on any
// pixmap-specific parameters, and this may change in the future
GLenum tex_tgt = 0 ;
if ( GLX_TEXTURE_2D_BIT_EXT & pcfg - > texture_tgts
if ( GLX_TEXTURE_2D_BIT_EXT & pcfg - > texture_tgts
& & ps - > glx_has_texture_non_power_of_two )
& & ps - > glx_has_texture_non_power_of_two )
tex_tgt = GLX_TEXTURE_2D_EXT ;
tex_tgt = GLX_TEXTURE_2D_EXT ;
@ -435,6 +411,8 @@ glx_bind_pixmap(session_t *ps, glx_texture_t **pptex, Pixmap pixmap,
ptex - > glpixmap = glXCreatePixmap ( ps - > dpy , pcfg - > cfg , pixmap , attrs ) ;
ptex - > glpixmap = glXCreatePixmap ( ps - > dpy , pcfg - > cfg , pixmap , attrs ) ;
ptex - > pixmap = pixmap ;
ptex - > pixmap = pixmap ;
ptex - > target = ( GLX_TEXTURE_2D_EXT = = tex_tgt ? GL_TEXTURE_2D :
GL_TEXTURE_RECTANGLE ) ;
ptex - > width = width ;
ptex - > width = width ;
ptex - > height = height ;
ptex - > height = height ;
ptex - > depth = depth ;
ptex - > depth = depth ;
@ -445,6 +423,32 @@ glx_bind_pixmap(session_t *ps, glx_texture_t **pptex, Pixmap pixmap,
return false ;
return false ;
}
}
glEnable ( ptex - > target ) ;
// Create texture
if ( ! ptex - > texture ) {
need_release = false ;
GLuint texture = 0 ;
glGenTextures ( 1 , & texture ) ;
glBindTexture ( ptex - > target , texture ) ;
glTexParameteri ( ptex - > target , GL_TEXTURE_MIN_FILTER , GL_NEAREST ) ;
glTexParameteri ( ptex - > target , GL_TEXTURE_MAG_FILTER , GL_NEAREST ) ;
glTexParameteri ( ptex - > target , GL_TEXTURE_WRAP_S , GL_CLAMP_TO_EDGE ) ;
glTexParameteri ( ptex - > target , GL_TEXTURE_WRAP_T , GL_CLAMP_TO_EDGE ) ;
glBindTexture ( ptex - > target , 0 ) ;
ptex - > texture = texture ;
}
if ( ! ptex - > texture ) {
printf_errf ( " (): Failed to allocate texture. " ) ;
return false ;
}
glBindTexture ( ptex - > target , ptex - > texture ) ;
// The specification requires rebinding whenever the content changes...
// The specification requires rebinding whenever the content changes...
// We can't follow this, too slow.
// We can't follow this, too slow.
if ( need_release )
if ( need_release )
@ -453,8 +457,8 @@ glx_bind_pixmap(session_t *ps, glx_texture_t **pptex, Pixmap pixmap,
ps - > glXBindTexImageProc ( ps - > dpy , ptex - > glpixmap , GLX_FRONT_LEFT_EXT , NULL ) ;
ps - > glXBindTexImageProc ( ps - > dpy , ptex - > glpixmap , GLX_FRONT_LEFT_EXT , NULL ) ;
// Cleanup
// Cleanup
glBindTexture ( target, 0 ) ;
glBindTexture ( ptex- > target, 0 ) ;
glDisable ( target) ;
glDisable ( ptex- > target) ;
return true ;
return true ;
}
}
@ -466,9 +470,9 @@ void
glx_release_pixmap ( session_t * ps , glx_texture_t * ptex ) {
glx_release_pixmap ( session_t * ps , glx_texture_t * ptex ) {
// Release binding
// Release binding
if ( ptex - > glpixmap & & ptex - > texture ) {
if ( ptex - > glpixmap & & ptex - > texture ) {
glBindTexture ( GL_TEXTURE_2D , ptex - > texture ) ;
glBindTexture ( ptex- > target , ptex - > texture ) ;
ps - > glXReleaseTexImageProc ( ps - > dpy , ptex - > glpixmap , GLX_FRONT_LEFT_EXT ) ;
ps - > glXReleaseTexImageProc ( ps - > dpy , ptex - > glpixmap , GLX_FRONT_LEFT_EXT ) ;
glBindTexture ( GL_TEXTURE_2D , 0 ) ;
glBindTexture ( ptex- > target , 0 ) ;
}
}
// Free GLX Pixmap
// Free GLX Pixmap
@ -478,6 +482,41 @@ glx_release_pixmap(session_t *ps, glx_texture_t *ptex) {
}
}
}
}
/**
* Preprocess function before start painting .
*/
void
glx_paint_pre ( session_t * ps , XserverRegion * preg ) {
ps - > glx_z = 0.0 ;
// glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// OpenGL doesn't support partial repaint without GLX_MESA_copy_sub_buffer,
// we currently redraw the whole screen or copy unmodified pixels from
// front buffer with --glx-copy-from-front.
if ( ! ps - > o . glx_copy_from_front | | ! * preg ) {
free_region ( ps , preg ) ;
}
else {
{
XserverRegion reg_copy = XFixesCreateRegion ( ps - > dpy , NULL , 0 ) ;
XFixesSubtractRegion ( ps - > dpy , reg_copy , ps - > screen_reg , * preg ) ;
glx_set_clip ( ps , reg_copy ) ;
free_region ( ps , & reg_copy ) ;
}
{
GLfloat raster_pos [ 4 ] ;
glGetFloatv ( GL_CURRENT_RASTER_POSITION , raster_pos ) ;
glReadBuffer ( GL_FRONT ) ;
glRasterPos2f ( 0.0 , 0.0 ) ;
glCopyPixels ( 0 , 0 , ps - > root_width , ps - > root_height , GL_COLOR ) ;
glReadBuffer ( GL_BACK ) ;
glRasterPos4fv ( raster_pos ) ;
}
}
glx_set_clip ( ps , * preg ) ;
}
/**
/**
* Set clipping region on the target window .
* Set clipping region on the target window .
*/
*/
@ -524,9 +563,9 @@ glx_set_clip(session_t *ps, XserverRegion reg) {
for ( int i = 0 ; i < nrects ; + + i ) {
for ( int i = 0 ; i < nrects ; + + i ) {
GLint rx = rects [ i ] . x ;
GLint rx = rects [ i ] . x ;
GLint ry = rects[ i ] . y ;
GLint ry = ps- > root_height - rects[ i ] . y ;
GLint rxe = rx + rects [ i ] . width ;
GLint rxe = rx + rects [ i ] . width ;
GLint rye = ry + rects [ i ] . height ;
GLint rye = ry - rects [ i ] . height ;
GLint z = 0 ;
GLint z = 0 ;
# ifdef DEBUG_GLX
# ifdef DEBUG_GLX
@ -550,6 +589,78 @@ glx_set_clip(session_t *ps, XserverRegion reg) {
XFree ( rects ) ;
XFree ( rects ) ;
}
}
bool
glx_blur_dst ( session_t * ps , int dx , int dy , int width , int height , float z ) {
// Read destination pixels into a texture
GLuint tex_scr = 0 ;
glGenTextures ( 1 , & tex_scr ) ;
if ( ! tex_scr ) {
printf_errf ( " (): Failed to allocate texture. " ) ;
return false ;
}
GLenum tex_tgt = GL_TEXTURE_RECTANGLE ;
if ( ps - > glx_has_texture_non_power_of_two )
tex_tgt = GL_TEXTURE_2D ;
glEnable ( tex_tgt ) ;
glBindTexture ( tex_tgt , tex_scr ) ;
glTexParameteri ( tex_tgt , GL_TEXTURE_MIN_FILTER , GL_LINEAR ) ;
glTexParameteri ( tex_tgt , GL_TEXTURE_MAG_FILTER , GL_LINEAR ) ;
glTexParameteri ( tex_tgt , GL_TEXTURE_WRAP_S , GL_CLAMP_TO_EDGE ) ;
glTexParameteri ( tex_tgt , GL_TEXTURE_WRAP_T , GL_CLAMP_TO_EDGE ) ;
glTexImage2D ( tex_tgt , 0 , GL_RGB , width , height , 0 , GL_BGRA , GL_UNSIGNED_BYTE , NULL ) ;
glCopyTexSubImage2D ( tex_tgt , 0 , 0 , 0 , dx , ps - > root_height - dy - height , width , height ) ;
# ifdef DEBUG_GLX
printf_dbgf ( " (): %d, %d, %d, %d \n " , dx , ps - > root_height - dy - height , width , height ) ;
# endif
// Paint it back
// TODO: Blur function. We are using color negation for testing now.
glTexEnvf ( GL_TEXTURE_ENV , GL_TEXTURE_ENV_MODE , GL_COMBINE ) ;
glTexEnvf ( GL_TEXTURE_ENV , GL_COMBINE_RGB , GL_REPLACE ) ;
glTexEnvf ( GL_TEXTURE_ENV , GL_OPERAND0_RGB , GL_ONE_MINUS_SRC_COLOR ) ;
glBegin ( GL_QUADS ) ;
{
const GLfloat rx = 0.0 ;
const GLfloat ry = 1.0 ;
const GLfloat rxe = 1.0 ;
const GLfloat rye = 0.0 ;
const GLint rdx = dx ;
const GLint rdy = ps - > root_height - dy ;
const GLint rdxe = rdx + width ;
const GLint rdye = rdy - height ;
# ifdef DEBUG_GLX
printf_dbgf ( " (): %f, %f, %f, %f -> %d, %d, %d, %d \n " , rx , ry , rxe , rye , rdx , rdy , rdxe , rdye ) ;
# endif
glTexCoord2f ( rx , ry ) ;
glVertex3f ( rdx , rdy , z ) ;
glTexCoord2f ( rxe , ry ) ;
glVertex3f ( rdxe , rdy , z ) ;
glTexCoord2f ( rxe , rye ) ;
glVertex3f ( rdxe , rdye , z ) ;
glTexCoord2f ( rx , rye ) ;
glVertex3f ( rdx , rdye , z ) ;
}
glEnd ( ) ;
glTexEnvi ( GL_TEXTURE_ENV , GL_TEXTURE_ENV_MODE , GL_REPLACE ) ;
glBindTexture ( tex_tgt , 0 ) ;
glDeleteTextures ( 1 , & tex_scr ) ;
glDisable ( tex_tgt ) ;
return true ;
}
/**
/**
* @ brief Render a region with texture data .
* @ brief Render a region with texture data .
*/
*/
@ -557,6 +668,8 @@ bool
glx_render ( session_t * ps , const glx_texture_t * ptex ,
glx_render ( session_t * ps , const glx_texture_t * ptex ,
int x , int y , int dx , int dy , int width , int height , int z ,
int x , int y , int dx , int dy , int width , int height , int z ,
double opacity , bool neg , XserverRegion reg_tgt ) {
double opacity , bool neg , XserverRegion reg_tgt ) {
bool blur_background = false ;
if ( ! ptex | | ! ptex - > texture ) {
if ( ! ptex | | ! ptex - > texture ) {
printf_errf ( " (): Missing texture. " ) ;
printf_errf ( " (): Missing texture. " ) ;
return false ;
return false ;
@ -565,12 +678,15 @@ glx_render(session_t *ps, const glx_texture_t *ptex,
// Enable blending if needed
// Enable blending if needed
if ( opacity < 1.0 | | GLX_TEXTURE_FORMAT_RGBA_EXT = =
if ( opacity < 1.0 | | GLX_TEXTURE_FORMAT_RGBA_EXT = =
ps - > glx_fbconfigs [ ptex - > depth ] - > texture_fmt ) {
ps - > glx_fbconfigs [ ptex - > depth ] - > texture_fmt ) {
if ( ! ps - > o . glx_no_stencil & & blur_background )
glx_blur_dst ( ps , dx , dy , width , height , z - 0.5 ) ;
glEnable ( GL_BLEND ) ;
glEnable ( GL_BLEND ) ;
// Needed for handling opacity of ARGB texture
// Needed for handling opacity of ARGB texture
glTexEnvi ( GL_TEXTURE_ENV , GL_TEXTURE_ENV_MODE , GL_MODULATE ) ;
glTexEnvi ( GL_TEXTURE_ENV , GL_TEXTURE_ENV_MODE , GL_MODULATE ) ;
// This is all weird, but X Render is using a strange ARGB format, and
// This is all weird, but X Render is using premulitplied ARGB format, and
// we need to use those things to correct it. Thanks to derhass for help.
// we need to use those things to correct it. Thanks to derhass for help.
glBlendFunc ( GL_ONE , GL_ONE_MINUS_SRC_ALPHA ) ;
glBlendFunc ( GL_ONE , GL_ONE_MINUS_SRC_ALPHA ) ;
glColor4f ( opacity , opacity , opacity , opacity ) ;
glColor4f ( opacity , opacity , opacity , opacity ) ;
@ -618,8 +734,8 @@ glx_render(session_t *ps, const glx_texture_t *ptex,
rects = XFixesFetchRegion ( ps - > dpy , reg_new , & nrects ) ;
rects = XFixesFetchRegion ( ps - > dpy , reg_new , & nrects ) ;
}
}
glEnable ( GL_TEXTURE_2D ) ;
glEnable ( ptex- > target ) ;
glBindTexture ( GL_TEXTURE_2D , ptex - > texture ) ;
glBindTexture ( ptex- > target , ptex - > texture ) ;
glBegin ( GL_QUADS ) ;
glBegin ( GL_QUADS ) ;
@ -629,9 +745,9 @@ glx_render(session_t *ps, const glx_texture_t *ptex,
GLfloat rxe = rx + ( double ) rects [ i ] . width / ptex - > width ;
GLfloat rxe = rx + ( double ) rects [ i ] . width / ptex - > width ;
GLfloat rye = ry + ( double ) rects [ i ] . height / ptex - > height ;
GLfloat rye = ry + ( double ) rects [ i ] . height / ptex - > height ;
GLint rdx = rects [ i ] . x ;
GLint rdx = rects [ i ] . x ;
GLint rdy = rects[ i ] . y ;
GLint rdy = ps- > root_height - rects[ i ] . y ;
GLint rdxe = rdx + rects [ i ] . width ;
GLint rdxe = rdx + rects [ i ] . width ;
GLint rdye = rdy + rects [ i ] . height ;
GLint rdye = rdy - rects [ i ] . height ;
// Invert Y if needed, this may not work as expected, though. I don't
// Invert Y if needed, this may not work as expected, though. I don't
// have such a FBConfig to test with.
// have such a FBConfig to test with.
@ -665,11 +781,12 @@ glx_render(session_t *ps, const glx_texture_t *ptex,
}
}
// Cleanup
// Cleanup
glBindTexture ( GL_TEXTURE_2D , 0 ) ;
glBindTexture ( ptex- > target , 0 ) ;
glColor4f ( 0.0f , 0.0f , 0.0f , 0.0f ) ;
glColor4f ( 0.0f , 0.0f , 0.0f , 0.0f ) ;
glTexEnvi ( GL_TEXTURE_ENV , GL_TEXTURE_ENV_MODE , GL_REPLACE ) ;
glTexEnvi ( GL_TEXTURE_ENV , GL_TEXTURE_ENV_MODE , GL_REPLACE ) ;
glDisable ( GL_BLEND ) ;
glDisable ( GL_BLEND ) ;
glDisable ( GL_COLOR_LOGIC_OP ) ;
glDisable ( GL_COLOR_LOGIC_OP ) ;
glDisable ( ptex - > target ) ;
return true ;
return true ;
}
}