xref: /aosp_15_r20/external/angle/src/libANGLE/BlendStateExt_unittest.cpp (revision 8975f5c5ed3d1c378011245431ada316dfb6f244)
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 // BlendStateExt_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 
22 // Test the initial state of BlendStateExt
TEST(BlendStateExt,Init)23 TEST(BlendStateExt, Init)
24 {
25     const std::array<uint8_t, 9> allEnabledMasks = {0, 1, 3, 7, 15, 31, 63, 127, 255};
26 
27     const std::array<uint32_t, 9> allColorMasks32 = {
28         0, 0xF, 0xFF, 0xFFF, 0xFFFF, 0xFFFFF, 0xFFFFFF, 0xFFFFFFF, 0xFFFFFFFF};
29 
30     const std::array<uint64_t, 9> allColorMasks64 = {
31         0x0000000000000000, 0x000000000000000F, 0x0000000000000F0F,
32         0x00000000000F0F0F, 0x000000000F0F0F0F, 0x0000000F0F0F0F0F,
33         0x00000F0F0F0F0F0F, 0x000F0F0F0F0F0F0F, 0x0F0F0F0F0F0F0F0F};
34 
35     const std::array<uint64_t, 9> sourceColorAlpha = {
36         0x0000000000000000, 0x0000000000000001, 0x0000000000000101,
37         0x0000000000010101, 0x0000000001010101, 0x0000000101010101,
38         0x0000010101010101, 0x0001010101010101, 0x0101010101010101};
39 
40     for (size_t c = 1; c <= 8; ++c)
41     {
42         const gl::BlendStateExt blendStateExt = gl::BlendStateExt(c);
43         ASSERT_EQ(blendStateExt.getDrawBufferCount(), c);
44 
45         ASSERT_EQ(blendStateExt.getEnabledMask().to_ulong(), 0u);
46         ASSERT_EQ(blendStateExt.getAllEnabledMask().to_ulong(), allEnabledMasks[c]);
47 
48         ASSERT_EQ(blendStateExt.getColorMaskBits(), blendStateExt.getAllColorMaskBits());
49         ASSERT_EQ(blendStateExt.getAllColorMaskBits(),
50                   is64Bit ? allColorMasks64[c] : allColorMasks32[c]);
51 
52         ASSERT_EQ(blendStateExt.getUsesAdvancedBlendEquationMask().to_ulong(), 0u);
53 
54         ASSERT_EQ(blendStateExt.getUsesExtendedBlendFactorMask().to_ulong(), 0u);
55 
56         ASSERT_EQ(blendStateExt.getSrcColorBits(), sourceColorAlpha[c]);
57         ASSERT_EQ(blendStateExt.getSrcAlphaBits(), sourceColorAlpha[c]);
58         ASSERT_EQ(blendStateExt.getDstColorBits(), 0u);
59         ASSERT_EQ(blendStateExt.getDstAlphaBits(), 0u);
60 
61         ASSERT_EQ(blendStateExt.getEquationColorBits(), 0u);
62         ASSERT_EQ(blendStateExt.getEquationAlphaBits(), 0u);
63 
64         for (size_t i = 0; i < c; ++i)
65         {
66             ASSERT_FALSE(blendStateExt.getEnabledMask().test(i));
67 
68             bool r, g, b, a;
69             blendStateExt.getColorMaskIndexed(i, &r, &g, &b, &a);
70             ASSERT_TRUE(r);
71             ASSERT_TRUE(g);
72             ASSERT_TRUE(b);
73             ASSERT_TRUE(a);
74 
75             ASSERT_EQ(blendStateExt.getEquationColorIndexed(i), gl::BlendEquationType::Add);
76             ASSERT_EQ(blendStateExt.getEquationAlphaIndexed(i), gl::BlendEquationType::Add);
77 
78             ASSERT_EQ(blendStateExt.getSrcColorIndexed(i), gl::BlendFactorType::One);
79             ASSERT_EQ(blendStateExt.getDstColorIndexed(i), gl::BlendFactorType::Zero);
80             ASSERT_EQ(blendStateExt.getSrcAlphaIndexed(i), gl::BlendFactorType::One);
81             ASSERT_EQ(blendStateExt.getDstAlphaIndexed(i), gl::BlendFactorType::Zero);
82         }
83     }
84 }
85 
86 // Test blend enabled flags
TEST(BlendStateExt,BlendEnabled)87 TEST(BlendStateExt, BlendEnabled)
88 {
89     const std::array<uint8_t, 9> enabled = {0, 1, 3, 7, 15, 31, 63, 127, 255};
90 
91     for (size_t c = 1; c <= 8; c++)
92     {
93         gl::BlendStateExt blendStateExt = gl::BlendStateExt(c);
94 
95         blendStateExt.setEnabled(true);
96         ASSERT_EQ(blendStateExt.getEnabledMask().to_ulong(), enabled[c]);
97 
98         blendStateExt.setEnabled(false);
99         ASSERT_EQ(blendStateExt.getEnabledMask().to_ulong(), 0u);
100 
101         blendStateExt.setEnabledIndexed(c / 2, true);
102         ASSERT_EQ(blendStateExt.getEnabledMask().to_ulong(), 1u << (c / 2));
103 
104         blendStateExt.setEnabledIndexed(c / 2, false);
105         ASSERT_EQ(blendStateExt.getEnabledMask().to_ulong(), 0u);
106     }
107 }
108 
validateMaskPacking(const uint8_t packed,const bool r,const bool g,const bool b,const bool a)109 void validateMaskPacking(const uint8_t packed,
110                          const bool r,
111                          const bool g,
112                          const bool b,
113                          const bool a)
114 {
115     ASSERT_EQ(gl::BlendStateExt::PackColorMask(r, g, b, a), packed);
116 
117     bool rOut, gOut, bOut, aOut;
118     gl::BlendStateExt::UnpackColorMask(packed, &rOut, &gOut, &bOut, &aOut);
119     ASSERT_EQ(r, rOut);
120     ASSERT_EQ(g, gOut);
121     ASSERT_EQ(b, bOut);
122     ASSERT_EQ(a, aOut);
123 }
124 
125 // Test color write mask packing
TEST(BlendStateExt,ColorMaskPacking)126 TEST(BlendStateExt, ColorMaskPacking)
127 {
128     validateMaskPacking(0x0, false, false, false, false);
129     validateMaskPacking(0x1, true, false, false, false);
130     validateMaskPacking(0x2, false, true, false, false);
131     validateMaskPacking(0x3, true, true, false, false);
132     validateMaskPacking(0x4, false, false, true, false);
133     validateMaskPacking(0x5, true, false, true, false);
134     validateMaskPacking(0x6, false, true, true, false);
135     validateMaskPacking(0x7, true, true, true, false);
136     validateMaskPacking(0x8, false, false, false, true);
137     validateMaskPacking(0x9, true, false, false, true);
138     validateMaskPacking(0xA, false, true, false, true);
139     validateMaskPacking(0xB, true, true, false, true);
140     validateMaskPacking(0xC, false, false, true, true);
141     validateMaskPacking(0xD, true, false, true, true);
142     validateMaskPacking(0xE, false, true, true, true);
143     validateMaskPacking(0xF, true, true, true, true);
144 }
145 
146 // Test color write mask manipulations
TEST(BlendStateExt,ColorMask)147 TEST(BlendStateExt, ColorMask)
148 {
149     const std::array<uint32_t, 9> startSingleValue32 = {0x00000000, 0x00000005, 0x00000055,
150                                                         0x00000555, 0x00005555, 0x00055555,
151                                                         0x00555555, 0x05555555, 0x55555555};
152 
153     const std::array<uint64_t, 9> startSingleValue64 = {
154         0x0000000000000000, 0x0000000000000005, 0x0000000000000505,
155         0x0000000000050505, 0x0000000005050505, 0x0000000505050505,
156         0x0000050505050505, 0x0005050505050505, 0x0505050505050505};
157 
158     for (size_t c = 1; c <= 8; c++)
159     {
160         gl::BlendStateExt blendStateExt = gl::BlendStateExt(c);
161 
162         blendStateExt.setColorMask(true, false, true, false);
163         ASSERT_EQ(blendStateExt.getColorMaskBits(),
164                   is64Bit ? startSingleValue64[c] : startSingleValue32[c]);
165 
166         blendStateExt.setColorMaskIndexed(c / 2, false, true, false, true);
167         for (size_t i = 0; i < c; ++i)
168         {
169             ASSERT_EQ(blendStateExt.getColorMaskIndexed(i), i == c / 2 ? 0xAu : 0x5u);
170         }
171 
172         blendStateExt.setColorMaskIndexed(0, 0xF);
173         bool r, g, b, a;
174         blendStateExt.getColorMaskIndexed(0, &r, &g, &b, &a);
175         ASSERT_TRUE(r);
176         ASSERT_TRUE(g);
177         ASSERT_TRUE(b);
178         ASSERT_TRUE(a);
179 
180         blendStateExt.setColorMaskIndexed(c - 1, true, false, true, true);
181         gl::BlendStateExt::ColorMaskStorage::Type otherColorMask =
182             blendStateExt.expandColorMaskIndexed(c - 1);
183         for (size_t i = 0; i < c; ++i)
184         {
185             ASSERT_EQ(gl::BlendStateExt::ColorMaskStorage::GetValueIndexed(i, otherColorMask), 0xD);
186         }
187 
188         // All masks are different except the c-th
189         {
190             const gl::DrawBufferMask diff = blendStateExt.compareColorMask(otherColorMask);
191             ASSERT_EQ(diff.to_ulong(), 127u >> (8 - c));
192         }
193 
194         // Test that all-enabled color mask correctly compares with the current color mask
195         {
196             blendStateExt.setColorMask(true, true, true, true);
197             blendStateExt.setColorMaskIndexed(c / 2, false, false, true, false);
198             const gl::DrawBufferMask diff =
199                 blendStateExt.compareColorMask(blendStateExt.getAllColorMaskBits());
200             ASSERT_EQ(diff.to_ulong(), 1u << (c / 2));
201         }
202     }
203 }
204 
205 // Test blend equations manipulations
TEST(BlendStateExt,BlendEquations)206 TEST(BlendStateExt, BlendEquations)
207 {
208     gl::BlendStateExt blendStateExt = gl::BlendStateExt(7);
209 
210     blendStateExt.setEquations(GL_MIN, GL_FUNC_SUBTRACT);
211     ASSERT_EQ(blendStateExt.getEquationColorBits(), 0x01010101010101u);
212     ASSERT_EQ(blendStateExt.getEquationAlphaBits(), 0x04040404040404u);
213 
214     blendStateExt.setEquationsIndexed(3, GL_MAX, GL_FUNC_SUBTRACT);
215     blendStateExt.setEquationsIndexed(5, GL_MIN, GL_FUNC_ADD);
216     ASSERT_EQ(blendStateExt.getEquationColorBits(), 0x01010102010101u);
217     ASSERT_EQ(blendStateExt.getEquationAlphaBits(), 0x04000404040404u);
218     ASSERT_EQ(blendStateExt.getEquationColorIndexed(3), gl::BlendEquationType::Max);
219     ASSERT_EQ(blendStateExt.getEquationAlphaIndexed(5), gl::BlendEquationType::Add);
220 
221     gl::BlendStateExt::EquationStorage::Type otherEquationColor =
222         blendStateExt.expandEquationColorIndexed(0);
223     gl::BlendStateExt::EquationStorage::Type otherEquationAlpha =
224         blendStateExt.expandEquationAlphaIndexed(0);
225 
226     ASSERT_EQ(otherEquationColor, 0x01010101010101u);
227     ASSERT_EQ(otherEquationAlpha, 0x04040404040404u);
228 
229     const gl::DrawBufferMask diff =
230         blendStateExt.compareEquations(otherEquationColor, otherEquationAlpha);
231     ASSERT_EQ(diff.to_ulong(), 40u);
232 
233     // Copy buffer 3 to buffer 0
234     blendStateExt.setEquationsIndexed(0, 3, blendStateExt);
235     ASSERT_EQ(blendStateExt.getEquationColorIndexed(0), gl::BlendEquationType::Max);
236     ASSERT_EQ(blendStateExt.getEquationAlphaIndexed(0), gl::BlendEquationType::Subtract);
237 
238     // Copy buffer 5 to buffer 0
239     blendStateExt.setEquationsIndexed(0, 5, blendStateExt);
240     ASSERT_EQ(blendStateExt.getEquationColorIndexed(0), gl::BlendEquationType::Min);
241     ASSERT_EQ(blendStateExt.getEquationAlphaIndexed(0), gl::BlendEquationType::Add);
242 }
243 
244 // Test blend factors manipulations
TEST(BlendStateExt,BlendFactors)245 TEST(BlendStateExt, BlendFactors)
246 {
247     gl::BlendStateExt blendStateExt = gl::BlendStateExt(8);
248 
249     blendStateExt.setFactors(GL_SRC_COLOR, GL_DST_COLOR, GL_SRC_ALPHA, GL_DST_ALPHA);
250     ASSERT_EQ(blendStateExt.getSrcColorBits(), 0x0202020202020202u);
251     ASSERT_EQ(blendStateExt.getDstColorBits(), 0x0808080808080808u);
252     ASSERT_EQ(blendStateExt.getSrcAlphaBits(), 0x0404040404040404u);
253     ASSERT_EQ(blendStateExt.getDstAlphaBits(), 0x0606060606060606u);
254 
255     blendStateExt.setFactorsIndexed(0, GL_ONE, GL_DST_COLOR, GL_SRC_ALPHA, GL_DST_ALPHA);
256     blendStateExt.setFactorsIndexed(3, GL_SRC_COLOR, GL_ONE, GL_SRC_ALPHA, GL_DST_ALPHA);
257     blendStateExt.setFactorsIndexed(5, GL_SRC_COLOR, GL_DST_COLOR, GL_ONE, GL_DST_ALPHA);
258     blendStateExt.setFactorsIndexed(7, GL_SRC_COLOR, GL_DST_COLOR, GL_SRC_ALPHA, GL_ONE);
259     ASSERT_EQ(blendStateExt.getSrcColorBits(), 0x0202020202020201u);
260     ASSERT_EQ(blendStateExt.getDstColorBits(), 0x0808080801080808u);
261     ASSERT_EQ(blendStateExt.getSrcAlphaBits(), 0x0404010404040404u);
262     ASSERT_EQ(blendStateExt.getDstAlphaBits(), 0x0106060606060606u);
263 
264     ASSERT_EQ(blendStateExt.getSrcColorIndexed(0), gl::BlendFactorType::One);
265     ASSERT_EQ(blendStateExt.getDstColorIndexed(3), gl::BlendFactorType::One);
266     ASSERT_EQ(blendStateExt.getSrcAlphaIndexed(5), gl::BlendFactorType::One);
267     ASSERT_EQ(blendStateExt.getDstAlphaIndexed(7), gl::BlendFactorType::One);
268 
269     gl::BlendStateExt::FactorStorage::Type otherSrcColor = blendStateExt.expandSrcColorIndexed(1);
270     gl::BlendStateExt::FactorStorage::Type otherDstColor = blendStateExt.expandDstColorIndexed(1);
271     gl::BlendStateExt::FactorStorage::Type otherSrcAlpha = blendStateExt.expandSrcAlphaIndexed(1);
272     gl::BlendStateExt::FactorStorage::Type otherDstAlpha = blendStateExt.expandDstAlphaIndexed(1);
273 
274     ASSERT_EQ(otherSrcColor, 0x0202020202020202u);
275     ASSERT_EQ(otherDstColor, 0x0808080808080808u);
276     ASSERT_EQ(otherSrcAlpha, 0x0404040404040404u);
277     ASSERT_EQ(otherDstAlpha, 0x0606060606060606u);
278 
279     const gl::DrawBufferMask diff =
280         blendStateExt.compareFactors(otherSrcColor, otherDstColor, otherSrcAlpha, otherDstAlpha);
281     ASSERT_EQ(diff.to_ulong(), 169u);
282 
283     // Copy buffer 0 to buffer 1
284     blendStateExt.setFactorsIndexed(1, 0, blendStateExt);
285     ASSERT_EQ(blendStateExt.getSrcColorIndexed(1), gl::BlendFactorType::One);
286     ASSERT_EQ(blendStateExt.getDstColorIndexed(1), gl::BlendFactorType::DstColor);
287     ASSERT_EQ(blendStateExt.getSrcAlphaIndexed(1), gl::BlendFactorType::SrcAlpha);
288     ASSERT_EQ(blendStateExt.getDstAlphaIndexed(1), gl::BlendFactorType::DstAlpha);
289 
290     // Copy buffer 3 to buffer 1
291     blendStateExt.setFactorsIndexed(1, 3, blendStateExt);
292     ASSERT_EQ(blendStateExt.getSrcColorIndexed(1), gl::BlendFactorType::SrcColor);
293     ASSERT_EQ(blendStateExt.getDstColorIndexed(1), gl::BlendFactorType::One);
294     ASSERT_EQ(blendStateExt.getSrcAlphaIndexed(1), gl::BlendFactorType::SrcAlpha);
295     ASSERT_EQ(blendStateExt.getDstAlphaIndexed(1), gl::BlendFactorType::DstAlpha);
296 
297     // Copy buffer 5 to buffer 1
298     blendStateExt.setFactorsIndexed(1, 5, blendStateExt);
299     ASSERT_EQ(blendStateExt.getSrcColorIndexed(1), gl::BlendFactorType::SrcColor);
300     ASSERT_EQ(blendStateExt.getDstColorIndexed(1), gl::BlendFactorType::DstColor);
301     ASSERT_EQ(blendStateExt.getSrcAlphaIndexed(1), gl::BlendFactorType::One);
302     ASSERT_EQ(blendStateExt.getDstAlphaIndexed(1), gl::BlendFactorType::DstAlpha);
303 
304     // Copy buffer 7 to buffer 1
305     blendStateExt.setFactorsIndexed(1, 7, blendStateExt);
306     ASSERT_EQ(blendStateExt.getSrcColorIndexed(1), gl::BlendFactorType::SrcColor);
307     ASSERT_EQ(blendStateExt.getDstColorIndexed(1), gl::BlendFactorType::DstColor);
308     ASSERT_EQ(blendStateExt.getSrcAlphaIndexed(1), gl::BlendFactorType::SrcAlpha);
309     ASSERT_EQ(blendStateExt.getDstAlphaIndexed(1), gl::BlendFactorType::One);
310 }
311 
312 // Test clip rectangle
TEST(Rectangle,Clip)313 TEST(Rectangle, Clip)
314 {
315     const gl::Rectangle source(0, 0, 100, 200);
316     const gl::Rectangle clip1(0, 0, 50, 100);
317     gl::Rectangle result;
318 
319     ASSERT_TRUE(gl::ClipRectangle(source, clip1, &result));
320     ASSERT_EQ(result.x, 0);
321     ASSERT_EQ(result.y, 0);
322     ASSERT_EQ(result.width, 50);
323     ASSERT_EQ(result.height, 100);
324 
325     gl::Rectangle clip2(10, 20, 30, 40);
326 
327     ASSERT_TRUE(gl::ClipRectangle(source, clip2, &result));
328     ASSERT_EQ(result.x, 10);
329     ASSERT_EQ(result.y, 20);
330     ASSERT_EQ(result.width, 30);
331     ASSERT_EQ(result.height, 40);
332 
333     gl::Rectangle clip3(-20, -30, 10000, 400000);
334 
335     ASSERT_TRUE(gl::ClipRectangle(source, clip3, &result));
336     ASSERT_EQ(result.x, 0);
337     ASSERT_EQ(result.y, 0);
338     ASSERT_EQ(result.width, 100);
339     ASSERT_EQ(result.height, 200);
340 
341     gl::Rectangle clip4(50, 100, -20, -30);
342 
343     ASSERT_TRUE(gl::ClipRectangle(source, clip4, &result));
344     ASSERT_EQ(result.x, 30);
345     ASSERT_EQ(result.y, 70);
346     ASSERT_EQ(result.width, 20);
347     ASSERT_EQ(result.height, 30);
348 
349     // Non-overlapping rectangles
350     gl::Rectangle clip5(-100, 0, 99, 200);
351     ASSERT_FALSE(gl::ClipRectangle(source, clip5, nullptr));
352 
353     gl::Rectangle clip6(0, -100, 100, 99);
354     ASSERT_FALSE(gl::ClipRectangle(source, clip6, nullptr));
355 
356     gl::Rectangle clip7(101, 0, 99, 200);
357     ASSERT_FALSE(gl::ClipRectangle(source, clip7, nullptr));
358 
359     gl::Rectangle clip8(0, 201, 100, 99);
360     ASSERT_FALSE(gl::ClipRectangle(source, clip8, nullptr));
361 
362     // Zero-width/height rectangles
363     gl::Rectangle clip9(50, 0, 0, 200);
364     ASSERT_FALSE(gl::ClipRectangle(source, clip9, nullptr));
365     ASSERT_FALSE(gl::ClipRectangle(clip9, source, nullptr));
366 
367     gl::Rectangle clip10(0, 100, 100, 0);
368     ASSERT_FALSE(gl::ClipRectangle(source, clip10, nullptr));
369     ASSERT_FALSE(gl::ClipRectangle(clip10, source, nullptr));
370 }
371 
372 // Test combine rectangles
TEST(Rectangle,Combine)373 TEST(Rectangle, Combine)
374 {
375     const gl::Rectangle rect1(0, 0, 100, 200);
376     const gl::Rectangle rect2(0, 0, 50, 100);
377     gl::Rectangle result;
378 
379     gl::GetEnclosingRectangle(rect1, rect2, &result);
380     ASSERT_EQ(result.x0(), 0);
381     ASSERT_EQ(result.y0(), 0);
382     ASSERT_EQ(result.x1(), 100);
383     ASSERT_EQ(result.y1(), 200);
384 
385     const gl::Rectangle rect3(50, 100, 100, 200);
386 
387     gl::GetEnclosingRectangle(rect1, rect3, &result);
388     ASSERT_EQ(result.x0(), 0);
389     ASSERT_EQ(result.y0(), 0);
390     ASSERT_EQ(result.x1(), 150);
391     ASSERT_EQ(result.y1(), 300);
392 
393     const gl::Rectangle rect4(-20, -30, 100, 200);
394 
395     gl::GetEnclosingRectangle(rect1, rect4, &result);
396     ASSERT_EQ(result.x0(), -20);
397     ASSERT_EQ(result.y0(), -30);
398     ASSERT_EQ(result.x1(), 100);
399     ASSERT_EQ(result.y1(), 200);
400 
401     const gl::Rectangle rect5(10, -30, 100, 200);
402 
403     gl::GetEnclosingRectangle(rect1, rect5, &result);
404     ASSERT_EQ(result.x0(), 0);
405     ASSERT_EQ(result.y0(), -30);
406     ASSERT_EQ(result.x1(), 110);
407     ASSERT_EQ(result.y1(), 200);
408 }
409 
410 // Test extend rectangles
TEST(Rectangle,Extend)411 TEST(Rectangle, Extend)
412 {
413     const gl::Rectangle source(0, 0, 100, 200);
414     const gl::Rectangle extend1(0, 0, 50, 100);
415     gl::Rectangle result;
416 
417     //  +------+       +------+
418     //  |   |  |       |      |
419     //  +---+  |  -->  |      |
420     //  |      |       |      |
421     //  +------+       +------+
422     //
423     gl::ExtendRectangle(source, extend1, &result);
424     ASSERT_EQ(result.x0(), 0);
425     ASSERT_EQ(result.y0(), 0);
426     ASSERT_EQ(result.x1(), 100);
427     ASSERT_EQ(result.y1(), 200);
428 
429     //  +------+           +------+
430     //  |S     |           |      |
431     //  |   +--+---+  -->  |      |
432     //  |   |  |   |       |      |
433     //  +---+--+   +       +------+
434     //      |      |
435     //      +------+
436     //
437     const gl::Rectangle extend2(50, 100, 100, 200);
438 
439     gl::ExtendRectangle(source, extend2, &result);
440     ASSERT_EQ(result.x0(), 0);
441     ASSERT_EQ(result.y0(), 0);
442     ASSERT_EQ(result.x1(), 100);
443     ASSERT_EQ(result.y1(), 200);
444 
445     //    +------+           +------+
446     //    |S     |           |      |
447     //  +-+------+---+  -->  |      |
448     //  | |      |   |       |      |
449     //  | +------+   +       |      |
450     //  |            |       |      |
451     //  +------------+       +------+
452     //
453     const gl::Rectangle extend3(-10, 100, 200, 200);
454 
455     gl::ExtendRectangle(source, extend3, &result);
456     ASSERT_EQ(result.x0(), 0);
457     ASSERT_EQ(result.y0(), 0);
458     ASSERT_EQ(result.x1(), 100);
459     ASSERT_EQ(result.y1(), 300);
460 
461     //    +------+           +------+
462     //    |S     |           |      |
463     //    |      |      -->  |      |
464     //    |      |           |      |
465     //  +-+------+---+       |      |
466     //  |            |       |      |
467     //  +------------+       +------+
468     //
469     for (int offsetLeft = 10; offsetLeft >= 0; offsetLeft -= 10)
470     {
471         for (int offsetRight = 10; offsetRight >= 0; offsetRight -= 10)
472         {
473             const gl::Rectangle extend4(-offsetLeft, 200, 100 + offsetLeft + offsetRight, 100);
474 
475             gl::ExtendRectangle(source, extend4, &result);
476             ASSERT_EQ(result.x0(), 0) << offsetLeft << " " << offsetRight;
477             ASSERT_EQ(result.y0(), 0) << offsetLeft << " " << offsetRight;
478             ASSERT_EQ(result.x1(), 100) << offsetLeft << " " << offsetRight;
479             ASSERT_EQ(result.y1(), 300) << offsetLeft << " " << offsetRight;
480         }
481     }
482 
483     // Similar to extend4, but with the second rectangle on the top, left and right.
484     for (int offsetLeft = 10; offsetLeft >= 0; offsetLeft -= 10)
485     {
486         for (int offsetRight = 10; offsetRight >= 0; offsetRight -= 10)
487         {
488             const gl::Rectangle extend4(-offsetLeft, -100, 100 + offsetLeft + offsetRight, 100);
489 
490             gl::ExtendRectangle(source, extend4, &result);
491             ASSERT_EQ(result.x0(), 0) << offsetLeft << " " << offsetRight;
492             ASSERT_EQ(result.y0(), -100) << offsetLeft << " " << offsetRight;
493             ASSERT_EQ(result.x1(), 100) << offsetLeft << " " << offsetRight;
494             ASSERT_EQ(result.y1(), 200) << offsetLeft << " " << offsetRight;
495         }
496     }
497     for (int offsetTop = 10; offsetTop >= 0; offsetTop -= 10)
498     {
499         for (int offsetBottom = 10; offsetBottom >= 0; offsetBottom -= 10)
500         {
501             const gl::Rectangle extend4(-50, -offsetTop, 50, 200 + offsetTop + offsetBottom);
502 
503             gl::ExtendRectangle(source, extend4, &result);
504             ASSERT_EQ(result.x0(), -50) << offsetTop << " " << offsetBottom;
505             ASSERT_EQ(result.y0(), 0) << offsetTop << " " << offsetBottom;
506             ASSERT_EQ(result.x1(), 100) << offsetTop << " " << offsetBottom;
507             ASSERT_EQ(result.y1(), 200) << offsetTop << " " << offsetBottom;
508         }
509     }
510     for (int offsetTop = 10; offsetTop >= 0; offsetTop -= 10)
511     {
512         for (int offsetBottom = 10; offsetBottom >= 0; offsetBottom -= 10)
513         {
514             const gl::Rectangle extend4(100, -offsetTop, 50, 200 + offsetTop + offsetBottom);
515 
516             gl::ExtendRectangle(source, extend4, &result);
517             ASSERT_EQ(result.x0(), 0) << offsetTop << " " << offsetBottom;
518             ASSERT_EQ(result.y0(), 0) << offsetTop << " " << offsetBottom;
519             ASSERT_EQ(result.x1(), 150) << offsetTop << " " << offsetBottom;
520             ASSERT_EQ(result.y1(), 200) << offsetTop << " " << offsetBottom;
521         }
522     }
523 
524     //    +------+           +------+
525     //    |S     |           |      |
526     //    |      |      -->  |      |
527     //    |      |           |      |
528     //    +------+           +------+
529     //  +------------+
530     //  |            |
531     //  +------------+
532     //
533     const gl::Rectangle extend5(-10, 201, 120, 100);
534 
535     gl::ExtendRectangle(source, extend5, &result);
536     ASSERT_EQ(result.x0(), 0);
537     ASSERT_EQ(result.y0(), 0);
538     ASSERT_EQ(result.x1(), 100);
539     ASSERT_EQ(result.y1(), 200);
540 
541     // Similar to extend5, but with the second rectangle on the top, left and right.
542     const gl::Rectangle extend6(-10, -101, 120, 100);
543 
544     gl::ExtendRectangle(source, extend6, &result);
545     ASSERT_EQ(result.x0(), 0);
546     ASSERT_EQ(result.y0(), 0);
547     ASSERT_EQ(result.x1(), 100);
548     ASSERT_EQ(result.y1(), 200);
549 
550     const gl::Rectangle extend7(-101, -10, 100, 220);
551 
552     gl::ExtendRectangle(source, extend7, &result);
553     ASSERT_EQ(result.x0(), 0);
554     ASSERT_EQ(result.y0(), 0);
555     ASSERT_EQ(result.x1(), 100);
556     ASSERT_EQ(result.y1(), 200);
557 
558     const gl::Rectangle extend8(101, -10, 100, 220);
559 
560     gl::ExtendRectangle(source, extend8, &result);
561     ASSERT_EQ(result.x0(), 0);
562     ASSERT_EQ(result.y0(), 0);
563     ASSERT_EQ(result.x1(), 100);
564     ASSERT_EQ(result.y1(), 200);
565 
566     //  +-------------+       +-------------+
567     //  |   +------+  |       |             |
568     //  |   |S     |  |       |             |
569     //  |   |      |  |  -->  |             |
570     //  |   |      |  |       |             |
571     //  |   +------+  |       |             |
572     //  +-------------+       +-------------+
573     //
574     const gl::Rectangle extend9(-100, -100, 300, 400);
575 
576     gl::ExtendRectangle(source, extend9, &result);
577     ASSERT_EQ(result.x0(), -100);
578     ASSERT_EQ(result.y0(), -100);
579     ASSERT_EQ(result.x1(), 200);
580     ASSERT_EQ(result.y1(), 300);
581 }
582 
583 }  // namespace angle
584