Merge lp:~smspillaz/compiz/compiz.revenge-of-the-blur-plugin into lp:compiz/0.9.12
- compiz.revenge-of-the-blur-plugin
- Merge into 0.9.12
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 |
Related bugs: |
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 glTransformatio
PS Jenkins bot (ps-jenkins) wrote : | # |
- 4019. By Sam Spilsbury <email address hidden>
-
debian: Install the blur plugin as part of compiz-plugins
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:4019
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
- 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.
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:4020
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
Marco Trevisan (Treviño) (3v1n0) wrote : | # |
Nice cleanup, thanks a lot.
ABI changes are in fact not relevant for other parts.
Preview Diff
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 ®ion, |
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 ®ion, |
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 = ®ion; |
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 ®ion, 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 ®ion, |
1879 | - unsigned int mask) |
1880 | +BlurWindow::glDraw (const GLMatrix &transform, |
1881 | + const GLWindowPaintAttrib &attrib, |
1882 | + const CompRegion ®ion, |
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 = ®ion; |
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 ®ion, |
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 ®ion, |
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 ®, |
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 ®ion, |
3203 | + unsigned int mask) |
3204 | + WRAPABLE_DEF (glTransformationComplete, matrix, region, mask) |
3205 | + |
3206 | bool |
3207 | GLWindowInterface::glPaint (const GLWindowPaintAttrib &attrib, |
3208 | const GLMatrix &transform, |
FAILED: Continuous integration, rev:4018 jenkins. qa.ubuntu. com/job/ compiz- ci/126/ jenkins. qa.ubuntu. com/job/ compiz- xenial- amd64-ci/ 17/console jenkins. qa.ubuntu. com/job/ compiz- xenial- armhf-ci/ 17 jenkins. qa.ubuntu. com/job/ compiz- xenial- i386-ci/ 17/console
http://
Executed test runs:
FAILURE: http://
SUCCESS: http://
FAILURE: http://
Click here to trigger a rebuild: s-jenkins. ubuntu- ci:8080/ job/compiz- ci/126/ rebuild
http://