[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [29558] branches/soc-2010-jwilkins/source/ blender/windowmanager/intern/wm_draw.c: * Optimization: Now uses GL_ARB_depth_texture and GLSL to speed up the saving and restoring of the depth buffer needed for On-Surface brush .
Jason Wilkins
Jason.A.Wilkins at gmail.com
Sat Jun 19 12:24:06 CEST 2010
Revision: 29558
http://projects.blender.org/plugins/scmsvn/viewcvs.php?view=rev&root=bf-blender&revision=29558
Author: jwilkins
Date: 2010-06-19 12:24:04 +0200 (Sat, 19 Jun 2010)
Log Message:
-----------
* Optimization: Now uses GL_ARB_depth_texture and GLSL to speed up the saving and restoring of the depth buffer needed for On-Surface brush.
Hopefully this restores the performance that was lost.
Modified Paths:
--------------
branches/soc-2010-jwilkins/source/blender/windowmanager/intern/wm_draw.c
Modified: branches/soc-2010-jwilkins/source/blender/windowmanager/intern/wm_draw.c
===================================================================
--- branches/soc-2010-jwilkins/source/blender/windowmanager/intern/wm_draw.c 2010-06-19 06:49:59 UTC (rev 29557)
+++ branches/soc-2010-jwilkins/source/blender/windowmanager/intern/wm_draw.c 2010-06-19 10:24:04 UTC (rev 29558)
@@ -324,6 +324,15 @@
char* depth;
GLenum depth_type;
+
+ GLuint depth_bind[MAX_N_TEX*MAX_N_TEX];
+ int depth_x[MAX_N_TEX], depth_y[MAX_N_TEX];
+ int depth_nx, depth_ny;
+ GLenum depth_target;
+
+ GLenum depth_vertex_shader;
+ GLenum depth_fragment_shader;
+ GLenum depth_program;
} wmDrawTriple;
static int is_pow2(int n)
@@ -392,7 +401,17 @@
wmDrawTriple *triple= win->drawdata;
glDeleteTextures(triple->nx*triple->ny, triple->bind);
- MEM_freeN(triple->depth);
+
+ if (GLEW_ARB_depth_texture && GLEW_ARB_shader_objects) {
+ glDeleteTextures(triple->depth_nx*triple->depth_ny, triple->depth_bind);
+ glDeleteObjectARB(triple->depth_vertex_shader);
+ glDeleteObjectARB(triple->depth_fragment_shader);
+ glDeleteObjectARB(triple->depth_program);
+ }
+
+ if (triple->depth)
+ MEM_freeN(triple->depth);
+
MEM_freeN(triple);
win->drawdata= NULL;
@@ -544,18 +563,204 @@
static int wm_triple_gen_depth_buffer(wmWindow *win, wmDrawTriple *triple)
{
- const int count = win->sizex * win->sizey;
- const int size = count*sizeof(GLfloat);
+ if (GLEW_ARB_depth_texture &&
+ GLEW_ARB_shader_objects &&
+ GLEW_ARB_vertex_shader &&
+ GLEW_ARB_fragment_shader &&
+ GLEW_ARB_shading_language_100)
+ {
+ GLint maxsize;
+ int x, y;
- triple->depth_type = GL_FLOAT;
- triple->depth = MEM_mallocN(size, "wm_triple_gen_depth_buffer");
+ /* compute texture sizes */
+ if(GLEW_ARB_texture_rectangle) {
+ triple->depth_target= GL_TEXTURE_RECTANGLE_ARB;
+ triple->depth_nx= 1;
+ triple->depth_ny= 1;
+ triple->depth_x[0]= win->sizex;
+ triple->depth_y[0]= win->sizey;
+ }
+ else if(GPU_non_power_of_two_support()) {
+ triple->depth_target= GL_TEXTURE_2D;
+ triple->depth_nx= 1;
+ triple->depth_ny= 1;
+ triple->depth_x[0]= win->sizex;
+ triple->depth_y[0]= win->sizey;
+ }
+ else {
+ triple->depth_target= GL_TEXTURE_2D;
+ triple->depth_nx= 0;
+ triple->depth_ny= 0;
+ split_width(win->sizex, MAX_N_TEX, triple->depth_x, &triple->depth_nx);
+ split_width(win->sizey, MAX_N_TEX, triple->depth_y, &triple->depth_ny);
+ }
+ /* generate texture names */
+ glGenTextures(triple->depth_nx*triple->depth_ny, triple->depth_bind);
+
+ if(!triple->depth_bind[0]) {
+ /* not the typical failure case but we handle it anyway */
+ printf("WM: failed to allocate depth texture for triple buffer drawing (glGenTextures).\n");
+ return 0;
+ }
+
+ for(y=0; y<triple->depth_ny; y++) {
+ for(x=0; x<triple->depth_nx; x++) {
+ /* proxy texture is only guaranteed to test for the cases that
+ * there is only one texture in use, which may not be the case */
+ glGetIntegerv(GL_MAX_TEXTURE_SIZE, &maxsize);
+
+ if(triple->depth_x[x] > maxsize || triple->depth_y[y] > maxsize) {
+ glBindTexture(triple->depth_target, 0);
+ printf("WM: failed to allocate texture for triple buffer drawing (texture too large for graphics card).\n");
+ return 0;
+ }
+
+ /* setup actual texture */
+ glBindTexture(triple->depth_target, triple->depth_bind[x + y*triple->depth_nx]);
+ glTexImage2D(triple->depth_target, 0, GL_DEPTH_COMPONENT, triple->depth_x[x], triple->depth_y[y], 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, NULL);
+ glTexParameteri(triple->depth_target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ glTexParameteri(triple->depth_target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ glTexParameteri(triple->depth_target, GL_TEXTURE_COMPARE_MODE, GL_NONE);
+ glBindTexture(triple->depth_target, 0);
+
+ /* not sure if this works everywhere .. */
+ if(glGetError() == GL_OUT_OF_MEMORY) {
+ printf("WM: failed to allocate depth texture for triple buffer drawing (out of memory).\n");
+ return 0;
+ }
+ }
+ }
+
+ {
+ int success;
+ GLsizei len;
+
+ static const GLcharARB* depth_vertex_shader_source[] = {
+// "varying vec2 texture_coordinate;\n",
+ "void main()\n",
+ "{\n",
+ "gl_TexCoord[0] = gl_MultiTexCoord0;\n",
+ "gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;\n",
+ "}\n",
+ };
+
+ static const GLcharARB* depth_fragment_shader_source[] = {
+// "varying vec2 texture_coordinate;\n",
+ "uniform sampler2DRect depth_texture;\n",
+ "void main()\n",
+ "{\n",
+ "gl_FragDepth = texture2D(depth_texture, gl_TexCoord[0].xy).x;\n",
+ "}\n",
+ };
+
+ static const GLcharARB* depth_fragment_shader_rect_source[] = {
+ "#extension GL_ARB_texture_rectangle : enable\n",
+// "varying vec2 texture_coordinate;\n",
+ "uniform sampler2DRect depth_texture;\n",
+ "void main()\n",
+ "{\n",
+ "gl_FragDepth = texture2DRect(depth_texture, gl_TexCoord[0].xy).x;\n",
+ "}\n",
+ };
+
+ triple->depth_vertex_shader = glCreateShaderObjectARB(GL_VERTEX_SHADER_ARB);
+ glShaderSourceARB(triple->depth_vertex_shader, sizeof(depth_vertex_shader_source)/sizeof(GLcharARB*), depth_vertex_shader_source, NULL);
+ glCompileShaderARB(triple->depth_vertex_shader);
+
+ glGetObjectParameterivARB(triple->depth_vertex_shader, GL_OBJECT_COMPILE_STATUS_ARB, &success);
+
+ /*if (!success)*/ {
+ GLbyte infoLog[1000];
+ len = 1000;
+
+ glGetInfoLogARB(triple->depth_vertex_shader, 1000, &len, infoLog);
+
+ //fprintf(stderr, "Error in vertex shader compilation!\n");
+
+ if (len > 0)
+ fprintf(stderr, "vertex:\n%s\n", infoLog);
+ }
+
+ triple->depth_fragment_shader = glCreateShaderObjectARB(GL_FRAGMENT_SHADER_ARB);
+
+ if (GLEW_ARB_texture_rectangle)
+ glShaderSourceARB(triple->depth_fragment_shader, sizeof(depth_fragment_shader_rect_source)/sizeof(GLcharARB*), depth_fragment_shader_rect_source, NULL);
+ else
+ glShaderSourceARB(triple->depth_fragment_shader, sizeof(depth_fragment_shader_source)/sizeof(GLcharARB*), depth_fragment_shader_source, NULL);
+
+ glCompileShaderARB(triple->depth_fragment_shader);
+
+ glGetObjectParameterivARB(triple->depth_fragment_shader, GL_OBJECT_COMPILE_STATUS_ARB, &success);
+
+ /*if (!success)*/ {
+ GLbyte infoLog[1000];
+
+ glGetInfoLogARB(triple->depth_fragment_shader, 1000, &len, infoLog);
+
+ //fprintf(stderr, "Error in fragment shader compilation!\n");
+
+ if (len > 0)
+ fprintf(stderr, "fragment:\n%s\n", infoLog);
+ }
+
+ triple->depth_program = glCreateProgramObjectARB();
+
+ glAttachObjectARB(triple->depth_program, triple->depth_vertex_shader);
+ glAttachObjectARB(triple->depth_program, triple->depth_fragment_shader);
+
+ glLinkProgramARB(triple->depth_program);
+
+ glGetObjectParameterivARB(triple->depth_program, GL_OBJECT_LINK_STATUS_ARB, &success);
+
+ /*if (!success)*/ {
+ GLbyte infoLog[1000];
+
+ glGetInfoLogARB(triple->depth_program, 1000, &len, infoLog);
+
+ //fprintf(stderr, "Error in linking!\n");
+
+ if (len > 0)
+ fprintf(stderr, "GLSL linking:\n%s\n", infoLog);
+ }
+ }
+ }
+ else {
+ const int count = win->sizex * win->sizey;
+ const int size = count*sizeof(GLfloat);
+
+ triple->depth_type = GL_FLOAT;
+ triple->depth = MEM_mallocN(size, "wm_triple_gen_depth_buffer");
+ }
+
return 1;
}
static void wm_triple_copy_depth_buffer(wmWindow *win, wmDrawTriple *triple)
{
- if (triple->depth) {
+ if (GLEW_ARB_depth_texture &&
+ GLEW_ARB_shader_objects &&
+ GLEW_ARB_vertex_shader &&
+ GLEW_ARB_fragment_shader &&
+ GLEW_ARB_shading_language_100)
+ {
+ int x, y, sizex, sizey, offx, offy;
+
+ for(y=0, offy=0; y<triple->depth_ny; offy+=triple->depth_y[y], y++) {
+ for(x=0, offx=0; x<triple->depth_nx; offx+=triple->depth_x[x], x++) {
+ sizex= (x == triple->depth_nx-1)? win->sizex-offx: triple->depth_x[x];
+ sizey= (y == triple->depth_ny-1)? win->sizey-offy: triple->depth_y[y];
+
+ glBindTexture(triple->depth_target, triple->depth_bind[x + y*triple->depth_nx]);
+ glCopyTexSubImage2D(triple->depth_target, 0, 0, 0, offx, offy, sizex, sizey);
+ }
+ }
+
+ glBindTexture(triple->depth_target, 0);
+ }
+ else if (triple->depth) {
+ glPushAttrib(GL_PIXEL_MODE_BIT);
+
glPixelStorei(GL_PACK_SWAP_BYTES, GL_FALSE);
glPixelStorei(GL_PACK_ROW_LENGTH, 0);
glPixelStorei(GL_PACK_SKIP_ROWS, 0);
@@ -566,41 +771,119 @@
glPixelTransferi(GL_DEPTH_BIAS, 0);
glReadPixels(0, 0, win->sizex, win->sizey, GL_DEPTH_COMPONENT, triple->depth_type, triple->depth);
+
+ glPopAttrib();
}
}
static void wm_triple_draw_depth_buffer(wmWindow *win, wmDrawTriple *triple)
{
- // This state changing is probably overkill, but I had a lot of trouble figuring out exactly what state was keeping this from working.
+ if (GLEW_ARB_depth_texture &&
+ GLEW_ARB_shader_objects &&
+ GLEW_ARB_vertex_shader &&
+ GLEW_ARB_fragment_shader &&
+ GLEW_ARB_shading_language_100)
+ {
+ float halfx, halfy, ratiox, ratioy;
+ int x, y, sizex, sizey, offx, offy;
+ GLint depth_texture;
- if (triple->depth) {
- glPixelStorei(GL_UNPACK_SWAP_BYTES, GL_FALSE);
- glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
- glPixelStorei(GL_UNPACK_SKIP_ROWS, 0);
- glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
- glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
+ glPushAttrib(
+ GL_COLOR_BUFFER_BIT|
+ GL_DEPTH_BUFFER_BIT);
- glPixelTransferi(GL_DEPTH_SCALE, 1);
- glPixelTransferi(GL_DEPTH_BIAS, 0);
-
- glPixelZoom(1.0, 1.0);
-
glEnable(GL_DEPTH_TEST);
+ glDepthFunc(GL_ALWAYS);
+ glDepthMask(GL_TRUE);
- glDepthMask(GL_TRUE);
glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
- glDepthFunc(GL_ALWAYS);
+ glUseProgramObjectARB(triple->depth_program);
+ depth_texture = glGetUniformLocationARB(triple->depth_program, "depth_texture");
- glRasterPos2i(0, 0);
- glDrawPixels(win->sizex, win->sizey, GL_DEPTH_COMPONENT, triple->depth_type, triple->depth);
+ glActiveTextureARB(GL_TEXTURE0_ARB);
- glDepthFunc(GL_LEQUAL);
+ glEnable(triple->depth_target);
- glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
+ for(y=0, offy=0; y<triple->depth_ny; offy+=triple->depth_y[y], y++) {
+ for(x=0, offx=0; x<triple->depth_nx; offx+=triple->depth_x[x], x++) {
+ sizex= (x == triple->depth_nx-1)? win->sizex-offx: triple->depth_x[x];
+ sizey= (y == triple->depth_ny-1)? win->sizey-offy: triple->depth_y[y];
- glDisable(GL_DEPTH_TEST);
+ /* wmOrtho for the screen has this same offset */
@@ Diff output truncated at 10240 characters. @@
More information about the Bf-blender-cvs
mailing list