glamor: Move to using shader objects.

This commit is contained in:
Eric Anholt 2009-08-20 12:32:53 -07:00 committed by Zhigang Gong
parent fbbdd788cb
commit f1dbed5456
4 changed files with 221 additions and 41 deletions

View File

@ -97,12 +97,21 @@ glamor_init(ScreenPtr screen)
dixSetPrivate(&screen->devPrivates, glamor_screen_private_key, glamor_priv); dixSetPrivate(&screen->devPrivates, glamor_screen_private_key, glamor_priv);
glewInit();
if (!GLEW_ARB_shader_objects) {
ErrorF("GL_ARB_shader_objects required\n");
goto fail;
}
if (!GLEW_ARB_vertex_shader) {
ErrorF("GL_ARB_vertex_shader required\n");
goto fail;
}
if (!RegisterBlockAndWakeupHandlers(glamor_block_handler, if (!RegisterBlockAndWakeupHandlers(glamor_block_handler,
glamor_wakeup_handler, glamor_wakeup_handler,
NULL)) { NULL)) {
dixSetPrivate(&screen->devPrivates, glamor_screen_private_key, NULL); goto fail;
xfree(glamor_priv);
return FALSE;
} }
glamor_priv->saved_create_gc = screen->CreateGC; glamor_priv->saved_create_gc = screen->CreateGC;
@ -114,9 +123,14 @@ glamor_init(ScreenPtr screen)
glamor_priv->saved_destroy_pixmap = screen->DestroyPixmap; glamor_priv->saved_destroy_pixmap = screen->DestroyPixmap;
screen->DestroyPixmap = glamor_destroy_pixmap; screen->DestroyPixmap = glamor_destroy_pixmap;
glewInit(); glamor_init_solid_shader(screen);
return TRUE; return TRUE;
fail:
xfree(glamor_priv);
dixSetPrivate(&screen->devPrivates, glamor_screen_private_key, NULL);
return FALSE;
} }
void void

View File

@ -39,16 +39,7 @@
#include "glamor_priv.h" #include "glamor_priv.h"
static void Bool
glamor_set_color_from_fgpixel(PixmapPtr pixmap, unsigned long fg_pixel)
{
glColor4ub((fg_pixel >> 16) & 0xff,
(fg_pixel >> 8) & 0xff,
(fg_pixel) & 0xff,
(fg_pixel >> 24) & 0xff);
}
static Bool
glamor_set_destination_pixmap(PixmapPtr pixmap) glamor_set_destination_pixmap(PixmapPtr pixmap)
{ {
ScreenPtr screen = pixmap->drawable.pScreen; ScreenPtr screen = pixmap->drawable.pScreen;
@ -63,37 +54,103 @@ glamor_set_destination_pixmap(PixmapPtr pixmap)
screen_pixmap->drawable.width, screen_pixmap->drawable.width,
screen_pixmap->drawable.height); screen_pixmap->drawable.height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0, screen_pixmap->drawable.width,
0, screen_pixmap->drawable.height,
-1.0, 1.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
return TRUE; return TRUE;
} }
void void
glamor_solid(PixmapPtr pixmap, int x, int y, int width, int height, glamor_get_transform_uniform_locations(GLint prog,
unsigned char alu, unsigned long planemask, unsigned long fg_pixel) glamor_transform_uniforms *uniform_locations)
{ {
int x1 = x; uniform_locations->x_bias = glGetUniformLocationARB(prog, "x_bias");
int x2 = x + width; uniform_locations->x_scale = glGetUniformLocationARB(prog, "x_scale");
int y1 = y; uniform_locations->y_bias = glGetUniformLocationARB(prog, "y_bias");
int y2 = y + height; uniform_locations->y_scale = glGetUniformLocationARB(prog, "y_scale");
}
if (!glamor_set_destination_pixmap(pixmap)) /* We don't use a full matrix for our transformations because it's
return; * wasteful when all we want is to rescale to NDC and possibly do a flip
glamor_set_color_from_fgpixel(pixmap, fg_pixel); * if it's the front buffer.
*/
void
glamor_set_transform_for_pixmap(PixmapPtr pixmap,
glamor_transform_uniforms *uniform_locations)
{
glUniform1fARB(uniform_locations->x_bias, -pixmap->drawable.width / 2.0f);
glUniform1fARB(uniform_locations->x_scale, 2.0f / pixmap->drawable.width);
glUniform1fARB(uniform_locations->y_bias, -pixmap->drawable.height / 2.0f);
glUniform1fARB(uniform_locations->y_scale, -2.0f / pixmap->drawable.height);
}
glBegin(GL_TRIANGLE_FAN); GLint
glVertex2f(x1, y1); glamor_compile_glsl_prog(GLenum type, const char *source)
glVertex2f(x1, y2); {
glVertex2f(x2, y2); GLint ok;
glVertex2f(x2, y1); GLint prog;
glEnd();
prog = glCreateShaderObjectARB(type);
glShaderSourceARB(prog, 1, (const GLchar **)&source, NULL);
glCompileShaderARB(prog);
glGetObjectParameterivARB(prog, GL_OBJECT_COMPILE_STATUS_ARB, &ok);
if (!ok) {
GLchar *info;
GLint size;
glGetObjectParameterivARB(prog, GL_OBJECT_INFO_LOG_LENGTH_ARB, &size);
info = malloc(size);
glGetInfoLogARB(prog, size, NULL, info);
ErrorF("Failed to compile %s: %s\n",
type == GL_FRAGMENT_SHADER ? "FS" : "VS",
info);
ErrorF("Program source:\n%s", source);
FatalError("GLSL compile failure\n");
}
return prog;
}
void
glamor_link_glsl_prog(GLint prog)
{
GLint ok;
glLinkProgram(prog);
glGetObjectParameterivARB(prog, GL_OBJECT_LINK_STATUS_ARB, &ok);
if (!ok) {
GLchar *info;
GLint size;
glGetObjectParameterivARB(prog, GL_OBJECT_INFO_LOG_LENGTH_ARB, &size);
info = malloc(size);
glGetInfoLogARB(prog, size, NULL, info);
ErrorF("Failed to link: %s\n",
info);
FatalError("GLSL link failure\n");
}
}
static float ubyte_to_float(uint8_t b)
{
return b / 255.0f;
}
void
glamor_get_color_4f_from_pixel(PixmapPtr pixmap, unsigned long fg_pixel,
GLfloat *color)
{
if (pixmap->drawable.depth < 24) {
ErrorF("pixmap with bad depth\n");
color[0] = 1.0;
color[1] = 0.0;
color[2] = 1.0;
color[3] = 1.0;
} else {
color[0] = ubyte_to_float(fg_pixel >> 16);
color[1] = ubyte_to_float(fg_pixel >> 8);
color[2] = ubyte_to_float(fg_pixel >> 0);
color[3] = ubyte_to_float(fg_pixel >> 24);
}
} }
void void

