Merge lp:~smspillaz/compiz/compiz.revenge-of-the-blur-plugin into lp:compiz/0.9.12

Proposed by Sam Spilsbury
Status: Merged
Approved by: Marco Trevisan (Treviño)
Approved revision: 4020
Merged at revision: 4020
Proposed branch: lp:~smspillaz/compiz/compiz.revenge-of-the-blur-plugin
Merge into: lp:compiz/0.9.12
Diff against target: 3208 lines (+1260/-1141)
16 files modified
debian/compiz-plugins.install (+2/-0)
plugins/CMakeLists.txt (+0/-1)
plugins/blur/CMakeLists.txt (+12/-12)
plugins/blur/src/blur.cpp (+1086/-1077)
plugins/blur/src/blur.h (+59/-38)
plugins/opengl/DRIVERS (+10/-0)
plugins/opengl/include/opengl/opengl.h (+14/-2)
plugins/opengl/include/opengl/program.h (+1/-1)
plugins/opengl/include/opengl/vertexbuffer.h (+1/-0)
plugins/opengl/src/paint.cpp (+10/-0)
plugins/opengl/src/privates.h (+3/-0)
plugins/opengl/src/program.cpp (+2/-2)
plugins/opengl/src/screen.cpp (+44/-4)
plugins/opengl/src/shadercache.cpp (+5/-4)
plugins/opengl/src/vertexbuffer.cpp (+5/-0)
plugins/opengl/src/window.cpp (+6/-0)
To merge this branch: bzr merge lp:~smspillaz/compiz/compiz.revenge-of-the-blur-plugin
Reviewer Review Type Date Requested Status
Marco Trevisan (Treviño) Approve
PS Jenkins bot (community) continuous-integration Approve
Review via email: mp+294604@code.launchpad.net

Commit message

Blur: port the plugin to modern OpenGL

Description of the change

Port the blur plugin to modern OpenGL

Note: An ABI break was necessary to add glTransformationComplete to GLWindow. Other than that there's very little impact on other plugins.

To post a comment you must log in.
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
4019. By Sam Spilsbury <email address hidden>

debian: Install the blur plugin as part of compiz-plugins

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
4020. By Sam Spilsbury <email address hidden>

opengl: Don't invalidate the scratch buffer frame age every time it is queried

We only want to do this when we query the scratch buffer age and then
use it - as it is only on use when the age resets back to an invalidated
state.

Previously, the age would re-set every time it is queried, which would
cause it to appear invalidated the next time damageCutoff was reached.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
Marco Trevisan (Treviño) (3v1n0) wrote :

Nice cleanup, thanks a lot.

