• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 // Copyright 2020 The ANGLE Project Authors. All rights reserved.
3 // Use of this source code is governed by a BSD-style license that can be
4 // found in the LICENSE file.
5 //
6 
7 // angletypes_unittest.cpp: Unit tests of the BlendStateExt class.
8 
9 #include <gtest/gtest.h>
10 
11 #include "libANGLE/angletypes.h"
12 
13 namespace angle
14 {
15 
16 #if defined(ANGLE_IS_64_BIT_CPU)
17 constexpr bool is64Bit = true;
18 #else
19 constexpr bool is64Bit = false;
20 #endif
21 
checkInitState(const gl::BlendStateExt & blendStateExt)22 void checkInitState(const gl::BlendStateExt &blendStateExt)
23 {
24     for (size_t i = 0; i < blendStateExt.mMaxDrawBuffers; ++i)
25     {
26         ASSERT_FALSE(blendStateExt.mEnabledMask.test(i));
27 
28         bool r, g, b, a;
29         blendStateExt.getColorMaskIndexed(i, &r, &g, &b, &a);
30         ASSERT_TRUE(r);
31         ASSERT_TRUE(g);
32         ASSERT_TRUE(b);
33         ASSERT_TRUE(a);
34 
35         ASSERT_EQ(blendStateExt.getEquationColorIndexed(i), static_cast<GLenum>(GL_FUNC_ADD));
36         ASSERT_EQ(blendStateExt.getEquationAlphaIndexed(i), static_cast<GLenum>(GL_FUNC_ADD));
37 
38         ASSERT_EQ(blendStateExt.getSrcColorIndexed(i), static_cast<GLenum>(GL_ONE));
39         ASSERT_EQ(blendStateExt.getDstColorIndexed(i), static_cast<GLenum>(GL_ZERO));
40         ASSERT_EQ(blendStateExt.getSrcAlphaIndexed(i), static_cast<GLenum>(GL_ONE));
41         ASSERT_EQ(blendStateExt.getDstAlphaIndexed(i), static_cast<GLenum>(GL_ZERO));
42     }
43 }
44 
45 // Test the initial state of BlendStateExt
TEST(BlendStateExt,Init)46 TEST(BlendStateExt, Init)
47 {
48     {
49         const gl::BlendStateExt blendStateExt = gl::BlendStateExt(1);
50         ASSERT_EQ(blendStateExt.mMaxDrawBuffers, 1u);
51         ASSERT_EQ(blendStateExt.mMaxEnabledMask.to_ulong(), 1u);
52         ASSERT_EQ(blendStateExt.mMaxColorMask, is64Bit ? 0xFFu : 0xFu);
53         ASSERT_EQ(blendStateExt.mMaxEquationMask, is64Bit ? 0xFFu : 0xFu);
54         ASSERT_EQ(blendStateExt.mMaxFactorMask, 0xFFu);
55         checkInitState(blendStateExt);
56     }
57 
58     {
59         const gl::BlendStateExt blendStateExt = gl::BlendStateExt(4);
60         ASSERT_EQ(blendStateExt.mMaxDrawBuffers, 4u);
61         ASSERT_EQ(blendStateExt.mMaxEnabledMask.to_ulong(), 0xFu);
62         ASSERT_EQ(blendStateExt.mMaxColorMask, is64Bit ? 0xFFFFFFFFu : 0xFFFFu);
63         ASSERT_EQ(blendStateExt.mMaxEquationMask, is64Bit ? 0xFFFFFFFFu : 0xFFFFu);
64         ASSERT_EQ(blendStateExt.mMaxFactorMask, 0xFFFFFFFFu);
65         checkInitState(blendStateExt);
66     }
67 
68     {
69         const gl::BlendStateExt blendStateExt = gl::BlendStateExt(8);
70         ASSERT_EQ(blendStateExt.mMaxDrawBuffers, 8u);
71         ASSERT_EQ(blendStateExt.mMaxEnabledMask.to_ulong(), 0xFFu);
72         ASSERT_EQ(blendStateExt.mMaxColorMask, is64Bit ? 0xFFFFFFFFFFFFFFFFu : 0xFFFFFFFFu);
73         ASSERT_EQ(blendStateExt.mMaxEquationMask, is64Bit ? 0xFFFFFFFFFFFFFFFFu : 0xFFFFFFFFu);
74         ASSERT_EQ(blendStateExt.mMaxFactorMask, 0xFFFFFFFFFFFFFFFFu);
75         checkInitState(blendStateExt);
76     }
77 }
78 
79 // Test blend enabled flags
TEST(BlendStateExt,BlendEnabled)80 TEST(BlendStateExt, BlendEnabled)
81 {
82     gl::BlendStateExt blendStateExt = gl::BlendStateExt(3);
83 
84     blendStateExt.setEnabled(true);
85     ASSERT_EQ(blendStateExt.mEnabledMask.to_ulong(), 7u);
86 
87     blendStateExt.setEnabledIndexed(1, false);
88     ASSERT_EQ(blendStateExt.mEnabledMask.to_ulong(), 5u);
89 }
90 
91 // Test color write mask manipulations
TEST(BlendStateExt,ColorMask)92 TEST(BlendStateExt, ColorMask)
93 {
94     gl::BlendStateExt blendStateExt = gl::BlendStateExt(5);
95 
96     blendStateExt.setColorMask(true, false, true, false);
97     ASSERT_EQ(blendStateExt.mColorMask, is64Bit ? 0x0505050505u : 0x55555u);
98 
99     blendStateExt.setColorMaskIndexed(3, false, true, false, true);
100     ASSERT_EQ(blendStateExt.mColorMask, is64Bit ? 0x050A050505u : 0x5A555u);
101 
102     blendStateExt.setColorMaskIndexed(3, 0xF);
103     ASSERT_EQ(blendStateExt.getColorMaskIndexed(3), 0xF);
104 
105     blendStateExt.setColorMaskIndexed(3, 0xA);
106     ASSERT_EQ(blendStateExt.getColorMaskIndexed(3), 0xA);
107 
108     bool r, g, b, a;
109     blendStateExt.getColorMaskIndexed(3, &r, &g, &b, &a);
110     ASSERT_FALSE(r);
111     ASSERT_TRUE(g);
112     ASSERT_FALSE(b);
113     ASSERT_TRUE(a);
114 
115     gl::BlendStateExt::ColorMaskStorage::Type otherColorMask =
116         blendStateExt.expandColorMaskIndexed(3);
117     ASSERT_EQ(otherColorMask, is64Bit ? 0x0A0A0A0A0Au : 0xAAAAAu);
118 
119     const gl::DrawBufferMask diff = blendStateExt.compareColorMask(otherColorMask);
120     ASSERT_EQ(diff.to_ulong(), 23u);
121 }
122 
123 // Test blend equations manipulations
TEST(BlendStateExt,BlendEquations)124 TEST(BlendStateExt, BlendEquations)
125 {
126     gl::BlendStateExt blendStateExt = gl::BlendStateExt(7);
127 
128     blendStateExt.setEquations(GL_MIN, GL_FUNC_SUBTRACT);
129     ASSERT_EQ(blendStateExt.mEquationColor, is64Bit ? 0x01010101010101u : 0x1111111u);
130     ASSERT_EQ(blendStateExt.mEquationAlpha, is64Bit ? 0x04040404040404u : 0x4444444u);
131 
132     blendStateExt.setEquationsIndexed(3, GL_MAX, GL_FUNC_SUBTRACT);
133     blendStateExt.setEquationsIndexed(5, GL_MIN, GL_FUNC_ADD);
134     ASSERT_EQ(blendStateExt.mEquationColor, is64Bit ? 0x01010102010101u : 0x1112111u);
135     ASSERT_EQ(blendStateExt.mEquationAlpha, is64Bit ? 0x04000404040404u : 0x4044444u);
136     ASSERT_EQ(blendStateExt.getEquationColorIndexed(3), static_cast<GLenum>(GL_MAX));
137     ASSERT_EQ(blendStateExt.getEquationAlphaIndexed(5), static_cast<GLenum>(GL_FUNC_ADD));
138 
139     gl::BlendStateExt::EquationStorage::Type otherEquationColor =
140         blendStateExt.expandEquationColorIndexed(0);
141     gl::BlendStateExt::EquationStorage::Type otherEquationAlpha =
142         blendStateExt.expandEquationAlphaIndexed(0);
143 
144     ASSERT_EQ(otherEquationColor, is64Bit ? 0x01010101010101u : 0x1111111u);
145     ASSERT_EQ(otherEquationAlpha, is64Bit ? 0x04040404040404u : 0x4444444u);
146 
147     const gl::DrawBufferMask diff =
148         blendStateExt.compareEquations(otherEquationColor, otherEquationAlpha);
149     ASSERT_EQ(diff.to_ulong(), 40u);
150 
151     // Copy buffer 3 to buffer 0
152     blendStateExt.setEquationsIndexed(0, 3, blendStateExt);
153     ASSERT_EQ(blendStateExt.getEquationColorIndexed(0), static_cast<GLenum>(GL_MAX));
154     ASSERT_EQ(blendStateExt.getEquationAlphaIndexed(0), static_cast<GLenum>(GL_FUNC_SUBTRACT));
155 
156     // Copy buffer 5 to buffer 0
157     blendStateExt.setEquationsIndexed(0, 5, blendStateExt);
158     ASSERT_EQ(blendStateExt.getEquationColorIndexed(0), static_cast<GLenum>(GL_MIN));
159     ASSERT_EQ(blendStateExt.getEquationAlphaIndexed(0), static_cast<GLenum>(GL_FUNC_ADD));
160 }
161 
162 // Test blend factors manipulations
TEST(BlendStateExt,BlendFactors)163 TEST(BlendStateExt, BlendFactors)
164 {
165     gl::BlendStateExt blendStateExt = gl::BlendStateExt(8);
166 
167     blendStateExt.setFactors(GL_SRC_COLOR, GL_DST_COLOR, GL_SRC_ALPHA, GL_DST_ALPHA);
168     ASSERT_EQ(blendStateExt.mSrcColor, 0x0202020202020202u);
169     ASSERT_EQ(blendStateExt.mDstColor, 0x0808080808080808u);
170     ASSERT_EQ(blendStateExt.mSrcAlpha, 0x0404040404040404u);
171     ASSERT_EQ(blendStateExt.mDstAlpha, 0x0606060606060606u);
172 
173     blendStateExt.setFactorsIndexed(0, GL_ONE, GL_DST_COLOR, GL_SRC_ALPHA, GL_DST_ALPHA);
174     blendStateExt.setFactorsIndexed(3, GL_SRC_COLOR, GL_ONE, GL_SRC_ALPHA, GL_DST_ALPHA);
175     blendStateExt.setFactorsIndexed(5, GL_SRC_COLOR, GL_DST_COLOR, GL_ONE, GL_DST_ALPHA);
176     blendStateExt.setFactorsIndexed(7, GL_SRC_COLOR, GL_DST_COLOR, GL_SRC_ALPHA, GL_ONE);
177     ASSERT_EQ(blendStateExt.mSrcColor, 0x0202020202020201u);
178     ASSERT_EQ(blendStateExt.mDstColor, 0x0808080801080808u);
179     ASSERT_EQ(blendStateExt.mSrcAlpha, 0x0404010404040404u);
180     ASSERT_EQ(blendStateExt.mDstAlpha, 0x0106060606060606u);
181 
182     ASSERT_EQ(blendStateExt.getSrcColorIndexed(0), static_cast<GLenum>(GL_ONE));
183     ASSERT_EQ(blendStateExt.getDstColorIndexed(3), static_cast<GLenum>(GL_ONE));
184     ASSERT_EQ(blendStateExt.getSrcAlphaIndexed(5), static_cast<GLenum>(GL_ONE));
185     ASSERT_EQ(blendStateExt.getDstAlphaIndexed(7), static_cast<GLenum>(GL_ONE));
186 
187     gl::BlendStateExt::FactorStorage::Type otherSrcColor = blendStateExt.expandSrcColorIndexed(1);
188     gl::BlendStateExt::FactorStorage::Type otherDstColor = blendStateExt.expandDstColorIndexed(1);
189     gl::BlendStateExt::FactorStorage::Type otherSrcAlpha = blendStateExt.expandSrcAlphaIndexed(1);
190     gl::BlendStateExt::FactorStorage::Type otherDstAlpha = blendStateExt.expandDstAlphaIndexed(1);
191 
192     ASSERT_EQ(otherSrcColor, 0x0202020202020202u);
193     ASSERT_EQ(otherDstColor, 0x0808080808080808u);
194     ASSERT_EQ(otherSrcAlpha, 0x0404040404040404u);
195     ASSERT_EQ(otherDstAlpha, 0x0606060606060606u);
196 
197     const gl::DrawBufferMask diff =
198         blendStateExt.compareFactors(otherSrcColor, otherDstColor, otherSrcAlpha, otherDstAlpha);
199     ASSERT_EQ(diff.to_ulong(), 169u);
200 
201     // Copy buffer 0 to buffer 1
202     blendStateExt.setFactorsIndexed(1, 0, blendStateExt);
203     ASSERT_EQ(blendStateExt.getSrcColorIndexed(1), static_cast<GLenum>(GL_ONE));
204     ASSERT_EQ(blendStateExt.getDstColorIndexed(1), static_cast<GLenum>(GL_DST_COLOR));
205     ASSERT_EQ(blendStateExt.getSrcAlphaIndexed(1), static_cast<GLenum>(GL_SRC_ALPHA));
206     ASSERT_EQ(blendStateExt.getDstAlphaIndexed(1), static_cast<GLenum>(GL_DST_ALPHA));
207 
208     // Copy buffer 3 to buffer 1
209     blendStateExt.setFactorsIndexed(1, 3, blendStateExt);
210     ASSERT_EQ(blendStateExt.getSrcColorIndexed(1), static_cast<GLenum>(GL_SRC_COLOR));
211     ASSERT_EQ(blendStateExt.getDstColorIndexed(1), static_cast<GLenum>(GL_ONE));
212     ASSERT_EQ(blendStateExt.getSrcAlphaIndexed(1), static_cast<GLenum>(GL_SRC_ALPHA));
213     ASSERT_EQ(blendStateExt.getDstAlphaIndexed(1), static_cast<GLenum>(GL_DST_ALPHA));
214 
215     // Copy buffer 5 to buffer 1
216     blendStateExt.setFactorsIndexed(1, 5, blendStateExt);
217     ASSERT_EQ(blendStateExt.getSrcColorIndexed(1), static_cast<GLenum>(GL_SRC_COLOR));
218     ASSERT_EQ(blendStateExt.getDstColorIndexed(1), static_cast<GLenum>(GL_DST_COLOR));
219     ASSERT_EQ(blendStateExt.getSrcAlphaIndexed(1), static_cast<GLenum>(GL_ONE));
220     ASSERT_EQ(blendStateExt.getDstAlphaIndexed(1), static_cast<GLenum>(GL_DST_ALPHA));
221 
222     // Copy buffer 7 to buffer 1
223     blendStateExt.setFactorsIndexed(1, 7, blendStateExt);
224     ASSERT_EQ(blendStateExt.getSrcColorIndexed(1), static_cast<GLenum>(GL_SRC_COLOR));
225     ASSERT_EQ(blendStateExt.getDstColorIndexed(1), static_cast<GLenum>(GL_DST_COLOR));
226     ASSERT_EQ(blendStateExt.getSrcAlphaIndexed(1), static_cast<GLenum>(GL_SRC_ALPHA));
227     ASSERT_EQ(blendStateExt.getDstAlphaIndexed(1), static_cast<GLenum>(GL_ONE));
228 }
229 
230 // Test clip rectangle
TEST(Rectangle,Clip)231 TEST(Rectangle, Clip)
232 {
233     const gl::Rectangle source(0, 0, 100, 200);
234     const gl::Rectangle clip1(0, 0, 50, 100);
235     gl::Rectangle result;
236 
237     ASSERT_TRUE(gl::ClipRectangle(source, clip1, &result));
238     ASSERT_EQ(result.x, 0);
239     ASSERT_EQ(result.y, 0);
240     ASSERT_EQ(result.width, 50);
241     ASSERT_EQ(result.height, 100);
242 
243     gl::Rectangle clip2(10, 20, 30, 40);
244 
245     ASSERT_TRUE(gl::ClipRectangle(source, clip2, &result));
246     ASSERT_EQ(result.x, 10);
247     ASSERT_EQ(result.y, 20);
248     ASSERT_EQ(result.width, 30);
249     ASSERT_EQ(result.height, 40);
250 
251     gl::Rectangle clip3(-20, -30, 10000, 400000);
252 
253     ASSERT_TRUE(gl::ClipRectangle(source, clip3, &result));
254     ASSERT_EQ(result.x, 0);
255     ASSERT_EQ(result.y, 0);
256     ASSERT_EQ(result.width, 100);
257     ASSERT_EQ(result.height, 200);
258 
259     gl::Rectangle clip4(50, 100, -20, -30);
260 
261     ASSERT_TRUE(gl::ClipRectangle(source, clip4, &result));
262     ASSERT_EQ(result.x, 30);
263     ASSERT_EQ(result.y, 70);
264     ASSERT_EQ(result.width, 20);
265     ASSERT_EQ(result.height, 30);
266 
267     // Non-overlapping rectangles
268     gl::Rectangle clip5(-100, 0, 99, 200);
269     ASSERT_FALSE(gl::ClipRectangle(source, clip5, nullptr));
270 
271     gl::Rectangle clip6(0, -100, 100, 99);
272     ASSERT_FALSE(gl::ClipRectangle(source, clip6, nullptr));
273 
274     gl::Rectangle clip7(101, 0, 99, 200);
275     ASSERT_FALSE(gl::ClipRectangle(source, clip7, nullptr));
276 
277     gl::Rectangle clip8(0, 201, 100, 99);
278     ASSERT_FALSE(gl::ClipRectangle(source, clip8, nullptr));
279 
280     // Zero-width/height rectangles
281     gl::Rectangle clip9(50, 0, 0, 200);
282     ASSERT_FALSE(gl::ClipRectangle(source, clip9, nullptr));
283     ASSERT_FALSE(gl::ClipRectangle(clip9, source, nullptr));
284 
285     gl::Rectangle clip10(0, 100, 100, 0);
286     ASSERT_FALSE(gl::ClipRectangle(source, clip10, nullptr));
287     ASSERT_FALSE(gl::ClipRectangle(clip10, source, nullptr));
288 }
289 
290 // Test combine rectangles
TEST(Rectangle,Combine)291 TEST(Rectangle, Combine)
292 {
293     const gl::Rectangle rect1(0, 0, 100, 200);
294     const gl::Rectangle rect2(0, 0, 50, 100);
295     gl::Rectangle result;
296 
297     gl::GetEnclosingRectangle(rect1, rect2, &result);
298     ASSERT_EQ(result.x0(), 0);
299     ASSERT_EQ(result.y0(), 0);
300     ASSERT_EQ(result.x1(), 100);
301     ASSERT_EQ(result.y1(), 200);
302 
303     const gl::Rectangle rect3(50, 100, 100, 200);
304 
305     gl::GetEnclosingRectangle(rect1, rect3, &result);
306     ASSERT_EQ(result.x0(), 0);
307     ASSERT_EQ(result.y0(), 0);
308     ASSERT_EQ(result.x1(), 150);
309     ASSERT_EQ(result.y1(), 300);
310 
311     const gl::Rectangle rect4(-20, -30, 100, 200);
312 
313     gl::GetEnclosingRectangle(rect1, rect4, &result);
314     ASSERT_EQ(result.x0(), -20);
315     ASSERT_EQ(result.y0(), -30);
316     ASSERT_EQ(result.x1(), 100);
317     ASSERT_EQ(result.y1(), 200);
318 
319     const gl::Rectangle rect5(10, -30, 100, 200);
320 
321     gl::GetEnclosingRectangle(rect1, rect5, &result);
322     ASSERT_EQ(result.x0(), 0);
323     ASSERT_EQ(result.y0(), -30);
324     ASSERT_EQ(result.x1(), 110);
325     ASSERT_EQ(result.y1(), 200);
326 }
327 
328 // Test extend rectangles
TEST(Rectangle,Extend)329 TEST(Rectangle, Extend)
330 {
331     const gl::Rectangle source(0, 0, 100, 200);
332     const gl::Rectangle extend1(0, 0, 50, 100);
333     gl::Rectangle result;
334 
335     //  +------+       +------+
336     //  |   |  |       |      |
337     //  +---+  |  -->  |      |
338     //  |      |       |      |
339     //  +------+       +------+
340     //
341     gl::ExtendRectangle(source, extend1, &result);
342     ASSERT_EQ(result.x0(), 0);
343     ASSERT_EQ(result.y0(), 0);
344     ASSERT_EQ(result.x1(), 100);
345     ASSERT_EQ(result.y1(), 200);
346 
347     //  +------+           +------+
348     //  |S     |           |      |
349     //  |   +--+---+  -->  |      |
350     //  |   |  |   |       |      |
351     //  +---+--+   +       +------+
352     //      |      |
353     //      +------+
354     //
355     const gl::Rectangle extend2(50, 100, 100, 200);
356 
357     gl::ExtendRectangle(source, extend2, &result);
358     ASSERT_EQ(result.x0(), 0);
359     ASSERT_EQ(result.y0(), 0);
360     ASSERT_EQ(result.x1(), 100);
361     ASSERT_EQ(result.y1(), 200);
362 
363     //    +------+           +------+
364     //    |S     |           |      |
365     //  +-+------+---+  -->  |      |
366     //  | |      |   |       |      |
367     //  | +------+   +       |      |
368     //  |            |       |      |
369     //  +------------+       +------+
370     //
371     const gl::Rectangle extend3(-10, 100, 200, 200);
372 
373     gl::ExtendRectangle(source, extend3, &result);
374     ASSERT_EQ(result.x0(), 0);
375     ASSERT_EQ(result.y0(), 0);
376     ASSERT_EQ(result.x1(), 100);
377     ASSERT_EQ(result.y1(), 300);
378 
379     //    +------+           +------+
380     //    |S     |           |      |
381     //    |      |      -->  |      |
382     //    |      |           |      |
383     //  +-+------+---+       |      |
384     //  |            |       |      |
385     //  +------------+       +------+
386     //
387     for (int offsetLeft = 10; offsetLeft >= 0; offsetLeft -= 10)
388     {
389         for (int offsetRight = 10; offsetRight >= 0; offsetRight -= 10)
390         {
391             const gl::Rectangle extend4(-offsetLeft, 200, 100 + offsetLeft + offsetRight, 100);
392 
393             gl::ExtendRectangle(source, extend4, &result);
394             ASSERT_EQ(result.x0(), 0) << offsetLeft << " " << offsetRight;
395             ASSERT_EQ(result.y0(), 0) << offsetLeft << " " << offsetRight;
396             ASSERT_EQ(result.x1(), 100) << offsetLeft << " " << offsetRight;
397             ASSERT_EQ(result.y1(), 300) << offsetLeft << " " << offsetRight;
398         }
399     }
400 
401     // Similar to extend4, but with the second rectangle on the top, left and right.
402     for (int offsetLeft = 10; offsetLeft >= 0; offsetLeft -= 10)
403     {
404         for (int offsetRight = 10; offsetRight >= 0; offsetRight -= 10)
405         {
406             const gl::Rectangle extend4(-offsetLeft, -100, 100 + offsetLeft + offsetRight, 100);
407 
408             gl::ExtendRectangle(source, extend4, &result);
409             ASSERT_EQ(result.x0(), 0) << offsetLeft << " " << offsetRight;
410             ASSERT_EQ(result.y0(), -100) << offsetLeft << " " << offsetRight;
411             ASSERT_EQ(result.x1(), 100) << offsetLeft << " " << offsetRight;
412             ASSERT_EQ(result.y1(), 200) << offsetLeft << " " << offsetRight;
413         }
414     }
415     for (int offsetTop = 10; offsetTop >= 0; offsetTop -= 10)
416     {
417         for (int offsetBottom = 10; offsetBottom >= 0; offsetBottom -= 10)
418         {
419             const gl::Rectangle extend4(-50, -offsetTop, 50, 200 + offsetTop + offsetBottom);
420 
421             gl::ExtendRectangle(source, extend4, &result);
422             ASSERT_EQ(result.x0(), -50) << offsetTop << " " << offsetBottom;
423             ASSERT_EQ(result.y0(), 0) << offsetTop << " " << offsetBottom;
424             ASSERT_EQ(result.x1(), 100) << offsetTop << " " << offsetBottom;
425             ASSERT_EQ(result.y1(), 200) << offsetTop << " " << offsetBottom;
426         }
427     }
428     for (int offsetTop = 10; offsetTop >= 0; offsetTop -= 10)
429     {
430         for (int offsetBottom = 10; offsetBottom >= 0; offsetBottom -= 10)
431         {
432             const gl::Rectangle extend4(100, -offsetTop, 50, 200 + offsetTop + offsetBottom);
433 
434             gl::ExtendRectangle(source, extend4, &result);
435             ASSERT_EQ(result.x0(), 0) << offsetTop << " " << offsetBottom;
436             ASSERT_EQ(result.y0(), 0) << offsetTop << " " << offsetBottom;
437             ASSERT_EQ(result.x1(), 150) << offsetTop << " " << offsetBottom;
438             ASSERT_EQ(result.y1(), 200) << offsetTop << " " << offsetBottom;
439         }
440     }
441 
442     //    +------+           +------+
443     //    |S     |           |      |
444     //    |      |      -->  |      |
445     //    |      |           |      |
446     //    +------+           +------+
447     //  +------------+
448     //  |            |
449     //  +------------+
450     //
451     const gl::Rectangle extend5(-10, 201, 120, 100);
452 
453     gl::ExtendRectangle(source, extend5, &result);
454     ASSERT_EQ(result.x0(), 0);
455     ASSERT_EQ(result.y0(), 0);
456     ASSERT_EQ(result.x1(), 100);
457     ASSERT_EQ(result.y1(), 200);
458 
459     // Similar to extend5, but with the second rectangle on the top, left and right.
460     const gl::Rectangle extend6(-10, -101, 120, 100);
461 
462     gl::ExtendRectangle(source, extend6, &result);
463     ASSERT_EQ(result.x0(), 0);
464     ASSERT_EQ(result.y0(), 0);
465     ASSERT_EQ(result.x1(), 100);
466     ASSERT_EQ(result.y1(), 200);
467 
468     const gl::Rectangle extend7(-101, -10, 100, 220);
469 
470     gl::ExtendRectangle(source, extend7, &result);
471     ASSERT_EQ(result.x0(), 0);
472     ASSERT_EQ(result.y0(), 0);
473     ASSERT_EQ(result.x1(), 100);
474     ASSERT_EQ(result.y1(), 200);
475 
476     const gl::Rectangle extend8(101, -10, 100, 220);
477 
478     gl::ExtendRectangle(source, extend8, &result);
479     ASSERT_EQ(result.x0(), 0);
480     ASSERT_EQ(result.y0(), 0);
481     ASSERT_EQ(result.x1(), 100);
482     ASSERT_EQ(result.y1(), 200);
483 
484     //  +-------------+       +-------------+
485     //  |   +------+  |       |             |
486     //  |   |S     |  |       |             |
487     //  |   |      |  |  -->  |             |
488     //  |   |      |  |       |             |
489     //  |   +------+  |       |             |
490     //  +-------------+       +-------------+
491     //
492     const gl::Rectangle extend9(-100, -100, 300, 400);
493 
494     gl::ExtendRectangle(source, extend9, &result);
495     ASSERT_EQ(result.x0(), -100);
496     ASSERT_EQ(result.y0(), -100);
497     ASSERT_EQ(result.x1(), 200);
498     ASSERT_EQ(result.y1(), 300);
499 }
500 
501 }  // namespace angle
502