View File

@ -82,3 +82,89 @@ glamor_fill(DrawablePtr drawable,
break; break;
} }
} }
void
glamor_init_solid_shader(ScreenPtr screen)
{
glamor_screen_private *glamor_priv = glamor_get_screen_private(screen);
const char *solid_vs_only =
"uniform vec4 color;\n"
"uniform float x_bias;\n"
"uniform float x_scale;\n"
"uniform float y_bias;\n"
"uniform float y_scale;\n"
"void main()\n"
"{\n"
" gl_Position = vec4((gl_Vertex.x + x_bias) * x_scale,\n"
" (gl_Vertex.y + y_bias) * y_scale,\n"
" 0,\n"
" 1);\n"
" gl_Color = color;\n"
"}\n";
const char *solid_vs =
"uniform float x_bias;\n"
"uniform float x_scale;\n"
"uniform float y_bias;\n"
"uniform float y_scale;\n"
"void main()\n"
"{\n"
" gl_Position = vec4((gl_Vertex.x + x_bias) * x_scale,\n"
" (gl_Vertex.y + y_bias) * y_scale,\n"
" 0,\n"
" 1);\n"
"}\n";
const char *solid_fs =
"uniform vec4 color;\n"
"void main()\n"
"{\n"
" gl_FragColor = color;\n"
"}\n";
GLint fs_prog, vs_prog;
glamor_priv->solid_prog = glCreateProgramObjectARB();
if (GLEW_ARB_fragment_shader) {
vs_prog = glamor_compile_glsl_prog(GL_VERTEX_SHADER_ARB, solid_vs);
fs_prog = glamor_compile_glsl_prog(GL_FRAGMENT_SHADER_ARB, solid_fs);
glAttachObjectARB(glamor_priv->solid_prog, vs_prog);
glAttachObjectARB(glamor_priv->solid_prog, fs_prog);
} else {
vs_prog = glamor_compile_glsl_prog(GL_VERTEX_SHADER_ARB, solid_vs_only);
glAttachObjectARB(glamor_priv->solid_prog, vs_prog);
}
glamor_link_glsl_prog(glamor_priv->solid_prog);
glamor_priv->solid_color_uniform_location =
glGetUniformLocationARB(glamor_priv->solid_prog, "color");
glamor_get_transform_uniform_locations(glamor_priv->solid_prog,
&glamor_priv->solid_transform);
}
void
glamor_solid(PixmapPtr pixmap, int x, int y, int width, int height,
unsigned char alu, unsigned long planemask, unsigned long fg_pixel)
{
ScreenPtr screen = pixmap->drawable.pScreen;
glamor_screen_private *glamor_priv = glamor_get_screen_private(screen);
int x1 = x;
int x2 = x + width;
int y1 = y;
int y2 = y + height;
GLfloat color[4];
if (!glamor_set_destination_pixmap(pixmap))
return;
glUseProgramObjectARB(glamor_priv->solid_prog);
glamor_get_color_4f_from_pixel(pixmap, fg_pixel, color);
glUniform4fvARB(glamor_priv->solid_color_uniform_location, 1, color);
glamor_set_transform_for_pixmap(pixmap, &glamor_priv->solid_transform);
glBegin(GL_TRIANGLE_FAN);
glVertex2f(x1, y1);
glVertex2f(x1, y2);
glVertex2f(x2, y2);
glVertex2f(x2, y1);
glEnd();
glUseProgramObjectARB(0);
}