ABI changes are in fact not relevant for other parts.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'debian/compiz-plugins.install'
2--- debian/compiz-plugins.install 2015-07-24 16:28:37 +0000
3+++ debian/compiz-plugins.install 2016-05-14 02:33:05 +0000
4@@ -4,6 +4,8 @@
5 usr/share/compiz/*annotate.*
6 usr/lib/*/compiz/*bench.*
7 usr/share/compiz/*bench.*
8+usr/lib/*/compiz/*blur.*
9+usr/share/compiz/*blur.*
10 usr/lib/*/compiz/*clone.*
11 usr/share/compiz/*clone.*
12 usr/lib/*/compiz/*crashhandler.*
13
14=== modified file 'plugins/CMakeLists.txt'
15--- plugins/CMakeLists.txt 2016-03-03 14:23:38 +0000
16+++ plugins/CMakeLists.txt 2016-05-14 02:33:05 +0000
17@@ -12,7 +12,6 @@
18 # temporarily disable plugins that aren't ported yet
19 set (COMPIZ_DISABLE_PLUGIN_ANIMATIONADDON ON)
20 set (COMPIZ_DISABLE_PLUGIN_BICUBIC ON)
21-set (COMPIZ_DISABLE_PLUGIN_BLUR ON)
22 set (COMPIZ_DISABLE_PLUGIN_COLORFILTER ON)
23 set (COMPIZ_DISABLE_PLUGIN_GROUP ON)
24 set (COMPIZ_DISABLE_PLUGIN_LOGINOUT ON)
25
26=== modified file 'plugins/blur/CMakeLists.txt'
27--- plugins/blur/CMakeLists.txt 2012-05-17 10:41:21 +0000
28+++ plugins/blur/CMakeLists.txt 2016-05-14 02:33:05 +0000
29@@ -2,15 +2,15 @@
30
31 include (CompizPlugin)
32
33-#find_package (OpenGL)
34-
35-#if (OPENGL_GLU_FOUND)
36-# compiz_plugin(blur PLUGINDEPS composite opengl LIBRARIES decoration ${OPENGL_glu_LIBRARY} INCDIRS ${OPENGL_INCLUDE_DIR})
37-
38-# if (COMPIZ_BUILD_WITH_RPATH AND NOT COMPIZ_DISABLE_PLUGIN_BLUR)
39-# set_target_properties (
40-# blur PROPERTIES
41-# INSTALL_RPATH "${COMPIZ_LIBDIR}"
42-# )
43-# endif (COMPIZ_BUILD_WITH_RPATH AND NOT COMPIZ_DISABLE_PLUGIN_BLUR)
44-#endif ()
45+find_package (OpenGL)
46+
47+if (OPENGL_GLU_FOUND)
48+ compiz_plugin(blur PLUGINDEPS composite opengl LIBRARIES decoration ${OPENGL_glu_LIBRARY} INCDIRS ${OPENGL_INCLUDE_DIR})
49+
50+ if (COMPIZ_BUILD_WITH_RPATH AND NOT COMPIZ_DISABLE_PLUGIN_BLUR)
51+ set_target_properties (
52+ blur PROPERTIES
53+ INSTALL_RPATH "${COMPIZ_LIBDIR}"
54+ )
55+ endif (COMPIZ_BUILD_WITH_RPATH AND NOT COMPIZ_DISABLE_PLUGIN_BLUR)
56+endif ()
57
58=== modified file 'plugins/blur/src/blur.cpp'
59--- plugins/blur/src/blur.cpp 2013-05-09 13:43:07 +0000
60+++ plugins/blur/src/blur.cpp 2016-05-14 02:33:05 +0000
61@@ -22,19 +22,22 @@
62 *
63 * Author: David Reveman <davidr@novell.com>
64 */
65-
66 #include <blur.h>
67+#include <sstream>
68+#include <opengl/framebufferobject.h>
69+
70+/* Supporting independent texture fetch operations will require
71+ * GLVertexBuffer to support per-plugin attributes as texture co-ordinates
72+ * are two-component and not four-component
73+ */
74+#define INDEPENDENT_TEX_SUPPORTED 0
75
76 COMPIZ_PLUGIN_20090315 (blur, BlurPluginVTable)
77
78-const unsigned short BLUR_GAUSSIAN_RADIUS_MAX = 15;
79-
80-const unsigned short BLUR_STATE_CLIENT = 0;
81-const unsigned short BLUR_STATE_DECOR = 1;
82-const unsigned short BLUR_STATE_NUM = 2;
83-
84 /* pascal triangle based kernel generator */
85-static int
86+namespace
87+{
88+int
89 blurCreateGaussianLinearKernel (int radius,
90 float strength,
91 float *amp,
92@@ -106,6 +109,7 @@
93
94 return radius;
95 }
96+}
97
98 void
99 BlurScreen::updateFilterRadius ()
100@@ -137,20 +141,11 @@
101 {
102 updateFilterRadius ();
103
104- foreach (BlurFunction &bf, srcBlurFunctions)
105- GLFragment::destroyFragmentFunction (bf.id);
106 srcBlurFunctions.clear ();
107- foreach (BlurFunction &bf, dstBlurFunctions)
108- GLFragment::destroyFragmentFunction (bf.id);
109 dstBlurFunctions.clear ();
110
111- width = height = 0;
112-
113- if (program)
114- {
115- GL::deletePrograms (1, &program);
116- program = 0;
117- }
118+ program.reset ();
119+ texture.clear ();
120 }
121
122 static CompRegion
123@@ -249,7 +244,6 @@
124 int threshold,
125 std::vector<BlurBox> box)
126 {
127-
128 this->state[state].threshold = threshold;
129 this->state[state].box = box;
130
131@@ -289,7 +283,7 @@
132
133 match = &bScreen->optionGetFocusBlurMatch ();
134
135- focus = GL::fragmentProgram && match->evaluate (window);
136+ focus = GL::shaders && match->evaluate (window);
137 if (focus != focusBlur)
138 {
139 focusBlur = focus;
140@@ -421,49 +415,75 @@
141 }
142
143 cScreen->preparePaint (msSinceLastPaint);
144-
145- if (cScreen->damageMask () & COMPOSITE_SCREEN_DAMAGE_REGION_MASK)
146+}
147+
148+bool
149+BlurScreen::markAreaDirty (const CompRegion &r)
150+{
151+ return allowAreaDirtyOnOwnDamageBuffer;
152+}
153+
154+void
155+BlurScreen::damageCutoff ()
156+{
157+ if (alphaBlur)
158 {
159- /* walk from bottom to top and expand damage */
160- if (alphaBlur)
161+ this->output = &screen->fullscreenOutput ();
162+
163+ /* We need to do a primary pass here with glPaint to check which
164+ * regions of the backbuffer need to be updated.
165+ *
166+ * Because the backbuffer is effectively partially undefined, we are completely
167+ * reliant on what core is telling us the repair regions of the
168+ * backbuffer need to be - but obviously we can't completely rely
169+ * on it because of a feedback effect, as we need to expand
170+ * the repair region slightly so that the texture sampler
171+ * doesn't go out of range of the damage region. If we were to
172+ * simply expand the damage region, then that would feedback to us
173+ * on the next frame, until the damage region eventually became infinite.
174+ *
175+ * As such, we have a tracker in core to track all damage except the effect
176+ * of expanding the damage region that came back to us. We then use
177+ * this tracker along with the frame age to determine what damage really
178+ * needs to be expanded in order to determine the backbuffer update region,
179+ * and then use the real damage in order to determine what blur regions
180+ * should be updated
181+ */
182+ backbufferUpdateRegionThisFrame &= emptyRegion;
183+ CompRegion frameAgeDamage = damageQuery->damageForFrameAge (cScreen->getFrameAge ());
184+ foreach (CompWindow *w, screen->windows ())
185 {
186- int x1, y1, x2, y2;
187- int count = 0;
188- CompRegion damage (cScreen->currentDamage ());
189-
190- foreach (CompWindow *w, screen->windows ())
191- {
192- BLUR_WINDOW (w);
193-
194- if (!w->isViewable () || !CompositeWindow::get (w)->damaged ())
195- continue;
196-
197- if (!bw->region.isEmpty ())
198- {
199- CompRect r = bw->region.boundingRect ();
200- CompRect d = damage.boundingRect ();
201- x1 = r.x1 () - filterRadius;
202- y1 = r.y1 () - filterRadius;
203- x2 = r.x2 () + filterRadius;
204- y2 = r.y2 () + filterRadius;
205-
206- if (x1 < d.x2 () &&
207- y1 < d.y2 () &&
208- x2 > d.x1 () &&
209- y2 > d.y1 ())
210- {
211- damage.shrink (-filterRadius, -filterRadius);
212- count++;
213- }
214- }
215- }
216-
217- if (count)
218- cScreen->damageRegion (damage);
219-
220- this->count = count;
221+ /* Skip windows that would not have glPaint called on them */
222+ if (w->destroyed ())
223+ continue;
224+
225+ if (!w->shaded () && !w->isViewable ())
226+ continue;
227+
228+ BlurWindow *bw = BlurWindow::get (w);
229+
230+ if (!bw->cWindow->redirected ())
231+ continue;
232+
233+ if (!bw->projectedBlurRegion.isEmpty ())
234+ bw->projectedBlurRegion &= emptyRegion;
235+
236+ GLMatrix screenSpace;
237+ screenSpace.toScreenSpace (this->output, -DEFAULT_Z_CAMERA);
238+
239+ bw->gWindow->glPaint (bw->gWindow->paintAttrib (), screenSpace,
240+ frameAgeDamage,
241+ PAINT_WINDOW_NO_CORE_INSTANCE_MASK);
242+
243+ backbufferUpdateRegionThisFrame += bw->projectedBlurRegion;
244 }
245+
246+ allowAreaDirtyOnOwnDamageBuffer = false;
247+ cScreen->damageRegion (backbufferUpdateRegionThisFrame);
248+ allowAreaDirtyOnOwnDamageBuffer = true;
249 }
250+
251+ cScreen->damageCutoff ();
252 }
253
254 bool
255@@ -471,23 +491,10 @@
256 const GLMatrix &transform, const CompRegion &region,
257 CompOutput *output, unsigned int mask)
258 {
259- bool status;
260-
261 if (alphaBlur)
262 {
263 stencilBox = region.boundingRect ();
264 this->region = region;
265-
266- if (mask & PAINT_SCREEN_REGION_MASK)
267- {
268- /* we need to redraw more than the screen region being updated */
269- if (count)
270- {
271- this->region.shrink (-filterRadius * 2, -filterRadius * 2);
272-
273- this->region &= screen->region ();
274- }
275- }
276 }
277
278 if (!blurOcclusion)
279@@ -500,12 +507,7 @@
280
281 this->output = output;
282
283- if (alphaBlur)
284- status = gScreen->glPaintOutput (sAttrib, transform, this->region, output, mask);
285- else
286- status = gScreen->glPaintOutput (sAttrib, transform, region, output, mask);
287-
288- return status;
289+ return gScreen->glPaintOutput (sAttrib, transform, region, output, mask);
290 }
291
292 void
293@@ -542,12 +544,42 @@
294 cScreen->donePaint ();
295 }
296
297+void
298+BlurWindow::glTransformationComplete (const GLMatrix &matrix,
299+ const CompRegion &region,
300+ unsigned int mask)
301+{
302+ gWindow->glTransformationComplete (matrix, region, mask);
303+
304+ int clientThreshold;
305+ const CompRegion *reg = NULL;
306+
307+ /* only care about client window blurring when it's translucent */
308+ if (mask & PAINT_WINDOW_TRANSLUCENT_MASK)
309+ clientThreshold = state[BLUR_STATE_CLIENT].threshold;
310+ else
311+ clientThreshold = 0;
312+
313+ if (mask & PAINT_WINDOW_TRANSFORMED_MASK)
314+ reg = &infiniteRegion;
315+ else
316+ reg = &region;
317+
318+ bScreen->tmpRegion = this->region.intersected (*reg);
319+
320+ if (state[BLUR_STATE_DECOR].threshold || clientThreshold)
321+ {
322+ determineBlurRegion (bScreen->optionGetFilter (),
323+ matrix,
324+ clientThreshold);
325+ }
326+}
327+
328 bool
329 BlurWindow::glPaint (const GLWindowPaintAttrib &attrib,
330 const GLMatrix &transform,
331 const CompRegion &region, unsigned int mask)
332 {
333-
334 bool status = gWindow->glPaint (attrib, transform, region, mask);
335
336 if (!bScreen->blurOcclusion &&
337@@ -564,307 +596,359 @@
338 return status;
339 }
340
341-GLFragment::FunctionId
342-BlurScreen::getSrcBlurFragmentFunction (GLTexture *texture,
343- int param)
344-{
345- GLFragment::FunctionData data;
346+namespace
347+{
348+struct SamplerInfo
349+{
350+ GLint target;
351+ CompString func;
352+};
353+
354+SamplerInfo
355+getSamplerInfoForSize (const CompSize &size)
356+{
357+ SamplerInfo info;
358+
359+#ifdef USE_GLES
360+ info.target = GL_TEXTURE_2D;
361+ info.func = "texture2D";
362+#else
363+ if (GL::textureNonPowerOfTwo ||
364+ (POWER_OF_TWO (size.width ()) && POWER_OF_TWO (size.height ())))
365+ {
366+ info.target = GL_TEXTURE_2D;
367+ info.func = "texture2D";
368+ }
369+ else
370+ {
371+ info.target = GL_TEXTURE_RECTANGLE_NV;
372+ info.func = "textureRECT";
373+ }
374+#endif
375+
376+ return info;
377+}
378+}
379+
380+/* XXX: param is redundant */
381+const CompString &
382+BlurScreen::getSrcBlurFragmentFunction (GLTexture *texture)
383+{
384 BlurFunction function;
385- int target;
386-
387- if (texture->target () == GL_TEXTURE_2D)
388- target = COMP_FETCH_TARGET_2D;
389- else
390- target = COMP_FETCH_TARGET_RECT;
391-
392- foreach (BlurFunction &bf, srcBlurFunctions)
393- if (bf.param == param && bf.target == target)
394- return bf.id;
395-
396- if (data.status ())
397- {
398- static const char *temp[] = { "offset0", "offset1", "sum" };
399- unsigned int i;
400-
401- for (i = 0; i < sizeof (temp) / sizeof (temp[0]); i++)
402- data.addTempHeaderOp (temp[i]);
403-
404- data.addDataOp (
405- "MUL offset0, program.env[%d].xyzw, { 1.0, 1.0, 0.0, 0.0 };"
406- "MUL offset1, program.env[%d].zwww, { 1.0, 1.0, 0.0, 0.0 };",
407- param, param);
408-
409-
410- switch (optionGetFilter ()) {
411- case BlurOptions::Filter4xbilinear:
412- default:
413- data.addFetchOp ("output", "offset0", target);
414- data.addDataOp ("MUL sum, output, 0.25;");
415- data.addFetchOp ("output", "-offset0", target);
416- data.addDataOp ("MAD sum, output, 0.25, sum;");
417- data.addFetchOp ("output", "offset1", target);
418- data.addDataOp ("MAD sum, output, 0.25, sum;");
419- data.addFetchOp ("output", "-offset1", target);
420- data.addDataOp ("MAD output, output, 0.25, sum;");
421- break;
422- }
423-
424- if (!data.status ())
425- return 0;
426-
427- function.id = data.createFragmentFunction ("blur");
428- function.target = target;
429- function.param = param;
430- function.unit = 0;
431-
432- srcBlurFunctions.push_back (function);
433-
434- return function.id;
435- }
436-
437- return 0;
438+ std::stringstream data (std::stringstream::out);
439+
440+ SamplerInfo info (getSamplerInfoForSize (CompSize (texture->width (),
441+ texture->height ())));
442+
443+ foreach (const BlurFunction &bf, srcBlurFunctions)
444+ if (bf.target == info.target)
445+ return bf.shader;
446+
447+ data << "uniform vec4 focusblur_input_offset;\n"\
448+ "\n"\
449+ "void focusblur_fragment ()\n"\
450+ "{\n";
451+
452+ if (optionGetFilter () == BlurOptions::Filter4xbilinear)
453+ data << " float blur_offset0, blur_offset1;\n"\
454+ " vec4 blur_sum;\n"\
455+ " vec4 offset0 = focusblur_input_offset.xyzw * vec4 (1.0, 1.0, 0.0, 0.0);\n"\
456+ " vec4 offset1 = focusblur_input_offset.zwww * vec4 (1.0, 1.0, 0.0, 0.0);\n"
457+ " vec4 output = texture2D (texture0, vTexCoord0 + offset0);\n"\
458+ " blur_sum = output * 0.25;\n"\
459+ " output = " << info.func << " (texture0, vTexCoord0 - offset0);\n"\
460+ " blur_sum += output * 0.25;\n"\
461+ " output = " << info.func << " (texture0, vTexCoord0 + offset1);\n"\
462+ " blur_sum += output * 0.25;\n"\
463+ " output = " << info.func << " (texture0, vTexCoord0 - offset1);\n"\
464+ " output = output * 0.25 + blur_sum;\n"\
465+ " gl_FragColor = output;\n";
466+
467+ data << "}\n";
468+
469+ function.shader = data.str ();
470+ function.target = info.target;
471+
472+ srcBlurFunctions.push_back (function);
473+
474+ return srcBlurFunctions.back ().shader;
475 }
476
477-GLFragment::FunctionId
478+/* This seems incomplete to me */
479+
480+const CompString &
481 BlurScreen::getDstBlurFragmentFunction (GLTexture *texture,
482- int param,
483- int unit,
484+ int unit,
485 int numITC,
486 int startTC)
487 {
488- BlurFunction function;
489- GLFragment::FunctionData data;
490- int target;
491- char *targetString;
492+ BlurFunction function;
493+ std::stringstream data (std::stringstream::out);
494+ int saturation = optionGetSaturation ();
495
496- if (texture->target () == GL_TEXTURE_2D)
497- {
498- target = COMP_FETCH_TARGET_2D;
499- targetString = (char *) "2D";
500- }
501- else
502- {
503- target = COMP_FETCH_TARGET_RECT;
504- targetString = (char *) "RECT";
505- }
506+ SamplerInfo info (getSamplerInfoForSize (CompSize (texture->width (),
507+ texture->height ())));
508
509 foreach (BlurFunction &function, dstBlurFunctions)
510- if (function.param == param &&
511- function.target == target &&
512- function.unit == unit &&
513+ if (function.target == info.target &&
514 function.numITC == numITC &&
515- function.startTC == startTC)
516- return function.id;
517-
518- if (data.status ())
519- {
520- static const char *temp[] = { "fCoord", "mask", "sum", "dst" };
521- int i, j;
522- char str[1024];
523- int saturation = optionGetSaturation ();
524- int numIndirect;
525- int numIndirectOp;
526- int base, end, ITCbase;
527-
528- for (i = 0; (unsigned int) i < sizeof (temp) / sizeof (temp[0]); i++)
529- data.addTempHeaderOp (temp[i]);
530-
531- if (saturation < 100)
532- data.addTempHeaderOp ("sat");
533-
534- switch (optionGetFilter ()) {
535- case BlurOptions::Filter4xbilinear: {
536- static const char *filterTemp[] = {
537- "t0", "t1", "t2", "t3",
538- "s0", "s1", "s2", "s3"
539- };
540-
541- for (i = 0;
542- (unsigned int) i < sizeof (filterTemp) / sizeof (filterTemp[0]);
543- i++)
544- data.addTempHeaderOp (filterTemp[i]);
545-
546- data.addFetchOp ("output", NULL, target);
547- data.addColorOp ("output", "output");
548-
549- data.addDataOp (
550- "MUL fCoord, fragment.position, program.env[%d];",
551- param);
552-
553-
554- data.addDataOp (
555- "ADD t0, fCoord, program.env[%d];"
556- "TEX s0, t0, texture[%d], %s;"
557-
558- "SUB t1, fCoord, program.env[%d];"
559- "TEX s1, t1, texture[%d], %s;"
560-
561- "MAD t2, program.env[%d], { -1.0, 1.0, 0.0, 0.0 }, fCoord;"
562- "TEX s2, t2, texture[%d], %s;"
563-
564- "MAD t3, program.env[%d], { 1.0, -1.0, 0.0, 0.0 }, fCoord;"
565- "TEX s3, t3, texture[%d], %s;"
566-
567- "MUL_SAT mask, output.a, program.env[%d];"
568-
569- "MUL sum, s0, 0.25;"
570- "MAD sum, s1, 0.25, sum;"
571- "MAD sum, s2, 0.25, sum;"
572- "MAD sum, s3, 0.25, sum;",
573-
574- param + 2, unit, targetString,
575- param + 2, unit, targetString,
576- param + 2, unit, targetString,
577- param + 2, unit, targetString,
578- param + 1);
579-
580- } break;
581- case BlurOptions::FilterGaussian: {
582-
583- /* try to use only half of the available temporaries to keep
584- other plugins working */
585- if ((maxTemp / 2) - 4 >
586- (numTexop + (numTexop - numITC)) * 2)
587- {
588- numIndirect = 1;
589- numIndirectOp = numTexop;
590- }
591- else
592- {
593- i = MAX (((maxTemp / 2) - 4) / 4, 1);
594- numIndirect = ceil ((float)numTexop / (float)i);
595- numIndirectOp = ceil ((float)numTexop / (float)numIndirect);
596- }
597-
598- /* we need to define all coordinate temporaries if we have
599- multiple indirection steps */
600- j = (numIndirect > 1) ? 0 : numITC;
601-
602- for (i = 0; i < numIndirectOp * 2; i++)
603- {
604- snprintf (str, 1024, "pix_%d", i);
605- data.addTempHeaderOp (str);
606- }
607-
608- for (i = j * 2; i < numIndirectOp * 2; i++)
609- {
610- snprintf (str, 1024, "coord_%d", i);
611- data.addTempHeaderOp (str);
612- }
613-
614- data.addFetchOp ("output", NULL, target);
615- data.addColorOp ("output", "output");
616-
617- data.addDataOp (
618- "MUL fCoord, fragment.position, program.env[%d];",
619- param);
620-
621-
622- data.addDataOp ("TEX sum, fCoord, texture[%d], %s;",
623- unit + 1, targetString);
624-
625-
626- data.addDataOp ("MUL_SAT mask, output.a, program.env[%d];"
627- "MUL sum, sum, %f;",
628- param + 1, amp[numTexop]);
629-
630- for (j = 0; j < numIndirect; j++)
631- {
632- base = j * numIndirectOp;
633- end = MIN ((j + 1) * numIndirectOp, numTexop) - base;
634-
635- ITCbase = MAX (numITC - base, 0);
636-
637- for (i = ITCbase; i < end; i++)
638- {
639- data.addDataOp (
640- "ADD coord_%d, fCoord, {0.0, %g, 0.0, 0.0};"
641- "SUB coord_%d, fCoord, {0.0, %g, 0.0, 0.0};",
642- i * 2, pos[base + i] * ty,
643- (i * 2) + 1, pos[base + i] * ty);
644- }
645-
646- for (i = 0; i < ITCbase; i++)
647- {
648- data.addDataOp (
649- "TXP pix_%d, fragment.texcoord[%d], texture[%d], %s;"
650- "TXP pix_%d, fragment.texcoord[%d], texture[%d], %s;",
651- i * 2, startTC + ((i + base) * 2),
652- unit + 1, targetString,
653- (i * 2) + 1, startTC + 1 + ((i + base) * 2),
654- unit + 1, targetString);
655- }
656-
657- for (i = ITCbase; i < end; i++)
658- {
659- data.addDataOp (
660- "TEX pix_%d, coord_%d, texture[%d], %s;"
661- "TEX pix_%d, coord_%d, texture[%d], %s;",
662- i * 2, i * 2,
663- unit + 1, targetString,
664- (i * 2) + 1, (i * 2) + 1,
665- unit + 1, targetString);
666- }
667-
668- for (i = 0; i < end * 2; i++)
669- {
670- data.addDataOp (
671- "MAD sum, pix_%d, %f, sum;",
672- i, amp[base + (i / 2)]);
673- }
674- }
675-
676- } break;
677- case BlurOptions::FilterMipmap:
678- data.addFetchOp ("output", NULL, target);
679- data.addColorOp ("output", "output");
680-
681- data.addDataOp (
682- "MUL fCoord, fragment.position, program.env[%d].xyzz;"
683- "MOV fCoord.w, program.env[%d].w;"
684- "TXB sum, fCoord, texture[%d], %s;"
685- "MUL_SAT mask, output.a, program.env[%d];",
686- param, param, unit, targetString,
687- param + 1);
688-
689- break;
690- }
691-
692- if (saturation < 100)
693- {
694- data.addDataOp (
695- "MUL sat, sum, { 1.0, 1.0, 1.0, 0.0 };"
696- "DP3 sat, sat, { %f, %f, %f, %f };"
697- "LRP sum.xyz, %f, sum, sat;",
698- RED_SATURATION_WEIGHT, GREEN_SATURATION_WEIGHT,
699- BLUE_SATURATION_WEIGHT, 0.0f, saturation / 100.0f);
700- }
701-
702- data.addDataOp (
703- "MAD dst, mask, -output.a, mask;"
704- "MAD output.rgb, sum, dst.a, output;"
705- "ADD output.a, output.a, dst.a;");
706-
707- if (!data.status ())
708- {
709- return 0;
710- }
711-
712-
713-
714- function.id = data.createFragmentFunction ("blur");
715- function.target = target;
716- function.param = param;
717- function.unit = unit;
718- function.numITC = numITC;
719- function.startTC = startTC;
720-
721- dstBlurFunctions.push_back (function);
722-
723- return function.id;
724- }
725-
726- return 0;
727+ function.startTC == startTC &&
728+ function.saturation == saturation)
729+ return function.shader;
730+
731+ data << "uniform vec4 blur_translation;\n"\
732+ "uniform vec4 blur_threshold;\n";
733+
734+ int i, j;
735+ /* These are always initialized if running a gaussian shader */
736+ int numIndirect = 0;
737+ int numIndirectOp = 0;
738+ int base, end, ITCbase;
739+
740+ /* Set per-shader uniforms */
741+ switch (optionGetFilter ())
742+ {
743+ case BlurOptions::Filter4xbilinear:
744+ data << "uniform vec4 blur_dxdy;\n";
745+ break;
746+ default:
747+ break;
748+ }
749+
750+ data << "\n"\
751+ "void blur_fragment ()\n"\
752+ "{\n"\
753+ " vec4 blur_sum, blur_dst, blur_output;\n"\
754+ " vec2 blur_fCoord;\n"\
755+ " vec4 blur_mask;\n";
756+
757+ if (saturation < 100)
758+ data << " float blur_sat;\n";
759+
760+ /* Define per-filter temporaries */
761+ switch (optionGetFilter ())
762+ {
763+ case BlurOptions::Filter4xbilinear:
764+ {
765+ static const char *filterTemp[] = {
766+ "blur_t0", "blur_t1", "blur_t2", "blur_t3",
767+ };
768+
769+ static const char *filterSampleTemp[] = {
770+ "blur_s0", "blur_s1", "blur_s2", "blur_s3"
771+ };
772+
773+ for (i = 0;
774+ (unsigned int) i < sizeof (filterTemp) / sizeof (filterTemp[0]);
775+ ++i)
776+ data << " vec2 " << filterTemp[i] << ";\n";
777+
778+ for (i = 0;
779+ (unsigned int) i < sizeof (filterSampleTemp) / sizeof (filterSampleTemp[0]);
780+ ++i)
781+ data << " vec4 " << filterSampleTemp[i] << ";\n";
782+ }
783+ break;
784+ case BlurOptions::FilterGaussian:
785+ {
786+ /* try to use only half of the available temporaries to keep
787+ other plugins working */
788+ if ((maxTemp / 2) - 4 >
789+ (numTexop + (numTexop - numITC)) * 2)
790+ {
791+ numIndirect = 1;
792+ numIndirectOp = numTexop;
793+ }
794+ else
795+ {
796+ i = MAX (((maxTemp / 2) - 4) / 4, 1);
797+ numIndirect = ceil ((float)numTexop / (float)i);
798+ numIndirectOp = ceil ((float)numTexop / (float)numIndirect);
799+ }
800+
801+ /* we need to define all coordinate temporaries if we have
802+ multiple indirection steps */
803+ j = (numIndirect > 1) ? 0 : numITC;
804+
805+ for (i = 0; i < numIndirectOp * 2; i++)
806+ data << " vec4 blur_pix_" << i << ";\n";
807+
808+ for (i = j * 2; i < numIndirectOp * 2; i++)
809+ data << " vec2 blur_coord_" << i << ";\n";
810+ }
811+ break;
812+ case BlurOptions::FilterMipmap:
813+ {
814+ data << " float lod_bias;\n";
815+ }
816+ default:
817+ break;
818+ }
819+
820+ /*
821+ * blur_output: copy the original gl_FragColor determined by sampling
822+ * the window texture in the core shader
823+ * blur_fCoord: take the fragment co-ordinate in window co-ordinates
824+ * and normalize it (eg, blur_translation). Once normalized we can
825+ * sample texUnitN + 1 (for the copy of the backbuffer we wish to blur)
826+ * and texUnitN + 2 (scratch fbo for gaussian blurs)
827+ * blur_mask: take blur_output pixel alpha value, multiply by threshold value
828+ * and clamp between 0 - 1. We will use this later to mix the blur fragments
829+ * with the window fragments.
830+ */
831+ data << "\n"\
832+ " blur_output = gl_FragColor;\n"\
833+ " blur_fCoord = gl_FragCoord.st * blur_translation.st;\n"\
834+ " blur_mask = clamp (blur_output.a * blur_threshold, vec4 (0.0, 0.0, 0.0, 0.), vec4 (1.0, 1.0, 1.0, 1.0));\n"\
835+ "\n";
836+
837+ /* Define filter program */
838+ switch (optionGetFilter ())
839+ {
840+ case BlurOptions::Filter4xbilinear:
841+ {
842+ data << " blur_t0 = blur_fCoord + blur_dxdy.st;\n"\
843+ " blur_s0 = " << info.func << " (texture1, blur_t0);\n"\
844+ " blur_t1 = blur_fCoord - blur_dxdy.st;\n"\
845+ " blur_s1 = " << info.func << " (texture1, blur_t1);\n"\
846+ " blur_t2 = blur_fCoord + vec2 (-1.0, 1.0) * blur_dxdy.st;\n"\
847+ " blur_s2 = " << info.func << " (texture1, blur_t2);\n"\
848+ " blur_t3 = blur_fCoord + vec2 (1.0, -1.0) * blur_dxdy.st;\n"\
849+ " blur_s3 = " << info.func << " (texture1, blur_t3);\n"\
850+ " blur_sum = blur_s0 * 0.25;\n"\
851+ " blur_sum += blur_s1 * 0.25;\n"\
852+ " blur_sum += blur_s2 * 0.25;\n"\
853+ " blur_sum += blur_s3 * 0.25;\n";
854+ } break;
855+ case BlurOptions::FilterGaussian:
856+ {
857+ /* Invert y */
858+ data << " blur_fCoord.y = 1.0 - blur_fCoord.y;\n"\
859+ " blur_sum = " << info.func << " (texture2, blur_fCoord);\n"\
860+ " blur_sum *= " << amp[numTexop] << ";\n";
861+
862+ for (j = 0; j < numIndirect; j++)
863+ {
864+ base = j * numIndirectOp;
865+ end = MIN ((j + 1) * numIndirectOp, numTexop) - base;
866+
867+ ITCbase = MAX (numITC - base, 0);
868+
869+ for (i = ITCbase; i < end; i++)
870+ {
871+ data << " blur_coord_" << i * 2 << " = blur_fCoord + vec2 (0.0, " << pos[base + i] * ty << ");\n"\
872+ " blur_coord_" << (i * 2) + 1 << " = blur_fCoord - vec2 (0.0, " << pos[base + i] * ty << ");\n";
873+ }
874+#if INDEPENDENT_TEX_SUPPORTED
875+ for (i = 0; i < ITCbase; i++)
876+ {
877+ data << " blur_pix_" + i * 2 + " vTexCoord"
878+ data.addDataOp (
879+ "TXP pix_%d, fragment.texcoord[%d], texture[%d], %s;"
880+ "TXP pix_%d, fragment.texcoord[%d], texture[%d], %s;",
881+ i * 2, startTC + ((i + base) * 2),
882+ unit + 1, targetString,
883+ (i * 2) + 1, startTC + 1 + ((i + base) * 2),
884+ unit + 1, targetString);
885+ }
886+#endif
887+ for (i = ITCbase; i < end; i++)
888+ {
889+ data << " blur_pix_" << i * 2 << " = " << info.func << " (texture2, blur_coord_" << i * 2 << ");\n"\
890+ " blur_pix_" << (i * 2) + 1 << " = " << info.func << " (texture2, blur_coord_" << (i * 2) + 1 << ");\n";
891+ }
892+
893+ for (i = 0; i < end * 2; i++)
894+ data << " blur_sum += blur_pix_" << i << " * " << amp[base + (i / 2)] << ";\n";
895+ }
896+
897+ } break;
898+ case BlurOptions::FilterMipmap:
899+ data << " lod_bias = blur_translation.w;\n"\
900+ " blur_sum = " << info.func << " (texture1, blur_fCoord, lod_bias);\n";
901+
902+ break;
903+ }
904+
905+ if (saturation < 100)
906+ {
907+ data << " blur_sat = blur_sum * vec4 (1.0, 1.0, 1.0, 0.0);\n"\
908+ " blur_sat = dot (blur_sat, vec4 (" <<
909+ RED_SATURATION_WEIGHT << ", " << GREEN_SATURATION_WEIGHT << ", " <<
910+ BLUE_SATURATION_WEIGHT << ", 0.0f);\n"\
911+ " blur_sum.xyz = mix (" << saturation / 100.f << ", blur_sat);\n";
912+ }
913+
914+ data << " blur_dst = (blur_mask * -blur_output.a) + blur_mask;\n"\
915+ " blur_output.rgb = blur_sum.rgb * blur_dst.a + blur_output.rgb;\n"\
916+ " blur_output.a += blur_dst.a;\n"\
917+ " gl_FragColor = blur_output;\n"\
918+ "}";
919+
920+ function.shader = data.str ();
921+ function.target = texture->target ();
922+ function.numITC = numITC;
923+ function.startTC = startTC;
924+ function.saturation = saturation;
925+
926+ dstBlurFunctions.push_back (function);
927+
928+ return dstBlurFunctions.back ().shader;
929+}
930+
931+namespace
932+{
933+bool
934+project (float objx, float objy, float objz,
935+ const float modelview[16], const float projection[16],
936+ const GLint viewport[4],
937+ float *winx, float *winy, float *winz)
938+{
939+ unsigned int i;
940+ float in[4];
941+ float out[4];
942+
943+ in[0] = objx;
944+ in[1] = objy;
945+ in[2] = objz;
946+ in[3] = 1.0;
947+
948+ for (i = 0; i < 4; i++) {
949+ out[i] =
950+ in[0] * modelview[i] +
951+ in[1] * modelview[4 + i] +
952+ in[2] * modelview[8 + i] +
953+ in[3] * modelview[12 + i];
954+ }
955+
956+ for (i = 0; i < 4; i++) {
957+ in[i] =
958+ out[0] * projection[i] +
959+ out[1] * projection[4 + i] +
960+ out[2] * projection[8 + i] +
961+ out[3] * projection[12 + i];
962+ }
963+
964+ if (in[3] == 0.0)
965+ return false;
966+
967+ in[0] /= in[3];
968+ in[1] /= in[3];
969+ in[2] /= in[3];
970+ /* Map x, y and z to range 0-1 */
971+ in[0] = in[0] * 0.5 + 0.5;
972+ in[1] = in[1] * 0.5 + 0.5;
973+ in[2] = in[2] * 0.5 + 0.5;
974+
975+ /* Map x,y to viewport */
976+ in[0] = in[0] * viewport[2] + viewport[0];
977+ in[1] = in[1] * viewport[3] + viewport[1];
978+
979+ *winx = in[0];
980+ *winy = in[1];
981+ *winz = in[2];
982+ return true;
983+}
984 }
985
986 bool
987@@ -874,11 +958,11 @@
988 float *scr,
989 int n)
990 {
991- GLdouble dProjection[16];
992- GLdouble dModel[16];
993- GLint viewport[4];
994- double x, y, z;
995- int i;
996+ GLfloat dProjection[16];
997+ GLfloat dModel[16];
998+ GLint viewport[4];
999+ float x, y, z;
1000+ int i;
1001
1002 viewport[0] = output->x1 ();
1003 viewport[1] = screen->height () - output->y2 ();
1004@@ -888,14 +972,14 @@
1005 for (i = 0; i < 16; i++)
1006 {
1007 dModel[i] = transform.getMatrix ()[i];
1008- dProjection[i] = gScreen->projectionMatrix ()[i];
1009+ dProjection[i] = gScreen->projectionMatrix ()->getMatrix ()[i];
1010 }
1011
1012 while (n--)
1013 {
1014- if (!gluProject (object[0], object[1], object[2],
1015- dModel, dProjection, viewport,
1016- &x, &y, &z))
1017+ if (!project (object[0], object[1], object[2],
1018+ dModel, dProjection, viewport,
1019+ &x, &y, &z))
1020 return false;
1021
1022 scr[0] = x;
1023@@ -909,57 +993,56 @@
1024 }
1025
1026 bool
1027-BlurScreen::loadFragmentProgram (GLuint *program,
1028- const char *string)
1029+BlurScreen::loadFragmentProgram (boost::shared_ptr <GLProgram> &program,
1030+ const char *vertex,
1031+ const char *fragment)
1032 {
1033- GLint errorPos;
1034-
1035- /* clear errors */
1036- glGetError ();
1037-
1038- if (!*program)
1039- (*GL::genPrograms) (1, program);
1040-
1041- (*GL::bindProgram) (GL_FRAGMENT_PROGRAM_ARB, *program);
1042- (*GL::programString) (GL_FRAGMENT_PROGRAM_ARB,
1043- GL_PROGRAM_FORMAT_ASCII_ARB,
1044- strlen (string), string);
1045-
1046- glGetIntegerv (GL_PROGRAM_ERROR_POSITION_ARB, &errorPos);
1047- if (glGetError () != GL_NO_ERROR || errorPos != -1)
1048+ if (!program)
1049+ program.reset (new GLProgram (CompString (vertex),
1050+ CompString (fragment)));
1051+
1052+ if (program && program->valid ())
1053+ return true;
1054+ else
1055 {
1056+ program.reset ();
1057 compLogMessage ("blur", CompLogLevelError,
1058- "Failed to load blur program %s", string);
1059-
1060- (*GL::deletePrograms) (1, program);
1061- *program = 0;
1062-
1063+ "Failed to load blur program %s", fragment);
1064 return false;
1065 }
1066-
1067- return true;
1068 }
1069
1070 bool
1071 BlurScreen::loadFilterProgram (int numITC)
1072 {
1073- char buffer[4096];
1074- char *targetString;
1075- char *str = buffer;
1076+ std::stringstream svtx;
1077+
1078+ /* A simple pass-thru vertex shader */
1079+ svtx << "#ifdef GL_ES\n"\
1080+ "precision mediump float;\n"\
1081+ "#endif\n"\
1082+ "uniform mat4 modelview;\n"\
1083+ "uniform mat4 projection;\n"\
1084+ "attribute vec4 position;\n"\
1085+ "attribute vec2 texCoord0;\n"\
1086+ "varying vec2 vTexCoord0;\n"\
1087+ "\n"\
1088+ "void main ()\n"\
1089+ "{\n"\
1090+ " vTexCoord0 = texCoord0;\n"\
1091+ " gl_Position = projection * modelview * position;\n"\
1092+ "}";
1093+
1094+ std::stringstream str;
1095 int i, j;
1096 int numIndirect;
1097 int numIndirectOp;
1098 int base, end, ITCbase;
1099
1100- if (target == GL_TEXTURE_2D)
1101- targetString = (char *) "2D";
1102- else
1103- targetString = (char *) "RECT";
1104+ SamplerInfo info (getSamplerInfoForSize (*screen));
1105
1106- str += sprintf (str,
1107- "!!ARBfp1.0"
1108- "ATTRIB texcoord = fragment.texcoord[0];"
1109- "TEMP sum;");
1110+ str << "varying vec2 vTexCoord0;\n"\
1111+ "uniform sampler2D texture0;\n";
1112
1113 if (maxTemp - 1 > (numTexop + (numTexop - numITC)) * 2)
1114 {
1115@@ -977,19 +1060,19 @@
1116 multiple indirection steps */
1117 j = (numIndirect > 1) ? 0 : numITC;
1118
1119+ str << "\n"\
1120+ "void main ()\n"\
1121+ "{\n";
1122+
1123 for (i = 0; i < numIndirectOp; i++)
1124- str += sprintf (str,"TEMP pix_%d, pix_%d;", i * 2, (i * 2) + 1);
1125+ str << " vec4 blur_pix_" << i * 2 << ", blur_pix_" << (i * 2) + 1 << ";\n";
1126
1127 for (i = j; i < numIndirectOp; i++)
1128- str += sprintf (str,"TEMP coord_%d, coord_%d;", i * 2, (i * 2) + 1);
1129-
1130- str += sprintf (str,
1131- "TEX sum, texcoord, texture[0], %s;",
1132- targetString);
1133-
1134- str += sprintf (str,
1135- "MUL sum, sum, %f;",
1136- amp[numTexop]);
1137+ str << " vec2 blur_coord_" << i * 2 << ", blur_coord_" << (i * 2) + 1 << ";\n";
1138+
1139+ str << " vec4 blur_sum;\n";
1140+ str << " blur_sum = " << info.func << " (texture0, vTexCoord0);\n"\
1141+ " blur_sum = blur_sum * " << amp[numTexop] << ";\n";
1142
1143 for (j = 0; j < numIndirect; j++)
1144 {
1145@@ -999,37 +1082,30 @@
1146 ITCbase = MAX (numITC - base, 0);
1147
1148 for (i = ITCbase; i < end; i++)
1149- str += sprintf (str,
1150- "ADD coord_%d, texcoord, {%g, 0.0, 0.0, 0.0};"
1151- "SUB coord_%d, texcoord, {%g, 0.0, 0.0, 0.0};",
1152- i * 2, pos[base + i] * tx,
1153- (i * 2) + 1, pos[base + i] * tx);
1154-
1155+ str << " blur_coord_" << i * 2 << " = vTexCoord0 + vec2 (" << pos[base + i] * tx << ", 0.0);\n"\
1156+ " blur_coord_" << (i * 2) + 1 << " = vTexCoord0 - vec2 (" << pos[base + i] * tx << ", 0.0);\n";
1157+#if INDEPENDENT_TEX_SUPPORTED
1158 for (i = 0; i < ITCbase; i++)
1159- str += sprintf (str,
1160+ str << sprintf (str,
1161 "TEX pix_%d, fragment.texcoord[%d], texture[0], %s;"
1162 "TEX pix_%d, fragment.texcoord[%d], texture[0], %s;",
1163 i * 2, ((i + base) * 2) + 1, targetString,
1164 (i * 2) + 1, ((i + base) * 2) + 2, targetString);
1165-
1166+#endif
1167 for (i = ITCbase; i < end; i++)
1168- str += sprintf (str,
1169- "TEX pix_%d, coord_%d, texture[0], %s;"
1170- "TEX pix_%d, coord_%d, texture[0], %s;",
1171- i * 2, i * 2, targetString,
1172- (i * 2) + 1, (i * 2) + 1, targetString);
1173+ str << " blur_pix_" << (i * 2) << " = " << info.func << " (texture0, blur_coord_" << i * 2 << ");\n"\
1174+ " blur_pix_" << (i * 2) + 1 << " = " << info.func << " (texture0, blur_coord_" << (i * 2) + 1 << ");\n";
1175
1176 for (i = 0; i < end * 2; i++)
1177- str += sprintf (str,
1178- "MAD sum, pix_%d, %f, sum;",
1179- i, amp[base + (i / 2)]);
1180+ str << " blur_sum += blur_pix_" << i << " * " << amp[base + (i / 2)] << ";\n";
1181 }
1182
1183- str += sprintf (str,
1184- "MOV result.color, sum;"
1185- "END");
1186+ str << " gl_FragColor = blur_sum;\n"\
1187+ "}";
1188
1189- return loadFragmentProgram (&program, buffer);
1190+ return loadFragmentProgram (program,
1191+ svtx.str ().c_str (),
1192+ str.str ().c_str ());
1193 }
1194
1195 bool
1196@@ -1038,51 +1114,7 @@
1197 if (!fbo)
1198 return false;
1199
1200- (*GL::bindFramebuffer) (GL_FRAMEBUFFER_EXT, fbo);
1201-
1202- /* bind texture and check status the first time */
1203- if (!fboStatus)
1204- {
1205- (*GL::framebufferTexture2D) (GL_FRAMEBUFFER_EXT,
1206- GL_COLOR_ATTACHMENT0_EXT,
1207- target, texture[1],
1208- 0);
1209-
1210- int currStatus = (*GL::checkFramebufferStatus) (GL_FRAMEBUFFER_EXT);
1211- if (currStatus != GL_FRAMEBUFFER_COMPLETE_EXT)
1212- {
1213- compLogMessage ("blur", CompLogLevelError,
1214- "Framebuffer incomplete");
1215-
1216- (*GL::bindFramebuffer) (GL_FRAMEBUFFER_EXT, 0);
1217- (*GL::deleteFramebuffers) (1, &fbo);
1218-
1219- fbo = 0;
1220-
1221- return false;
1222- }
1223- else
1224- fboStatus = true;
1225- }
1226-
1227- glPushAttrib (GL_VIEWPORT_BIT | GL_ENABLE_BIT);
1228-
1229- glDrawBuffer (GL_COLOR_ATTACHMENT0_EXT);
1230- glReadBuffer (GL_COLOR_ATTACHMENT0_EXT);
1231-
1232- glDisable (GL_CLIP_PLANE0);
1233- glDisable (GL_CLIP_PLANE1);
1234- glDisable (GL_CLIP_PLANE2);
1235- glDisable (GL_CLIP_PLANE3);
1236-
1237- glViewport (0, 0, width, height);
1238- glMatrixMode (GL_PROJECTION);
1239- glPushMatrix ();
1240- glLoadIdentity ();
1241- glOrtho (0.0, width, 0.0, height, -1.0, 1.0);
1242- glMatrixMode (GL_MODELVIEW);
1243- glPushMatrix ();
1244- glLoadIdentity ();
1245+ oldDrawFramebuffer = fbo->bind ();
1246
1247 return true;
1248 }
1249@@ -1090,37 +1122,22 @@
1250 void
1251 BlurScreen::fboEpilogue ()
1252 {
1253- (*GL::bindFramebuffer) (GL_FRAMEBUFFER_EXT, 0);
1254-
1255- glMatrixMode (GL_PROJECTION);
1256- glLoadIdentity ();
1257- glMatrixMode (GL_MODELVIEW);
1258- glLoadIdentity ();
1259- glDepthRange (0, 1);
1260- glViewport (-1, -1, 2, 2);
1261- glRasterPos2f (0, 0);
1262-
1263- gScreen->resetRasterPos ();
1264-
1265- glMatrixMode (GL_PROJECTION);
1266- glPopMatrix ();
1267- glMatrixMode (GL_MODELVIEW);
1268- glPopMatrix ();
1269-
1270- glDrawBuffer (GL_BACK);
1271- glReadBuffer (GL_BACK);
1272-
1273- glPopAttrib ();
1274+ oldDrawFramebuffer->bind ();
1275+
1276+ fbo->tex ()->enable (GLTexture::Good);
1277+ //GL::generateMipmap (fbo->tex ()->target ());
1278+
1279+ fbo->tex ()->disable ();
1280 }
1281
1282 bool
1283 BlurScreen::fboUpdate (BoxPtr pBox,
1284 int nBox)
1285 {
1286- int i, y, iTC = 0;
1287+ float iTC = 0;
1288 bool wasCulled = glIsEnabled (GL_CULL_FACE);
1289
1290- if (GL::maxTextureUnits && optionGetIndependentTex ())
1291+ if (GL::maxTextureUnits && optionGetIndependentTex () && false)
1292 iTC = MIN ((GL::maxTextureUnits - 1) / 2, numTexop);
1293
1294 if (!program)
1295@@ -1131,83 +1148,51 @@
1296 return false;
1297
1298 glDisable (GL_CULL_FACE);
1299-
1300- glDisableClientState (GL_TEXTURE_COORD_ARRAY);
1301-
1302- glBindTexture (target, texture[0]);
1303-
1304- glEnable (GL_FRAGMENT_PROGRAM_ARB);
1305- (*GL::bindProgram) (GL_FRAGMENT_PROGRAM_ARB, program);
1306-
1307- glBegin (GL_QUADS);
1308+ GL::activeTexture (GL_TEXTURE0);
1309+ texture[0]->enable (GLTexture::Good);
1310+
1311+ GLVertexBuffer *streamingBuffer = GLVertexBuffer::streamingBuffer ();
1312
1313 while (nBox--)
1314 {
1315- y = screen->height () - pBox->y2;
1316-
1317- for (i = 0; i < iTC; i++)
1318- {
1319- (*GL::multiTexCoord2f) (GL_TEXTURE1_ARB + (i * 2),
1320- tx * (pBox->x1 + pos[i]),
1321- ty * y);
1322- (*GL::multiTexCoord2f) (GL_TEXTURE1_ARB + (i * 2) + 1,
1323- tx * (pBox->x1 - pos[i]),
1324- ty * y);
1325- }
1326-
1327- glTexCoord2f (tx * pBox->x1, ty * y);
1328- glVertex2i (pBox->x1, y);
1329-
1330- for (i = 0; i < iTC; i++)
1331- {
1332- (*GL::multiTexCoord2f) (GL_TEXTURE1_ARB + (i * 2),
1333- tx * (pBox->x2 + pos[i]),
1334- ty * y);
1335- (*GL::multiTexCoord2f) (GL_TEXTURE1_ARB + (i * 2) + 1,
1336- tx * (pBox->x2 - pos[i]),
1337- ty * y);
1338- }
1339-
1340- glTexCoord2f (tx * pBox->x2, ty * y);
1341- glVertex2i (pBox->x2, y);
1342-
1343- y = screen->height () - pBox->y1;
1344-
1345- for (i = 0; i < iTC; i++)
1346- {
1347- (*GL::multiTexCoord2f) (GL_TEXTURE1_ARB + (i * 2),
1348- tx * (pBox->x2 + pos[i]),
1349- ty * y);
1350- (*GL::multiTexCoord2f) (GL_TEXTURE1_ARB + (i * 2) + 1,
1351- tx * (pBox->x2 - pos[i]),
1352- ty * y);
1353- }
1354-
1355- glTexCoord2f (tx * pBox->x2, ty * y);
1356- glVertex2i (pBox->x2, y);
1357-
1358- for (i = 0; i < iTC; i++)
1359- {
1360- (*GL::multiTexCoord2f) (GL_TEXTURE1_ARB + (i * 2),
1361- tx * (pBox->x1 + pos[i]),
1362- ty * y);
1363- (*GL::multiTexCoord2f) (GL_TEXTURE1_ARB + (i * 2) + 1,
1364- tx * (pBox->x1 - pos[i]),
1365- ty * y);
1366- }
1367-
1368- glTexCoord2f (tx * pBox->x1, ty * y);
1369- glVertex2i (pBox->x1, y);
1370+ float x1 = pBox->x1;
1371+ float x2 = pBox->x2;
1372+ float y1 = screen->height () - pBox->y2;
1373+ float y2 = screen->height () - pBox->y1;
1374+
1375+ GLfloat texCoords[] =
1376+ {
1377+ tx * x1, ty * y1,
1378+ tx * x1, ty * y2,
1379+ tx * x2, ty * y1,
1380+ tx * x2, ty * y2
1381+ };
1382+
1383+ GLfloat vertices[] =
1384+ {
1385+ x1, y1, 0,
1386+ x1, y2, 0,
1387+ x2, y1, 0,
1388+ x2, y2, 0
1389+ };
1390+
1391+ GLMatrix mv;
1392+ mv.toScreenSpace (output, -DEFAULT_Z_CAMERA);
1393+
1394+ streamingBuffer->begin (GL_TRIANGLE_STRIP);
1395+ streamingBuffer->setProgram (program.get ());
1396+ streamingBuffer->addTexCoords (0, 4, texCoords);
1397+ streamingBuffer->addVertices (4, vertices);
1398+
1399+ if (streamingBuffer->end ())
1400+ streamingBuffer->render (mv);
1401+
1402+ /* Unset program */
1403+ streamingBuffer->setProgram (NULL);
1404
1405 pBox++;
1406 }
1407
1408- glEnd ();
1409-
1410- glDisable (GL_FRAGMENT_PROGRAM_ARB);
1411-
1412- glEnableClientState (GL_TEXTURE_COORD_ARRAY);
1413-
1414 if (wasCulled)
1415 glEnable (GL_CULL_FACE);
1416
1417@@ -1231,92 +1216,70 @@
1418 float *scr;
1419
1420 GLTexture::MatrixList ml;
1421- GLWindow::Geometry *gm;
1422
1423- gWindow->geometry ().reset ();
1424+ gWindow->vertexBuffer ()->begin ();
1425 gWindow->glAddGeometry (ml, bScreen->tmpRegion2, infiniteRegion);
1426
1427- if (!gWindow->geometry ().vCount)
1428+ if (!gWindow->vertexBuffer ()->end ())
1429 return;
1430
1431- gm = &gWindow->geometry ();
1432+ GLVertexBuffer *vb = gWindow->vertexBuffer ();
1433
1434- nVertices = (gm->indexCount) ? gm->indexCount: gm->vCount;
1435+ nVertices = vb->countVertices ();
1436 nQuadCombine = 1;
1437
1438- stride = gm->vertexStride;
1439- vert = gm->vertices + (stride - 3);
1440-
1441- /* we need to find the best value here */
1442- if (nVertices <= MAX_VERTEX_PROJECT_COUNT)
1443+ stride = vb->getVertexStride ();
1444+ vert = vb->getVertices () + (stride - 3);
1445+
1446+ /* construct quads from bounding vertices */
1447+ minX = screen->width ();
1448+ maxX = 0;
1449+ minY = screen->height ();
1450+ maxY = 0;
1451+ minZ = 1000000;
1452+ maxZ = -1000000;
1453+
1454+ for (i = 0; i < vb->countVertices (); i++)
1455 {
1456- for (i = 0; i < nVertices; i++)
1457- {
1458- if (gm->indexCount)
1459- {
1460- v = vert + (stride * gm->indices[i]);
1461- }
1462- else
1463- {
1464- v = vert + (stride * i);
1465- }
1466-
1467- vertices[i * 3] = v[0];
1468- vertices[(i * 3) + 1] = v[1];
1469- vertices[(i * 3) + 2] = v[2];
1470- }
1471+ v = vert + (stride * i);
1472+
1473+ if (v[0] < minX)
1474+ minX = v[0];
1475+
1476+ if (v[0] > maxX)
1477+ maxX = v[0];
1478+
1479+ if (v[1] < minY)
1480+ minY = v[1];
1481+
1482+ if (v[1] > maxY)
1483+ maxY = v[1];
1484+
1485+ if (v[2] < minZ)
1486+ minZ = v[2];
1487+
1488+ if (v[2] > maxZ)
1489+ maxZ = v[2];
1490 }
1491- else
1492+
1493+ vertices[0] = vertices[9] = minX;
1494+ vertices[1] = vertices[4] = minY;
1495+ vertices[3] = vertices[6] = maxX;
1496+ vertices[7] = vertices[10] = maxY;
1497+ vertices[2] = vertices[5] = maxZ;
1498+ vertices[8] = vertices[11] = maxZ;
1499+
1500+ nVertices = 4;
1501+
1502+ if (maxZ != minZ)
1503 {
1504- minX = screen->width ();
1505- maxX = 0;
1506- minY = screen->height ();
1507- maxY = 0;
1508- minZ = 1000000;
1509- maxZ = -1000000;
1510-
1511- for (i = 0; i < gm->vCount; i++)
1512- {
1513- v = vert + (stride * i);
1514-
1515- if (v[0] < minX)
1516- minX = v[0];
1517-
1518- if (v[0] > maxX)
1519- maxX = v[0];
1520-
1521- if (v[1] < minY)
1522- minY = v[1];
1523-
1524- if (v[1] > maxY)
1525- maxY = v[1];
1526-
1527- if (v[2] < minZ)
1528- minZ = v[2];
1529-
1530- if (v[2] > maxZ)
1531- maxZ = v[2];
1532- }
1533-
1534- vertices[0] = vertices[9] = minX;
1535- vertices[1] = vertices[4] = minY;
1536- vertices[3] = vertices[6] = maxX;
1537- vertices[7] = vertices[10] = maxY;
1538- vertices[2] = vertices[5] = maxZ;
1539- vertices[8] = vertices[11] = maxZ;
1540-
1541- nVertices = 4;
1542-
1543- if (maxZ != minZ)
1544- {
1545- vertices[12] = vertices[21] = minX;
1546- vertices[13] = vertices[16] = minY;
1547- vertices[15] = vertices[18] = maxX;
1548- vertices[19] = vertices[22] = maxY;
1549- vertices[14] = vertices[17] = minZ;
1550- vertices[20] = vertices[23] = minZ;
1551- nQuadCombine = 2;
1552- }
1553+ vertices[12] = vertices[21] = minX;
1554+ vertices[13] = vertices[16] = minY;
1555+ vertices[15] = vertices[18] = maxX;
1556+ vertices[19] = vertices[22] = maxY;
1557+ vertices[14] = vertices[17] = minZ;
1558+ vertices[20] = vertices[23] = minZ;
1559+ nQuadCombine = 2;
1560 }
1561
1562 if (!bScreen->projectVertices (output, transform, vertices, scrv,
1563@@ -1349,10 +1312,10 @@
1564
1565 int x1, y1, x2, y2;
1566
1567- x1 = minX - bScreen->filterRadius;
1568- y1 = screen->height () - maxY - bScreen->filterRadius;
1569- x2 = maxX + bScreen->filterRadius + 0.5f;
1570- y2 = screen->height () - minY + bScreen->filterRadius + 0.5f;
1571+ x1 = minX - bScreen->filterRadius - 0.5;
1572+ y1 = screen->height () - maxY - bScreen->filterRadius - 0.5;
1573+ x2 = maxX + bScreen->filterRadius + 0.5;
1574+ y2 = screen->height () - minY + bScreen->filterRadius + 0.5;
1575
1576
1577 bScreen->tmpRegion3 += CompRect (x1, y1, x2 - x1, y2 - y1);
1578@@ -1360,21 +1323,15 @@
1579 }
1580 }
1581
1582-bool
1583-BlurWindow::updateDstTexture (const GLMatrix &transform,
1584- CompRect *pExtents,
1585- int clientThreshold)
1586+void
1587+BlurWindow::determineBlurRegion (int filter,
1588+ const GLMatrix &transform,
1589+ int clientThreshold)
1590 {
1591- int y;
1592- int filter;
1593-
1594- filter = bScreen->optionGetFilter ();
1595-
1596 bScreen->tmpRegion3 = CompRegion ();
1597
1598 if (filter == BlurOptions::FilterGaussian)
1599 {
1600-
1601 if (state[BLUR_STATE_DECOR].threshold)
1602 {
1603 int xx, yy, ww, hh;
1604@@ -1394,7 +1351,7 @@
1605 // bottom
1606 xx = window->x () - window->output ().left;
1607 yy = window->y () + window->height ();
1608- ww = window->width () + window->output ().left +
1609+ ww = window->width () + window->output ().left +
1610 window->output ().right;
1611 hh = window->output ().bottom;
1612
1613@@ -1410,7 +1367,7 @@
1614 ww = window->output ().left;
1615 hh = window->height ();
1616
1617- bScreen->tmpRegion2 = bScreen->tmpRegion.intersected (
1618+ bScreen->tmpRegion2 = bScreen->tmpRegion.intersected (
1619 CompRect (xx, yy, ww, hh));
1620
1621 if (!bScreen->tmpRegion2.isEmpty ())
1622@@ -1422,7 +1379,7 @@
1623 ww = window->output ().right;
1624 hh = window->height ();
1625
1626- bScreen->tmpRegion2 = bScreen->tmpRegion.intersected (
1627+ bScreen->tmpRegion2 = bScreen->tmpRegion.intersected (
1628 CompRect (xx, yy, ww, hh));
1629
1630 if (!bScreen->tmpRegion2.isEmpty ())
1631@@ -1451,141 +1408,147 @@
1632 projectRegion (bScreen->output, transform);
1633 }
1634
1635- bScreen->tmpRegion = bScreen->region.intersected (bScreen->tmpRegion3);
1636+ projectedBlurRegion = bScreen->tmpRegion3;
1637+}
1638+
1639+bool
1640+BlurWindow::updateDstTexture (const GLMatrix &transform,
1641+ CompRect *pExtents,
1642+ unsigned int mask)
1643+{
1644+ bool ret = false;
1645+ int filter = bScreen->optionGetFilter ();
1646+
1647+ /* Paint region n projected region */
1648+ bScreen->tmpRegion = bScreen->region.intersected (projectedBlurRegion);
1649+
1650+ if (!bScreen->blurOcclusion &&
1651+ !(mask & PAINT_WINDOW_TRANSFORMED_MASK))
1652+ bScreen->tmpRegion -= clip;
1653
1654 if (bScreen->tmpRegion.isEmpty ())
1655 return false;
1656
1657- *pExtents = bScreen->tmpRegion.boundingRect ();
1658+ CompRect br (bScreen->tmpRegion.boundingRect ());
1659
1660- if (!bScreen->texture[0] || bScreen->width != screen->width () ||
1661- bScreen->height != screen->height ())
1662+ if (bScreen->texture.empty () ||
1663+ CompSize (bScreen->texture[0]->width (),
1664+ bScreen->texture[0]->height ()) !=
1665+ static_cast <const CompSize &> (*screen))
1666 {
1667- int i, textures = 1;
1668-
1669- bScreen->width = screen->width ();
1670- bScreen->height = screen->height ();
1671-
1672- if (GL::textureNonPowerOfTwo ||
1673- (POWER_OF_TWO (bScreen->width) && POWER_OF_TWO (bScreen->height)))
1674+ bScreen->texture = GLTexture::imageDataToTexture (NULL,
1675+ *screen,
1676+ GL_RGB,
1677+#if IMAGE_BYTE_ORDER == MSBFirst
1678+ GL_UNSIGNED_INT_8_8_8_8_REV);
1679+#else
1680+ GL_UNSIGNED_BYTE);
1681+#endif
1682+
1683+ if (bScreen->texture[0]->target () == GL_TEXTURE_2D)
1684 {
1685- bScreen->target = GL_TEXTURE_2D;
1686- bScreen->tx = 1.0f / bScreen->width;
1687- bScreen->ty = 1.0f / bScreen->height;
1688+ bScreen->tx = 1.0f / bScreen->texture[0]->width ();
1689+ bScreen->ty = 1.0f / bScreen->texture[0]->height ();
1690 }
1691 else
1692 {
1693- bScreen->target = GL_TEXTURE_RECTANGLE_NV;
1694 bScreen->tx = 1;
1695 bScreen->ty = 1;
1696 }
1697
1698 if (filter == BlurOptions::FilterGaussian)
1699 {
1700- if (GL::fbo && !bScreen->fbo)
1701- (*GL::genFramebuffers) (1, &bScreen->fbo);
1702-
1703- if (!bScreen->fbo)
1704+ bScreen->fbo->allocate (*screen,
1705+ NULL,
1706+ GL_BGRA);
1707+
1708+ /* We have to bind it in order to get a status */
1709+ GLFramebufferObject *old = bScreen->fbo->bind();
1710+ bool status = bScreen->fbo->checkStatus ();
1711+ old->bind();
1712+
1713+ if (!status)
1714 compLogMessage ("blur", CompLogLevelError,
1715 "Failed to create framebuffer object");
1716
1717- textures = 2;
1718- }
1719-
1720- bScreen->fboStatus = false;
1721-
1722- for (i = 0; i < textures; i++)
1723- {
1724- if (!bScreen->texture[i])
1725- glGenTextures (1, &bScreen->texture[i]);
1726-
1727- glBindTexture (bScreen->target, bScreen->texture[i]);
1728-
1729- glTexImage2D (bScreen->target, 0, GL_RGB,
1730- bScreen->width,
1731- bScreen->height,
1732- 0, GL_BGRA,
1733-
1734-#if IMAGE_BYTE_ORDER == MSBFirst
1735- GL_UNSIGNED_INT_8_8_8_8_REV,
1736-#else
1737- GL_UNSIGNED_BYTE,
1738-#endif
1739-
1740- NULL);
1741-
1742- glTexParameteri (bScreen->target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
1743- glTexParameteri (bScreen->target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
1744-
1745- if (filter == BlurOptions::FilterMipmap)
1746+ else
1747 {
1748- if (!GL::fbo)
1749- {
1750- compLogMessage ("blur", CompLogLevelWarn,
1751- "GL_EXT_framebuffer_object extension "
1752- "is required for mipmap filter");
1753- }
1754- else if (bScreen->target != GL_TEXTURE_2D)
1755- {
1756- compLogMessage ("blur", CompLogLevelWarn,
1757- "GL_ARB_texture_non_power_of_two "
1758- "extension is required for mipmap filter");
1759- }
1760- else
1761- {
1762- glTexParameteri (bScreen->target, GL_TEXTURE_MIN_FILTER,
1763- GL_LINEAR_MIPMAP_LINEAR);
1764- glTexParameteri (bScreen->target, GL_TEXTURE_MAG_FILTER,
1765- GL_LINEAR_MIPMAP_LINEAR);
1766- }
1767+ unsigned int filter = (bScreen->gScreen->driverHasBrokenFBOMipmaps () ?
1768+ GL_LINEAR : GL_LINEAR_MIPMAP_LINEAR);
1769+ bScreen->gScreen->setTextureFilter (filter);
1770+
1771+ bScreen->fbo->tex ()->enable (GLTexture::Good);
1772+
1773+ const CompRect &r (*bScreen->fbo->tex ());
1774+
1775+ glCopyTexSubImage2D (bScreen->fbo->tex ()->target (),
1776+ 0, 0, 0, 0, 0,
1777+ r.width (),
1778+ r.height ());
1779+
1780+ if (!bScreen->gScreen->driverHasBrokenFBOMipmaps ())
1781+ GL::generateMipmap (bScreen->fbo->tex ()->target ());
1782+
1783+ bScreen->fbo->tex ()->disable ();
1784 }
1785-
1786- glTexParameteri (bScreen->target, GL_TEXTURE_WRAP_S,
1787- GL_CLAMP_TO_EDGE);
1788- glTexParameteri (bScreen->target, GL_TEXTURE_WRAP_T,
1789- GL_CLAMP_TO_EDGE);
1790-
1791- glCopyTexSubImage2D (bScreen->target, 0, 0, 0, 0, 0,
1792- bScreen->width, bScreen->height);
1793 }
1794+
1795+ /* Set update region to entire screen */
1796+ br.setGeometry (0, 0,
1797+ screen->width (),
1798+ screen->height ());
1799 }
1800- else
1801+
1802+ *pExtents = br;
1803+
1804+ CompRegion *updateRegion = NULL;
1805+ updateRegion = &bScreen->tmpRegion;
1806+
1807+ foreach (GLTexture *tex, bScreen->texture)
1808 {
1809- glBindTexture (bScreen->target, bScreen->texture[0]);
1810-
1811- CompRect br = bScreen->tmpRegion.boundingRect ();
1812-
1813- y = screen->height () - br.y2 ();
1814-
1815- glCopyTexSubImage2D (bScreen->target, 0,
1816- br.x1 (), y,
1817- br.x1 (), y,
1818- br.width (),
1819- br.height ());
1820- }
1821-
1822- switch (filter) {
1823- case BlurOptions::FilterGaussian:
1824- return bScreen->fboUpdate (bScreen->tmpRegion.handle ()->rects,
1825- bScreen->tmpRegion.numRects ());
1826- case BlurOptions::FilterMipmap:
1827- if (GL::generateMipmap)
1828- (*GL::generateMipmap) (bScreen->target);
1829- break;
1830- case BlurOptions::Filter4xbilinear:
1831- break;
1832- }
1833-
1834- glBindTexture (bScreen->target, 0);
1835-
1836- return true;
1837+ /* We need to set the active texture filter to GL_LINEAR_MIPMAP_LINEAR */
1838+ if (filter == BlurOptions::FilterMipmap &&
1839+ !bScreen->gScreen->driverHasBrokenFBOMipmaps ())
1840+ bScreen->gScreen->setTextureFilter (GL_LINEAR_MIPMAP_LINEAR);
1841+
1842+ tex->enable (GLTexture::Good);
1843+
1844+ CompRect::vector rects (updateRegion->rects ());
1845+
1846+ foreach (const CompRect &r, rects)
1847+ {
1848+ int y = screen->height () - r.y2 ();
1849+
1850+ glCopyTexSubImage2D (bScreen->texture[0]->target (), 0,
1851+ r.x1 (), y,
1852+ r.x1 (), y,
1853+ r.width (),
1854+ r.height ());
1855+ }
1856+
1857+ /* Force mipmap regeneration, because GLTexture assumes static
1858+ * textures and won't do it for us */
1859+ if (filter == BlurOptions::FilterMipmap &&
1860+ !bScreen->gScreen->driverHasBrokenFBOMipmaps ())
1861+ GL::generateMipmap (tex->target ());
1862+
1863+ if (filter == BlurOptions::FilterGaussian)
1864+ ret |= bScreen->fboUpdate (updateRegion->handle ()->rects,
1865+ updateRegion->numRects ());
1866+ else
1867+ ret = true;
1868+
1869+ tex->disable ();
1870+ }
1871+
1872+ return ret;
1873 }
1874
1875 bool
1876-BlurWindow::glDraw (const GLMatrix &transform,
1877- GLFragment::Attrib &attrib,
1878- const CompRegion &region,
1879- unsigned int mask)
1880+BlurWindow::glDraw (const GLMatrix &transform,
1881+ const GLWindowPaintAttrib &attrib,
1882+ const CompRegion &region,
1883+ unsigned int mask)
1884 {
1885 bool status;
1886
1887@@ -1603,22 +1566,11 @@
1888 {
1889 bool clipped = false;
1890 CompRect box (0, 0, 0, 0);
1891- CompRegion reg;
1892
1893- bScreen->mvp = GLMatrix (bScreen->gScreen->projectionMatrix ());
1894+ bScreen->mvp = *(bScreen->gScreen->projectionMatrix ());
1895 bScreen->mvp *= transform;
1896
1897- if (mask & PAINT_WINDOW_TRANSFORMED_MASK)
1898- reg = infiniteRegion;
1899- else
1900- reg = region;
1901-
1902- bScreen->tmpRegion = this->region.intersected (reg);
1903- if (!bScreen->blurOcclusion &&
1904- !(mask & PAINT_WINDOW_TRANSFORMED_MASK))
1905- bScreen->tmpRegion -= clip;
1906-
1907- if (updateDstTexture (transform, &box, clientThreshold))
1908+ if (updateDstTexture (transform, &box, mask))
1909 {
1910 if (clientThreshold)
1911 {
1912@@ -1672,11 +1624,17 @@
1913 if (clipped)
1914 {
1915 GLTexture::MatrixList ml;
1916-
1917- gWindow->geometry ().reset ();
1918-
1919- gWindow->glAddGeometry (ml, bScreen->tmpRegion, reg);
1920- if (gWindow->geometry ().vCount)
1921+ const CompRegion *reg = NULL;
1922+
1923+ if (mask & PAINT_WINDOW_TRANSFORMED_MASK)
1924+ reg = &infiniteRegion;
1925+ else
1926+ reg = &region;
1927+
1928+ gWindow->vertexBuffer ()->begin ();
1929+ gWindow->glAddGeometry (ml, bScreen->tmpRegion, *reg);
1930+ gWindow->vertexBuffer ()->color4f (1.0, 1.0, 1.0, 1.0);
1931+ if (gWindow->vertexBuffer ()->end ())
1932 {
1933 CompRect clearBox = bScreen->stencilBox;
1934
1935@@ -1684,28 +1642,44 @@
1936
1937 glEnable (GL_STENCIL_TEST);
1938 glColorMask (GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
1939+ glStencilMask (1);
1940
1941 if (clearBox.x2 () > clearBox.x1 () &&
1942 clearBox.y2 () > clearBox.y1 ())
1943 {
1944- glPushAttrib (GL_SCISSOR_BIT);
1945- glEnable (GL_SCISSOR_TEST);
1946+ /* We might have a previous scissor region, so we need
1947+ * to fetch it, however slow that might be .. */
1948+ GLint scissorBox[4];
1949+ GLboolean scissorEnabled;
1950+
1951+ scissorEnabled = glIsEnabled (GL_SCISSOR_TEST);
1952+ glGetIntegerv (GL_SCISSOR_BOX, scissorBox);
1953+
1954+ if (!scissorEnabled)
1955+ glEnable (GL_SCISSOR_TEST);
1956+
1957 glScissor (clearBox.x1 (),
1958 screen->height () - clearBox.y2 (),
1959 clearBox.width (),
1960 clearBox.height ());
1961+ glClearStencil (0);
1962 glClear (GL_STENCIL_BUFFER_BIT);
1963- glPopAttrib ();
1964+
1965+ if (!scissorEnabled)
1966+ glDisable (GL_SCISSOR_TEST);
1967+
1968+ glScissor (scissorBox[0], scissorBox[1],
1969+ scissorBox[2], scissorBox[3]);
1970 }
1971
1972- glStencilFunc (GL_ALWAYS, 0x1, ~0);
1973+ glStencilFunc (GL_ALWAYS, 1, 1);
1974 glStencilOp (GL_KEEP, GL_KEEP, GL_REPLACE);
1975
1976- glDisableClientState (GL_TEXTURE_COORD_ARRAY);
1977- gWindow->glDrawGeometry ();
1978- glEnableClientState (GL_TEXTURE_COORD_ARRAY);
1979+ /* Render a white polygon where the window is */
1980+ gWindow->vertexBuffer ()->render (transform);
1981
1982 glColorMask (GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
1983+ glStencilMask (0);
1984 glDisable (GL_STENCIL_TEST);
1985 }
1986 }
1987@@ -1720,10 +1694,248 @@
1988 return status;
1989 }
1990
1991+namespace
1992+{
1993+void setupShadersAndUniformsForDstBlur (GLTexture *texture,
1994+ GLWindow *gWindow,
1995+ BlurScreen *bScreen,
1996+ int &unit,
1997+ int &iTC,
1998+ float threshold)
1999+{
2000+ GLfloat dx, dy;
2001+
2002+ switch (bScreen->optionGetFilter ())
2003+ {
2004+ case BlurOptions::Filter4xbilinear:
2005+ {
2006+ dx = bScreen->tx / 2.1f;
2007+ dy = bScreen->ty / 2.1f;
2008+
2009+ unit = 1; // FIXME!!
2010+
2011+ const CompString &function (
2012+ bScreen->getDstBlurFragmentFunction (
2013+ texture, unit, 0, 0));
2014+
2015+ if (!function.empty ())
2016+ {
2017+ (*GL::activeTexture) (GL_TEXTURE0 + unit);
2018+ bScreen->texture[0]->enable (GLTexture::Good);
2019+ gWindow->vertexBuffer ()->addTexCoords (unit, 0, NULL);
2020+ (*GL::activeTexture) (GL_TEXTURE0);
2021+
2022+ gWindow->addShaders ("blur",
2023+ "",
2024+ function);
2025+
2026+ gWindow->vertexBuffer ()->addUniform4f ("blur_translation",
2027+ bScreen->tx, bScreen->ty,
2028+ 0.0f, 0.0f);
2029+
2030+ gWindow->vertexBuffer ()->addUniform4f ("blur_threshold",
2031+ threshold,
2032+ threshold,
2033+ threshold,
2034+ threshold);
2035+
2036+ gWindow->vertexBuffer ()->addUniform4f ("blur_dxdy",
2037+ dx, dy, 0.0, 0.0);
2038+ }
2039+ }
2040+ break;
2041+ case BlurOptions::FilterGaussian:
2042+ {
2043+#if INDEPENDENT_TEX_SUPPORTED
2044+ if (bScreen->optionGetIndependentTex ())
2045+ {
2046+ /* leave one free texture unit for fragment position */
2047+ iTC = MAX (0, GL::maxTextureUnits -
2048+ (gWindow->geometry ().texUnits + 1));
2049+ if (iTC)
2050+ iTC = MIN (iTC / 2, bScreen->numTexop);
2051+ }
2052+#endif
2053+ unit = 1;
2054+
2055+ const CompString &function (
2056+ bScreen->getDstBlurFragmentFunction (
2057+ texture, unit, iTC,
2058+ gWindow->vertexBuffer ()->countTextures ()));
2059+
2060+ if (!function.empty ())
2061+ {
2062+ gWindow->addShaders ("blur",
2063+ "",
2064+ function);
2065+
2066+ (*GL::activeTexture) (GL_TEXTURE0 + unit);
2067+ bScreen->texture[0]->enable (GLTexture::Good);
2068+ gWindow->vertexBuffer ()->addTexCoords (unit, 0, NULL);
2069+ (*GL::activeTexture) (GL_TEXTURE0 + unit + 1);
2070+ bScreen->fbo->tex ()->enable (GLTexture::Good);
2071+ gWindow->vertexBuffer ()->addTexCoords (unit + 1, 0, NULL);
2072+ (*GL::activeTexture) (GL_TEXTURE0);
2073+
2074+ gWindow->vertexBuffer ()->addUniform4f ("blur_translation",
2075+ bScreen->tx, bScreen->ty,
2076+ 0.0f, 0.0f);
2077+
2078+ gWindow->vertexBuffer ()->addUniform4f ("blur_threshold",
2079+ threshold,
2080+ threshold,
2081+ threshold,
2082+ threshold);
2083+#if INDEPENDENT_TEX_SUPPORTED
2084+ if (iTC)
2085+ {
2086+ GLMatrix tm, rm;
2087+ float s_gen[4], t_gen[4], q_gen[4];
2088+
2089+ for (unsigned int i = 0; i < 16; i++)
2090+ tm[i] = 0;
2091+ tm[0] = (bScreen->output->width () / 2.0) *
2092+ bScreen->tx;
2093+ tm[5] = (bScreen->output->height () / 2.0) *
2094+ bScreen->ty;
2095+ tm[10] = 1;
2096+
2097+ tm[12] = (bScreen->output->width () / 2.0 +
2098+ bScreen->output->x1 ()) * bScreen->tx;
2099+ tm[13] = (bScreen->output->height () / 2.0 +
2100+ screen->height () -
2101+ bScreen->output->y2 ()) * bScreen->ty;
2102+ tm[14] = 1;
2103+ tm[15] = 1;
2104+
2105+ tm *= bScreen->mvp;
2106+
2107+ for (int i = 0; i < iTC; i++)
2108+ {
2109+ (*GL::activeTexture) (GL_TEXTURE0 +
2110+ gWindow->geometry ().texUnits + (i * 2));
2111+
2112+ rm.reset ();
2113+ rm[13] = bScreen->ty * bScreen->pos[i];
2114+ rm *= tm;
2115+
2116+ s_gen[0] = rm[0];
2117+ s_gen[1] = rm[4];
2118+ s_gen[2] = rm[8];
2119+ s_gen[3] = rm[12];
2120+ t_gen[0] = rm[1];
2121+ t_gen[1] = rm[5];
2122+ t_gen[2] = rm[9];
2123+ t_gen[3] = rm[13];
2124+ q_gen[0] = rm[3];
2125+ q_gen[1] = rm[7];
2126+ q_gen[2] = rm[11];
2127+ q_gen[3] = rm[15];
2128+
2129+ glTexGenfv (GL_T, GL_OBJECT_PLANE, t_gen);
2130+ glTexGenfv (GL_S, GL_OBJECT_PLANE, s_gen);
2131+ glTexGenfv (GL_Q, GL_OBJECT_PLANE, q_gen);
2132+
2133+ glTexGeni (GL_S, GL_TEXTURE_GEN_MODE,
2134+ GL_OBJECT_LINEAR);
2135+ glTexGeni (GL_T, GL_TEXTURE_GEN_MODE,
2136+ GL_OBJECT_LINEAR);
2137+ glTexGeni (GL_Q, GL_TEXTURE_GEN_MODE,
2138+ GL_OBJECT_LINEAR);
2139+
2140+ glEnable (GL_TEXTURE_GEN_S);
2141+ glEnable (GL_TEXTURE_GEN_T);
2142+ glEnable (GL_TEXTURE_GEN_Q);
2143+
2144+ (*GL::activeTexture) (GL_TEXTURE0 +
2145+ gWindow->geometry ().texUnits +
2146+ 1 + (i * 2));
2147+
2148+ rm.reset ();
2149+
2150+ rm[13] = -bScreen->ty * bScreen->pos[i];
2151+ rm *= tm;
2152+
2153+ s_gen[0] = rm[0];
2154+ s_gen[1] = rm[4];
2155+ s_gen[2] = rm[8];
2156+ s_gen[3] = rm[12];
2157+ t_gen[0] = rm[1];
2158+ t_gen[1] = rm[5];
2159+ t_gen[2] = rm[9];
2160+ t_gen[3] = rm[13];
2161+ q_gen[0] = rm[3];
2162+ q_gen[1] = rm[7];
2163+ q_gen[2] = rm[11];
2164+ q_gen[3] = rm[15];
2165+
2166+ glTexGenfv (GL_T, GL_OBJECT_PLANE, t_gen);
2167+ glTexGenfv (GL_S, GL_OBJECT_PLANE, s_gen);
2168+ glTexGenfv (GL_Q, GL_OBJECT_PLANE, q_gen);
2169+
2170+ glTexGeni (GL_S, GL_TEXTURE_GEN_MODE,
2171+ GL_OBJECT_LINEAR);
2172+ glTexGeni (GL_T, GL_TEXTURE_GEN_MODE,
2173+ GL_OBJECT_LINEAR);
2174+ glTexGeni (GL_Q, GL_TEXTURE_GEN_MODE,
2175+ GL_OBJECT_LINEAR);
2176+
2177+ glEnable (GL_TEXTURE_GEN_S);
2178+ glEnable (GL_TEXTURE_GEN_T);
2179+ glEnable (GL_TEXTURE_GEN_Q);
2180+ }
2181+
2182+ (*GL::activeTexture) (GL_TEXTURE0);
2183+ }
2184+#endif
2185+ }
2186+ }
2187+ break;
2188+ case BlurOptions::FilterMipmap:
2189+ {
2190+ unit = 1; // FIXME!!
2191+
2192+ const CompString &function (
2193+ bScreen->getDstBlurFragmentFunction (texture,
2194+ unit,
2195+ 0,
2196+ 0));
2197+
2198+ if (!function.empty ())
2199+ {
2200+ float lod =
2201+ bScreen->optionGetMipmapLod ();
2202+
2203+ gWindow->addShaders ("blur",
2204+ "",
2205+ function);
2206+
2207+ (*GL::activeTexture) (GL_TEXTURE0 + unit);
2208+ bScreen->texture[0]->enable (GLTexture::Good);
2209+ gWindow->vertexBuffer ()->addTexCoords (unit, 0, NULL);
2210+ (*GL::activeTexture) (GL_TEXTURE0);
2211+
2212+ gWindow->vertexBuffer ()->addUniform4f ("blur_translation",
2213+ bScreen->tx, bScreen->ty,
2214+ 0.0f, lod);
2215+
2216+ gWindow->vertexBuffer ()->addUniform4f ("blur_threshold",
2217+ threshold,
2218+ threshold,
2219+ threshold,
2220+ threshold);
2221+ }
2222+ }
2223+ break;
2224+ }
2225+}
2226+}
2227+
2228 void
2229-BlurWindow::glDrawTexture (GLTexture *texture,
2230- GLFragment::Attrib &attrib,
2231- unsigned int mask)
2232+BlurWindow::glDrawTexture (GLTexture *texture,
2233+ const GLMatrix &matrix,
2234+ const GLWindowPaintAttrib &attrib,
2235+ unsigned int mask)
2236 {
2237 int state = BLUR_STATE_DECOR;
2238
2239@@ -1733,295 +1945,108 @@
2240
2241 if (blur || this->state[state].active)
2242 {
2243- GLFragment::Attrib fa (attrib);
2244- int param, function;
2245 int unit = 0;
2246- GLfloat dx, dy;
2247 int iTC = 0;
2248
2249 if (blur)
2250 {
2251- param = fa.allocParameters (1);
2252-
2253- function = bScreen->getSrcBlurFragmentFunction (texture, param);
2254- if (function)
2255+ GLfloat dx, dy;
2256+
2257+ const CompString &function (
2258+ bScreen->getSrcBlurFragmentFunction (texture));
2259+
2260+ if (!function.empty ())
2261 {
2262- fa.addFunction (function);
2263+ gWindow->addShaders ("focusblur",
2264+ "",
2265+ function);
2266
2267 dx = ((texture->matrix ().xx / 2.1f) * blur) / 65535.0f;
2268 dy = ((texture->matrix ().yy / 2.1f) * blur) / 65535.0f;
2269
2270- (*GL::programEnvParameter4f) (GL_FRAGMENT_PROGRAM_ARB,
2271- param, dx, dy, dx, -dy);
2272+ gWindow->vertexBuffer ()->addUniform4f ("focusblur_input_offset",
2273+ dx, dy, dx, -dy);
2274
2275 /* bi-linear filtering is required */
2276 mask |= PAINT_WINDOW_ON_TRANSFORMED_SCREEN_MASK;
2277 }
2278 }
2279
2280+ /* We are drawing the scraped texture, blur it */
2281 if (this->state[state].active)
2282 {
2283- GLFragment::Attrib dstFa (fa);
2284- float threshold = (float) this->state[state].threshold;
2285-
2286- switch (bScreen->optionGetFilter ()) {
2287- case BlurOptions::Filter4xbilinear:
2288- dx = bScreen->tx / 2.1f;
2289- dy = bScreen->ty / 2.1f;
2290-
2291- param = dstFa.allocParameters (3);
2292- unit = dstFa.allocTextureUnits (1);
2293-
2294- function = bScreen->getDstBlurFragmentFunction (
2295- texture, param, unit, 0, 0);
2296- if (function)
2297- {
2298- dstFa.addFunction (function);
2299-
2300- (*GL::activeTexture) (GL_TEXTURE0_ARB + unit);
2301- glBindTexture (bScreen->target, bScreen->texture[0]);
2302- (*GL::activeTexture) (GL_TEXTURE0_ARB);
2303-
2304- (*GL::programEnvParameter4f) (GL_FRAGMENT_PROGRAM_ARB,
2305- param,
2306- bScreen->tx, bScreen->ty,
2307- 0.0f, 0.0f);
2308-
2309- (*GL::programEnvParameter4f) (GL_FRAGMENT_PROGRAM_ARB,
2310- param + 1,
2311- threshold, threshold,
2312- threshold, threshold);
2313-
2314- (*GL::programEnvParameter4f) (GL_FRAGMENT_PROGRAM_ARB,
2315- param + 2,
2316- dx, dy, 0.0f, 0.0f);
2317- }
2318- break;
2319- case BlurOptions::FilterGaussian:
2320- if (bScreen->optionGetIndependentTex ())
2321- {
2322- /* leave one free texture unit for fragment position */
2323- iTC = MAX (0, GL::maxTextureUnits -
2324- (gWindow->geometry ().texUnits + 1));
2325- if (iTC)
2326- iTC = MIN (iTC / 2, bScreen->numTexop);
2327- }
2328-
2329- param = dstFa.allocParameters (2);
2330- unit = dstFa.allocTextureUnits (2);
2331-
2332- function = bScreen->getDstBlurFragmentFunction (
2333- texture, param, unit, iTC,
2334- gWindow->geometry ().texUnits);
2335-
2336- if (function)
2337- {
2338- dstFa.addFunction (function);
2339-
2340- (*GL::activeTexture) (GL_TEXTURE0_ARB + unit);
2341- glBindTexture (bScreen->target, bScreen->texture[0]);
2342- (*GL::activeTexture) (GL_TEXTURE0_ARB + unit + 1);
2343- glBindTexture (bScreen->target, bScreen->texture[1]);
2344- (*GL::activeTexture) (GL_TEXTURE0_ARB);
2345-
2346- (*GL::programEnvParameter4f) (GL_FRAGMENT_PROGRAM_ARB,
2347- param, bScreen->tx,
2348- bScreen->ty, 0.0f, 0.0f);
2349-
2350- (*GL::programEnvParameter4f) (GL_FRAGMENT_PROGRAM_ARB,
2351- param + 1,
2352- threshold, threshold,
2353- threshold, threshold);
2354-
2355- if (iTC)
2356- {
2357- GLMatrix tm, rm;
2358- float s_gen[4], t_gen[4], q_gen[4];
2359-
2360- for (unsigned int i = 0; i < 16; i++)
2361- tm[i] = 0;
2362- tm[0] = (bScreen->output->width () / 2.0) *
2363- bScreen->tx;
2364- tm[5] = (bScreen->output->height () / 2.0) *
2365- bScreen->ty;
2366- tm[10] = 1;
2367-
2368- tm[12] = (bScreen->output->width () / 2.0 +
2369- bScreen->output->x1 ()) * bScreen->tx;
2370- tm[13] = (bScreen->output->height () / 2.0 +
2371- screen->height () -
2372- bScreen->output->y2 ()) * bScreen->ty;
2373- tm[14] = 1;
2374- tm[15] = 1;
2375-
2376- tm *= bScreen->mvp;
2377-
2378- for (int i = 0; i < iTC; i++)
2379- {
2380- (*GL::activeTexture) (GL_TEXTURE0_ARB +
2381- gWindow->geometry ().texUnits + (i * 2));
2382-
2383- rm.reset ();
2384- rm[13] = bScreen->ty * bScreen->pos[i];
2385- rm *= tm;
2386-
2387- s_gen[0] = rm[0];
2388- s_gen[1] = rm[4];
2389- s_gen[2] = rm[8];
2390- s_gen[3] = rm[12];
2391- t_gen[0] = rm[1];
2392- t_gen[1] = rm[5];
2393- t_gen[2] = rm[9];
2394- t_gen[3] = rm[13];
2395- q_gen[0] = rm[3];
2396- q_gen[1] = rm[7];
2397- q_gen[2] = rm[11];
2398- q_gen[3] = rm[15];
2399-
2400- glTexGenfv (GL_T, GL_OBJECT_PLANE, t_gen);
2401- glTexGenfv (GL_S, GL_OBJECT_PLANE, s_gen);
2402- glTexGenfv (GL_Q, GL_OBJECT_PLANE, q_gen);
2403-
2404- glTexGeni (GL_S, GL_TEXTURE_GEN_MODE,
2405- GL_OBJECT_LINEAR);
2406- glTexGeni (GL_T, GL_TEXTURE_GEN_MODE,
2407- GL_OBJECT_LINEAR);
2408- glTexGeni (GL_Q, GL_TEXTURE_GEN_MODE,
2409- GL_OBJECT_LINEAR);
2410-
2411- glEnable (GL_TEXTURE_GEN_S);
2412- glEnable (GL_TEXTURE_GEN_T);
2413- glEnable (GL_TEXTURE_GEN_Q);
2414-
2415- (*GL::activeTexture) (GL_TEXTURE0_ARB +
2416- gWindow->geometry ().texUnits +
2417- 1 + (i * 2));
2418-
2419- rm.reset ();
2420-
2421- rm[13] = -bScreen->ty * bScreen->pos[i];
2422- rm *= tm;
2423-
2424- s_gen[0] = rm[0];
2425- s_gen[1] = rm[4];
2426- s_gen[2] = rm[8];
2427- s_gen[3] = rm[12];
2428- t_gen[0] = rm[1];
2429- t_gen[1] = rm[5];
2430- t_gen[2] = rm[9];
2431- t_gen[3] = rm[13];
2432- q_gen[0] = rm[3];
2433- q_gen[1] = rm[7];
2434- q_gen[2] = rm[11];
2435- q_gen[3] = rm[15];
2436-
2437- glTexGenfv (GL_T, GL_OBJECT_PLANE, t_gen);
2438- glTexGenfv (GL_S, GL_OBJECT_PLANE, s_gen);
2439- glTexGenfv (GL_Q, GL_OBJECT_PLANE, q_gen);
2440-
2441- glTexGeni (GL_S, GL_TEXTURE_GEN_MODE,
2442- GL_OBJECT_LINEAR);
2443- glTexGeni (GL_T, GL_TEXTURE_GEN_MODE,
2444- GL_OBJECT_LINEAR);
2445- glTexGeni (GL_Q, GL_TEXTURE_GEN_MODE,
2446- GL_OBJECT_LINEAR);
2447-
2448- glEnable (GL_TEXTURE_GEN_S);
2449- glEnable (GL_TEXTURE_GEN_T);
2450- glEnable (GL_TEXTURE_GEN_Q);
2451- }
2452-
2453- (*GL::activeTexture) (GL_TEXTURE0_ARB);
2454- }
2455-
2456- }
2457- break;
2458- case BlurOptions::FilterMipmap:
2459- param = dstFa.allocParameters (2);
2460- unit = dstFa.allocTextureUnits (1);
2461-
2462- function =
2463- bScreen->getDstBlurFragmentFunction (texture, param,
2464- unit, 0, 0);
2465- if (function)
2466- {
2467- float lod =
2468- bScreen->optionGetMipmapLod ();
2469-
2470- dstFa.addFunction (function);
2471-
2472- (*GL::activeTexture) (GL_TEXTURE0_ARB + unit);
2473- glBindTexture (bScreen->target, bScreen->texture[0]);
2474- (*GL::activeTexture) (GL_TEXTURE0_ARB);
2475-
2476- (*GL::programEnvParameter4f) (GL_FRAGMENT_PROGRAM_ARB,
2477- param,
2478- bScreen->tx, bScreen->ty,
2479- 0.0f, lod);
2480-
2481- (*GL::programEnvParameter4f) (GL_FRAGMENT_PROGRAM_ARB,
2482- param + 1,
2483- threshold, threshold,
2484- threshold, threshold);
2485- }
2486- break;
2487- }
2488+ setupShadersAndUniformsForDstBlur (texture,
2489+ gWindow,
2490+ bScreen,
2491+ unit,
2492+ iTC,
2493+ this->state[state].threshold);
2494
2495 if (this->state[state].clipped ||
2496 (!bScreen->blurOcclusion && !clip.isEmpty ()))
2497 {
2498 glEnable (GL_STENCIL_TEST);
2499
2500+ /* Don't touch the stencil buffer */
2501 glStencilOp (GL_KEEP, GL_KEEP, GL_KEEP);
2502- glStencilFunc (GL_EQUAL, 0x1, ~0);
2503-
2504- /* draw region with destination blur */
2505- gWindow->glDrawTexture (texture, dstFa, mask);
2506-
2507- glStencilFunc (GL_EQUAL, 0, ~0);
2508+
2509+ /* Draw region with blur only where the stencil test passes */
2510+ glStencilFunc (GL_EQUAL, 1, 1);
2511+
2512+ /* draw region with destination blur - we are relying
2513+ * on a fairly awkward side-effect here which clears our
2514+ * active shader once this call is complete */
2515+ gWindow->glDrawTexture (texture, matrix, attrib, mask);
2516+
2517+ /* Allow drawing in everywhere but where we just drew */
2518+ glStencilFunc (GL_EQUAL, 0, 1);
2519
2520 /* draw region without destination blur */
2521- gWindow->glDrawTexture (texture, fa, mask);
2522+ gWindow->glDrawTexture (texture, matrix, attrib, mask);
2523
2524 glDisable (GL_STENCIL_TEST);
2525 }
2526 else
2527 {
2528 /* draw with destination blur */
2529- gWindow->glDrawTexture (texture, dstFa, mask);
2530+ gWindow->glDrawTexture (texture, matrix, attrib, mask);
2531 }
2532 }
2533 else
2534 {
2535- gWindow->glDrawTexture (texture, fa, mask);
2536+ gWindow->glDrawTexture (texture, matrix, attrib, mask);
2537 }
2538
2539 if (unit)
2540 {
2541- (*GL::activeTexture) (GL_TEXTURE0_ARB + unit);
2542- glBindTexture (bScreen->target, 0);
2543- (*GL::activeTexture) (GL_TEXTURE0_ARB + unit + 1);
2544- glBindTexture (bScreen->target, 0);
2545- (*GL::activeTexture) (GL_TEXTURE0_ARB);
2546+ (*GL::activeTexture) (GL_TEXTURE0 + unit);
2547+ bScreen->texture[0]->disable ();
2548+ (*GL::activeTexture) (GL_TEXTURE0 + unit + 1);
2549+ if (bScreen->fbo &&
2550+ bScreen->fbo->tex ())
2551+ bScreen->fbo->tex ()->disable ();
2552+ (*GL::activeTexture) (GL_TEXTURE0);
2553 }
2554
2555+#if INDEPENDENT_TEX_SUPPORTED
2556 if (iTC)
2557 {
2558 int i;
2559 for (i = gWindow->geometry ().texUnits;
2560 i < gWindow->geometry ().texUnits + (2 * iTC); i++)
2561 {
2562- (*GL::activeTexture) (GL_TEXTURE0_ARB + i);
2563+ (*GL::activeTexture) (GL_TEXTURE0 + i);
2564 glDisable (GL_TEXTURE_GEN_S);
2565 glDisable (GL_TEXTURE_GEN_T);
2566 glDisable (GL_TEXTURE_GEN_Q);
2567 }
2568- (*GL::activeTexture) (GL_TEXTURE0_ARB);
2569+ (*GL::activeTexture) (GL_TEXTURE0);
2570 }
2571+#endif
2572 }
2573 else
2574 {
2575- gWindow->glDrawTexture (texture, attrib, mask);
2576+ gWindow->glDrawTexture (texture, matrix, attrib, mask);
2577 }
2578 }
2579
2580@@ -2115,7 +2140,7 @@
2581 screen->activeWindow ());
2582
2583 w = screen->findWindow (xid);
2584- if (w && GL::fragmentProgram)
2585+ if (w && GL::shaders)
2586 {
2587 BLUR_SCREEN (screen);
2588 BLUR_WINDOW (w);
2589@@ -2175,7 +2200,7 @@
2590 cScreen->damageScreen ();
2591 break;
2592 case BlurOptions::AlphaBlur:
2593- if (GL::fragmentProgram && optionGetAlphaBlur ())
2594+ if (GL::shaders && optionGetAlphaBlur ())
2595 alphaBlur = true;
2596 else
2597 alphaBlur = false;
2598@@ -2228,12 +2253,15 @@
2599 dstBlurFunctions (0),
2600 output (NULL),
2601 count (0),
2602- program (0),
2603 maxTemp (32),
2604- fbo (0),
2605- fboStatus (0)
2606+ fbo (new GLFramebufferObject ()),
2607+ oldDrawFramebuffer (NULL),
2608+ determineProjectedBlurRegionsPass (false),
2609+ damageQuery (cScreen->getDamageQuery (boost::bind (
2610+ &BlurScreen::markAreaDirty,
2611+ this,
2612+ _1)))
2613 {
2614-
2615 blurAtom[BLUR_STATE_CLIENT] =
2616 XInternAtom (screen->dpy (), "_COMPIZ_WM_WINDOW_BLUR", 0);
2617 blurAtom[BLUR_STATE_DECOR] =
2618@@ -2242,27 +2270,20 @@
2619 blurTime = 1000.0f / optionGetBlurSpeed ();
2620 blurOcclusion = optionGetOcclusion ();
2621
2622- for (int i = 0; i < 2; i++)
2623- texture[i] = 0;
2624-
2625 glGetIntegerv (GL_STENCIL_BITS, &stencilBits);
2626 if (!stencilBits)
2627 compLogMessage ("blur", CompLogLevelWarn,
2628 "No stencil buffer. Region based blur disabled");
2629
2630- /* We need GL_ARB_fragment_program for blur */
2631- if (GL::fragmentProgram)
2632+ /* We need GL_ARB_shading_language_100 for blur */
2633+ if (GL::shaders)
2634 alphaBlur = optionGetAlphaBlur ();
2635 else
2636 alphaBlur = false;
2637
2638- if (GL::fragmentProgram)
2639+ if (GL::shaders)
2640 {
2641- int tmp[4];
2642- GL::getProgramiv (GL_FRAGMENT_PROGRAM_ARB,
2643- GL_MAX_PROGRAM_NATIVE_TEMPORARIES_ARB,
2644- tmp);
2645- maxTemp = tmp[0];
2646+ maxTemp = 1024; // FIXME!!!!!!!
2647 }
2648
2649 updateFilterRadius ();
2650@@ -2277,20 +2298,7 @@
2651
2652 BlurScreen::~BlurScreen ()
2653 {
2654- foreach (BlurFunction &bf, srcBlurFunctions)
2655- GLFragment::destroyFragmentFunction (bf.id);
2656- foreach (BlurFunction &bf, dstBlurFunctions)
2657- GLFragment::destroyFragmentFunction (bf.id);
2658-
2659 cScreen->damageScreen ();
2660-
2661- if (fbo)
2662- (*GL::deleteFramebuffers) (1, &fbo);
2663-
2664- for (int i = 0; i < 2; i++)
2665- if (texture[i])
2666- glDeleteTextures (1, &texture[i]);
2667-
2668 }
2669
2670 BlurWindow::BlurWindow (CompWindow *w) :
2671@@ -2329,10 +2337,11 @@
2672 bool
2673 BlurPluginVTable::init ()
2674 {
2675- if (CompPlugin::checkPluginABI ("core", CORE_ABIVERSION) &&
2676- CompPlugin::checkPluginABI ("composite", COMPIZ_COMPOSITE_ABI) &&
2677- CompPlugin::checkPluginABI ("opengl", COMPIZ_OPENGL_ABI))
2678- return true;
2679+ if (!CompPlugin::checkPluginABI ("core", CORE_ABIVERSION) |
2680+ !CompPlugin::checkPluginABI ("composite", COMPIZ_COMPOSITE_ABI) |
2681+ !CompPlugin::checkPluginABI ("opengl", COMPIZ_OPENGL_ABI))
2682+ return false;
2683
2684- return false;
2685+ return true;
2686 }
2687+
2688
2689=== modified file 'plugins/blur/src/blur.h'
2690--- plugins/blur/src/blur.h 2012-09-07 22:37:20 +0000
2691+++ plugins/blur/src/blur.h 2016-05-14 02:33:05 +0000
2692@@ -23,32 +23,35 @@
2693 * Author: David Reveman <davidr@novell.com>
2694 */
2695
2696+#include <iosfwd>
2697+#include <boost/shared_ptr.hpp>
2698+
2699+#include <stdlib.h>
2700+#include <string.h>
2701+#include <math.h>
2702+#include <X11/Xatom.h>
2703+
2704 #include "blur_options.h"
2705
2706 #include <composite/composite.h>
2707 #include <opengl/opengl.h>
2708+#include <opengl/program.h>
2709 #include <decoration.h>
2710
2711-#include <stdlib.h>
2712-#include <string.h>
2713-#include <math.h>
2714-
2715-
2716-#include <X11/Xatom.h>
2717-#include <GL/glu.h>
2718-
2719-
2720-extern const unsigned short BLUR_GAUSSIAN_RADIUS_MAX;
2721-
2722-struct BlurFunction {
2723-
2724- GLFragment::FunctionId id;
2725-
2726+
2727+const unsigned short BLUR_GAUSSIAN_RADIUS_MAX = 15;
2728+
2729+const unsigned short BLUR_STATE_CLIENT = 0;
2730+const unsigned short BLUR_STATE_DECOR = 1;
2731+const unsigned short BLUR_STATE_NUM = 2;
2732+
2733+struct BlurFunction
2734+{
2735+ CompString shader;
2736 int target;
2737- int param;
2738- int unit;
2739 int startTC;
2740 int numITC;
2741+ int saturation;
2742 };
2743
2744 struct BlurBox {
2745@@ -56,10 +59,6 @@
2746 decor_point_t p2;
2747 };
2748
2749-extern const unsigned short BLUR_STATE_CLIENT;
2750-extern const unsigned short BLUR_STATE_DECOR;
2751-extern const unsigned short BLUR_STATE_NUM;
2752-
2753 struct BlurState {
2754 int threshold;
2755 std::vector<BlurBox> box;
2756@@ -88,6 +87,8 @@
2757 void preparePaint (int);
2758 void donePaint ();
2759
2760+ void damageCutoff ();
2761+
2762 bool glPaintOutput (const GLScreenPaintAttrib &,
2763 const GLMatrix &, const CompRegion &,
2764 CompOutput *, unsigned int);
2765@@ -99,12 +100,11 @@
2766 void updateFilterRadius ();
2767 void blurReset ();
2768
2769- GLFragment::FunctionId getSrcBlurFragmentFunction (GLTexture *, int);
2770- GLFragment::FunctionId getDstBlurFragmentFunction (GLTexture *texture,
2771- int param,
2772- int unit,
2773- int numITC,
2774- int startTC);
2775+ const CompString & getSrcBlurFragmentFunction (GLTexture *);
2776+ const CompString & getDstBlurFragmentFunction (GLTexture *texture,
2777+ int unit,
2778+ int numITC,
2779+ int startTC);
2780
2781 bool projectVertices (CompOutput *output,
2782 const GLMatrix &transform,
2783@@ -112,8 +112,9 @@
2784 float *scr,
2785 int n);
2786
2787- bool loadFragmentProgram (GLuint *program,
2788- const char *string);
2789+ bool loadFragmentProgram (boost::shared_ptr <GLProgram> &program,
2790+ const char *vertex,
2791+ const char *fragment);
2792
2793 bool loadFilterProgram (int numITC);
2794
2795@@ -152,24 +153,34 @@
2796 CompOutput *output;
2797 int count;
2798
2799- GLuint texture[2];
2800+ GLTexture::List texture;
2801
2802- GLenum target;
2803 float tx;
2804 float ty;
2805 int width;
2806 int height;
2807
2808- GLuint program;
2809+ boost::shared_ptr <GLProgram> program;
2810 int maxTemp;
2811- GLuint fbo;
2812- bool fboStatus;
2813+ boost::shared_ptr <GLFramebufferObject> fbo;
2814+
2815+ GLFramebufferObject *oldDrawFramebuffer;
2816
2817 float amp[BLUR_GAUSSIAN_RADIUS_MAX];
2818 float pos[BLUR_GAUSSIAN_RADIUS_MAX];
2819 int numTexop;
2820
2821 GLMatrix mvp;
2822+
2823+ bool determineProjectedBlurRegionsPass;
2824+ bool allowAreaDirtyOnOwnDamageBuffer;
2825+ CompRegion backbufferUpdateRegionThisFrame;
2826+
2827+ compiz::composite::buffertracking::AgeDamageQuery::Ptr damageQuery;
2828+
2829+ private:
2830+
2831+ bool markAreaDirty (const CompRegion &r);
2832 };
2833
2834 class BlurWindow :
2835@@ -188,11 +199,16 @@
2836
2837 bool glPaint (const GLWindowPaintAttrib &, const GLMatrix &,
2838 const CompRegion &, unsigned int);
2839- bool glDraw (const GLMatrix &, GLFragment::Attrib &,
2840+ void glTransformationComplete (const GLMatrix &matrix,
2841+ const CompRegion &region,
2842+ unsigned int mask);
2843+
2844+ bool glDraw (const GLMatrix &, const GLWindowPaintAttrib &,
2845 const CompRegion &, unsigned int);
2846- void glDrawTexture (GLTexture *texture, GLFragment::Attrib &,
2847+ void glDrawTexture (GLTexture *texture,
2848+ const GLMatrix &,
2849+ const GLWindowPaintAttrib &,
2850 unsigned int);
2851-
2852 void updateRegion ();
2853
2854 void setBlur (int state,
2855@@ -206,9 +222,13 @@
2856 void projectRegion (CompOutput *output,
2857 const GLMatrix &transform);
2858
2859+ void determineBlurRegion (int filter,
2860+ const GLMatrix &transform,
2861+ int clientThreshold);
2862+
2863 bool updateDstTexture (const GLMatrix &transform,
2864 CompRect *pExtents,
2865- int clientThreshold);
2866+ unsigned int mask);
2867
2868 public:
2869 CompWindow *window;
2870@@ -225,6 +245,7 @@
2871
2872 CompRegion region;
2873 CompRegion clip;
2874+ CompRegion projectedBlurRegion;
2875 };
2876
2877 #define BLUR_SCREEN(s) \
2878
2879=== modified file 'plugins/opengl/DRIVERS'
2880--- plugins/opengl/DRIVERS 2013-02-17 07:28:12 +0000
2881+++ plugins/opengl/DRIVERS 2016-05-14 02:33:05 +0000
2882@@ -74,3 +74,13 @@
2883 RESOLVED. WORKAROUND: force the usage of the copy-to-texture path
2884 when using this driver ("Chromium") and binding an externally
2885 managed pixmap to a texture
2886+
2887+vmwgfx
2888+======
2889+
2890+ 1. vmwgfx does not implement glGenerateMipmap for FBO-backed
2891+ textures.
2892+
2893+ RESOLVED. WORKAROUND: do not use glGenerateMipmap with vmwgfx. This
2894+ means that some functionality, like smoothed blurs will not be
2895+ available on this driver.
2896
2897=== modified file 'plugins/opengl/include/opengl/opengl.h'
2898--- plugins/opengl/include/opengl/opengl.h 2015-10-26 17:15:43 +0000
2899+++ plugins/opengl/include/opengl/opengl.h 2016-05-14 02:33:05 +0000
2900@@ -59,7 +59,7 @@
2901 #include <opengl/programcache.h>
2902 #include <opengl/shadercache.h>
2903
2904-#define COMPIZ_OPENGL_ABI 7
2905+#define COMPIZ_OPENGL_ABI 8
2906
2907 /*
2908 * Some plugins check for #ifdef USE_MODERN_COMPIZ_GL. Support it for now, but
2909@@ -851,6 +851,8 @@
2910
2911 bool glInitContext (XVisualInfo *);
2912
2913+ bool driverHasBrokenFBOMipmaps () const;
2914+
2915 WRAPABLE_HND (0, GLScreenInterface, bool, glPaintOutput,
2916 const GLScreenPaintAttrib &, const GLMatrix &,
2917 const CompRegion &, CompOutput *, unsigned int);
2918@@ -957,12 +959,20 @@
2919 unsigned int max = MAXSHORT);
2920 virtual void glDrawTexture (GLTexture *texture, const GLMatrix &,
2921 const GLWindowPaintAttrib &, unsigned int);
2922+
2923+ /**
2924+ * Hookable function to notify transformation was complete, plugins
2925+ * should use the results of transformation from glPaint here
2926+ */
2927+ virtual void glTransformationComplete (const GLMatrix &matrix,
2928+ const CompRegion &region,
2929+ unsigned int mask);
2930 };
2931
2932 extern template class PluginClassHandler<GLWindow, CompWindow, COMPIZ_OPENGL_ABI>;
2933
2934 class GLWindow :
2935- public WrapableHandler<GLWindowInterface, 4>,
2936+ public WrapableHandler<GLWindowInterface, 5>,
2937 public PluginClassHandler<GLWindow, CompWindow, COMPIZ_OPENGL_ABI>
2938 {
2939 public:
2940@@ -1041,6 +1051,8 @@
2941 WRAPABLE_HND (3, GLWindowInterface, void, glDrawTexture,
2942 GLTexture *texture, const GLMatrix &,
2943 const GLWindowPaintAttrib &, unsigned int);
2944+ WRAPABLE_HND (4, GLWindowInterface, void, glTransformationComplete,
2945+ const GLMatrix &, const CompRegion &, unsigned int);
2946
2947 friend class GLScreen;
2948 friend class PrivateGLScreen;
2949
2950=== modified file 'plugins/opengl/include/opengl/program.h'
2951--- plugins/opengl/include/opengl/program.h 2012-05-17 10:41:21 +0000
2952+++ plugins/opengl/include/opengl/program.h 2016-05-14 02:33:05 +0000
2953@@ -40,7 +40,7 @@
2954 class GLProgram
2955 {
2956 public:
2957- GLProgram (CompString &vertexShader, CompString &fragmentShader);
2958+ GLProgram (const CompString &vertexShader, const CompString &fragmentShader);
2959 ~GLProgram ();
2960
2961 bool valid ();
2962
2963=== modified file 'plugins/opengl/include/opengl/vertexbuffer.h'
2964--- plugins/opengl/include/opengl/vertexbuffer.h 2012-08-14 06:33:22 +0000
2965+++ plugins/opengl/include/opengl/vertexbuffer.h 2016-05-14 02:33:05 +0000
2966@@ -89,6 +89,7 @@
2967 void addTexCoords (GLuint texture,
2968 GLuint nTexcoords,
2969 const GLfloat *texcoords);
2970+ GLuint countTextures () const;
2971
2972 void addUniform (const char *name, GLfloat value);
2973 void addUniform (const char *name, GLint value);
2974
2975=== modified file 'plugins/opengl/src/paint.cpp'
2976--- plugins/opengl/src/paint.cpp 2015-04-07 14:20:32 +0000
2977+++ plugins/opengl/src/paint.cpp 2016-05-14 02:33:05 +0000
2978@@ -1367,6 +1367,14 @@
2979 return true;
2980 }
2981
2982+void
2983+GLWindow::glTransformationComplete (const GLMatrix &matrix,
2984+ const CompRegion &reg,
2985+ unsigned int mask)
2986+{
2987+ WRAPABLE_HND_FUNCTN (glTransformationComplete, matrix, reg, mask);
2988+}
2989+
2990 bool
2991 GLWindow::glPaint (const GLWindowPaintAttrib &attrib,
2992 const GLMatrix &transform,
2993@@ -1384,6 +1392,8 @@
2994
2995 priv->lastMask = mask;
2996
2997+ glTransformationComplete (transform, region, mask);
2998+
2999 if (mask & PAINT_WINDOW_OCCLUSION_DETECTION_MASK)
3000 {
3001 if (mask & PAINT_WINDOW_TRANSFORMED_MASK)
3002
3003=== modified file 'plugins/opengl/src/privates.h'
3004--- plugins/opengl/src/privates.h 2015-10-26 17:15:43 +0000
3005+++ plugins/opengl/src/privates.h 2016-05-14 02:33:05 +0000
3006@@ -131,6 +131,7 @@
3007 virtual ~FrameProvider () {}
3008
3009 virtual GLuint getCurrentFrame () = 0;
3010+ virtual void useCurrentFrame () = 0;
3011 virtual void endFrame () = 0;
3012
3013 virtual bool providesPersistence () = 0;
3014@@ -268,6 +269,8 @@
3015 std::vector<XToGLSync*>::size_type currentSyncNum;
3016 XToGLSync *currentSync;
3017 std::vector<XToGLSync*>::size_type warmupSyncs;
3018+
3019+ bool driverHasBrokenFBOMipmapImplementation;
3020 };
3021
3022 class PrivateGLWindow :
3023
3024=== modified file 'plugins/opengl/src/program.cpp'
3025--- plugins/opengl/src/program.cpp 2012-12-04 12:15:34 +0000
3026+++ plugins/opengl/src/program.cpp 2016-05-14 02:33:05 +0000
3027@@ -69,7 +69,7 @@
3028 }
3029 }
3030
3031-static bool compileShader (GLuint *shader, GLenum type, CompString &source)
3032+static bool compileShader (GLuint *shader, GLenum type, const CompString &source)
3033 {
3034 const GLchar *data;
3035 GLint status;
3036@@ -84,7 +84,7 @@
3037 return (status == GL_TRUE);
3038 }
3039
3040-GLProgram::GLProgram (CompString &vertexShader, CompString &fragmentShader) :
3041+GLProgram::GLProgram (const CompString &vertexShader, const CompString &fragmentShader) :
3042 priv (new PrivateProgram ())
3043 {
3044 GLuint vertex, fragment;
3045
3046=== modified file 'plugins/opengl/src/screen.cpp'
3047--- plugins/opengl/src/screen.cpp 2015-10-26 17:15:43 +0000
3048+++ plugins/opengl/src/screen.cpp 2016-05-14 02:33:05 +0000
3049@@ -345,6 +345,10 @@
3050 return age;
3051 }
3052
3053+ void useCurrentFrame ()
3054+ {
3055+ }
3056+
3057 void endFrame ()
3058 {
3059 }
3060@@ -436,6 +440,10 @@
3061 return 0;
3062 }
3063
3064+ void useCurrentFrame ()
3065+ {
3066+ }
3067+
3068 void endFrame ()
3069 {
3070 }
3071@@ -468,12 +476,14 @@
3072
3073 unsigned int getCurrentFrame ()
3074 {
3075+ return mAge;
3076+ }
3077+
3078+ void useCurrentFrame ()
3079+ {
3080 /* We are now using this buffer, reset
3081 * age back to zero */
3082- unsigned int lastAge = mAge;
3083 mAge = 0;
3084-
3085- return lastAge;
3086 }
3087
3088 void endFrame ()
3089@@ -526,6 +536,14 @@
3090 return mBackbuffer->getCurrentFrame ();
3091 }
3092
3093+ void useCurrentFrame ()
3094+ {
3095+ if (mPPRequired ())
3096+ mScratchbuffer->useCurrentFrame ();
3097+ else
3098+ mBackbuffer->useCurrentFrame ();
3099+ }
3100+
3101 void endFrame ()
3102 {
3103 mScratchbuffer->endFrame ();
3104@@ -896,6 +914,20 @@
3105 priv->incorrectRefreshRate = true;
3106 }
3107
3108+ if (glVendor != NULL && strstr (glVendor, "VMware") &&
3109+ glRenderer != NULL && strstr (glRenderer, "on SVGA3D"))
3110+ {
3111+ /* vmwgfx has an incomplete glGenerateMipmap implementation.
3112+ * It does not seem to support generating mipmaps for
3113+ * FBO backed textures - instead it raises SIGABRT with
3114+ * an exception stating that the command does not exist.
3115+ *
3116+ * This is actually supported in the spec, it just seems
3117+ * to be unavailable in the driver.
3118+ */
3119+ priv->driverHasBrokenFBOMipmapImplementation = true;
3120+ }
3121+
3122 if (strstr (glExtensions, "GL_ARB_texture_non_power_of_two"))
3123 GL::textureNonPowerOfTwo = true;
3124 GL::textureNonPowerOfTwoMipmap = GL::textureNonPowerOfTwo;
3125@@ -1163,6 +1195,12 @@
3126 return true;
3127 }
3128
3129+bool
3130+GLScreen::driverHasBrokenFBOMipmaps () const
3131+{
3132+ return priv->driverHasBrokenFBOMipmapImplementation;
3133+}
3134+
3135
3136 template class PluginClassHandler<GLScreen, CompScreen, COMPIZ_OPENGL_ABI>;
3137
3138@@ -1536,7 +1574,8 @@
3139 prevBlacklisted (false),
3140 currentSyncNum (0),
3141 currentSync (0),
3142- warmupSyncs (0)
3143+ warmupSyncs (0),
3144+ driverHasBrokenFBOMipmapImplementation (false)
3145 {
3146 ScreenInterface::setHandler (screen);
3147 CompositeScreenInterface::setHandler (cScreen);
3148@@ -2608,6 +2647,7 @@
3149 PrivateGLScreen::damageCutoff ()
3150 {
3151 cScreen->applyDamageForFrameAge (frameProvider->getCurrentFrame ());
3152+ frameProvider->useCurrentFrame ();
3153 cScreen->damageCutoff ();
3154 }
3155
3156
3157=== modified file 'plugins/opengl/src/shadercache.cpp'
3158--- plugins/opengl/src/shadercache.cpp 2014-10-30 12:47:25 +0000
3159+++ plugins/opengl/src/shadercache.cpp 2016-05-14 02:33:05 +0000
3160@@ -232,10 +232,11 @@
3161 else if (params.color == GLShaderVariableVarying)
3162 ss << "vColor *";
3163
3164- for (int i = 0; i < params.numTextures; i++)
3165- ss << " texture2D(texture" << i << ", vTexCoord" << i << ") *";
3166-
3167- ss << " 1.0;\n";
3168+ /* Sample first texture only */
3169+ if (params.numTextures)
3170+ ss << " texture2D(texture0, vTexCoord0);\n";
3171+ else
3172+ ss << " 1.0;\n";
3173
3174 if (params.saturation) {
3175 ss << "vec3 desaturated = color.rgb * vec3 (0.30, 0.59, 0.11);\n" <<
3176
3177=== modified file 'plugins/opengl/src/vertexbuffer.cpp'
3178--- plugins/opengl/src/vertexbuffer.cpp 2015-04-29 11:15:48 +0000
3179+++ plugins/opengl/src/vertexbuffer.cpp 2016-05-14 02:33:05 +0000
3180@@ -240,6 +240,11 @@
3181 data.push_back (texcoords[i]);
3182 }
3183
3184+GLuint GLVertexBuffer::countTextures () const
3185+{
3186+ return priv->nTextures;
3187+}
3188+
3189 void GLVertexBuffer::addUniform (const char *name, GLfloat value)
3190 {
3191 // we're casting to double here to make our template va_arg happy
3192
3193=== modified file 'plugins/opengl/src/window.cpp'
3194--- plugins/opengl/src/window.cpp 2014-10-30 12:47:25 +0000
3195+++ plugins/opengl/src/window.cpp 2016-05-14 02:33:05 +0000
3196@@ -210,6 +210,12 @@
3197 priv->needsRebind = true;
3198 }
3199
3200+void
3201+GLWindowInterface::glTransformationComplete (const GLMatrix &matrix,
3202+ const CompRegion &region,
3203+ unsigned int mask)
3204+ WRAPABLE_DEF (glTransformationComplete, matrix, region, mask)
3205+
3206 bool
3207 GLWindowInterface::glPaint (const GLWindowPaintAttrib &attrib,
3208 const GLMatrix &transform,

Subscribers

People subscribed via source and target branches