View File

@ -31,10 +31,22 @@
#include "glamor.h" #include "glamor.h"
#include <GL/glew.h> #include <GL/glew.h>
typedef struct glamor_transform_uniforms {
GLint x_bias;
GLint x_scale;
GLint y_bias;
GLint y_scale;
} glamor_transform_uniforms;
typedef struct glamor_screen_private { typedef struct glamor_screen_private {
CreateGCProcPtr saved_create_gc; CreateGCProcPtr saved_create_gc;
CreatePixmapProcPtr saved_create_pixmap; CreatePixmapProcPtr saved_create_pixmap;
DestroyPixmapProcPtr saved_destroy_pixmap; DestroyPixmapProcPtr saved_destroy_pixmap;
/* glamor_solid */
GLint solid_prog;
GLint solid_color_uniform_location;
glamor_transform_uniforms solid_transform;
} glamor_screen_private; } glamor_screen_private;
extern DevPrivateKey glamor_screen_private_key; extern DevPrivateKey glamor_screen_private_key;
@ -50,9 +62,6 @@ PixmapPtr glamor_get_drawable_pixmap(DrawablePtr drawable);
/* glamor_core.c */ /* glamor_core.c */
Bool glamor_create_gc(GCPtr gc); Bool glamor_create_gc(GCPtr gc);
void glamor_solid(PixmapPtr pixmap, int x, int y, int width, int height,
unsigned char alu, unsigned long planemask,
unsigned long fg_pixel);
void glamor_stipple(PixmapPtr pixmap, PixmapPtr stipple, void glamor_stipple(PixmapPtr pixmap, PixmapPtr stipple,
int x, int y, int width, int height, int x, int y, int width, int height,
unsigned char alu, unsigned long planemask, unsigned char alu, unsigned long planemask,
@ -62,6 +71,15 @@ void glamor_tile(PixmapPtr pixmap, PixmapPtr tile,
int x, int y, int width, int height, int x, int y, int width, int height,
unsigned char alu, unsigned long planemask, unsigned char alu, unsigned long planemask,
int tile_x, int tile_y); int tile_x, int tile_y);
GLint glamor_compile_glsl_prog(GLenum type, const char *source);
void glamor_link_glsl_prog(GLint prog);
void glamor_get_color_4f_from_pixel(PixmapPtr pixmap, unsigned long fg_pixel,
GLfloat *color);
Bool glamor_set_destination_pixmap(PixmapPtr pixmap);
void glamor_get_transform_uniform_locations(GLint prog,
glamor_transform_uniforms *uniform_locations);
void glamor_set_transform_for_pixmap(PixmapPtr pixmap,
glamor_transform_uniforms *uniform_locations);
/* glamor_fill.c */ /* glamor_fill.c */
void glamor_fill(DrawablePtr drawable, void glamor_fill(DrawablePtr drawable,
@ -70,6 +88,9 @@ void glamor_fill(DrawablePtr drawable,
int y, int y,
int width, int width,
int height); int height);
void glamor_solid(PixmapPtr pixmap, int x, int y, int width, int height,
unsigned char alu, unsigned long planemask,
unsigned long fg_pixel);
/* glamor_fillspans.c */ /* glamor_fillspans.c */
void glamor_fill_spans(DrawablePtr drawable, void glamor_fill_spans(DrawablePtr drawable,
@ -79,4 +100,6 @@ void glamor_fill_spans(DrawablePtr drawable,
int *widths, int *widths,
int sorted); int sorted);
void glamor_init_solid_shader(ScreenPtr screen);
#endif /* GLAMOR_PRIV_H */ #endif /* GLAMOR_PRIV_H */