vk: Add four unit tests for our lock-free data-structures
[mesa.git] / src / mesa / drivers / dri / i965 / brw_meta_util.c
1 /*
2 * Copyright © 2014 Intel Corporation
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21 * IN THE SOFTWARE.
22 */
23
24 #include "brw_meta_util.h"
25 #include "main/fbobject.h"
26
27 /**
28 * Helper function for handling mirror image blits.
29 *
30 * If coord0 > coord1, swap them and invert the "mirror" boolean.
31 */
32 static inline void
33 fixup_mirroring(bool *mirror, float *coord0, float *coord1)
34 {
35 if (*coord0 > *coord1) {
36 *mirror = !*mirror;
37 float tmp = *coord0;
38 *coord0 = *coord1;
39 *coord1 = tmp;
40 }
41 }
42
43 /**
44 * Adjust {src,dst}_x{0,1} to account for clipping and scissoring of
45 * destination coordinates.
46 *
47 * Return true if there is still blitting to do, false if all pixels got
48 * rejected by the clip and/or scissor.
49 *
50 * For clarity, the nomenclature of this function assumes we are clipping and
51 * scissoring the X coordinate; the exact same logic applies for Y
52 * coordinates.
53 *
54 * Note: this function may also be used to account for clipping of source
55 * coordinates, by swapping the roles of src and dst.
56 */
57 static inline bool
58 clip_or_scissor(bool mirror,
59 GLfloat *src_x0, GLfloat *src_x1,
60 GLfloat *dst_x0, GLfloat *dst_x1,
61 GLfloat fb_xmin, GLfloat fb_xmax)
62 {
63 float scale = (float) (*src_x1 - *src_x0) / (*dst_x1 - *dst_x0);
64 /* If we are going to scissor everything away, stop. */
65 if (!(fb_xmin < fb_xmax &&
66 *dst_x0 < fb_xmax &&
67 fb_xmin < *dst_x1 &&
68 *dst_x0 < *dst_x1)) {
69 return false;
70 }
71
72 /* Clip the destination rectangle, and keep track of how many pixels we
73 * clipped off of the left and right sides of it.
74 */
75 int pixels_clipped_left = 0;
76 int pixels_clipped_right = 0;
77 if (*dst_x0 < fb_xmin) {
78 pixels_clipped_left = fb_xmin - *dst_x0;
79 *dst_x0 = fb_xmin;
80 }
81 if (fb_xmax < *dst_x1) {
82 pixels_clipped_right = *dst_x1 - fb_xmax;
83 *dst_x1 = fb_xmax;
84 }
85
86 /* If we are mirrored, then before applying pixels_clipped_{left,right} to
87 * the source coordinates, we need to flip them to account for the
88 * mirroring.
89 */
90 if (mirror) {
91 int tmp = pixels_clipped_left;
92 pixels_clipped_left = pixels_clipped_right;
93 pixels_clipped_right = tmp;
94 }
95
96 /* Adjust the source rectangle to remove the pixels corresponding to those
97 * that were clipped/scissored out of the destination rectangle.
98 */
99 *src_x0 += pixels_clipped_left * scale;
100 *src_x1 -= pixels_clipped_right * scale;
101
102 return true;
103 }
104
105 bool
106 brw_meta_mirror_clip_and_scissor(const struct gl_context *ctx,
107 const struct gl_framebuffer *read_fb,
108 const struct gl_framebuffer *draw_fb,
109 GLfloat *srcX0, GLfloat *srcY0,
110 GLfloat *srcX1, GLfloat *srcY1,
111 GLfloat *dstX0, GLfloat *dstY0,
112 GLfloat *dstX1, GLfloat *dstY1,
113 bool *mirror_x, bool *mirror_y)
114 {
115 *mirror_x = false;
116 *mirror_y = false;
117
118 /* Detect if the blit needs to be mirrored */
119 fixup_mirroring(mirror_x, srcX0, srcX1);
120 fixup_mirroring(mirror_x, dstX0, dstX1);
121 fixup_mirroring(mirror_y, srcY0, srcY1);
122 fixup_mirroring(mirror_y, dstY0, dstY1);
123
124 /* If the destination rectangle needs to be clipped or scissored, do so. */
125 if (!(clip_or_scissor(*mirror_x, srcX0, srcX1, dstX0, dstX1,
126 draw_fb->_Xmin, draw_fb->_Xmax) &&
127 clip_or_scissor(*mirror_y, srcY0, srcY1, dstY0, dstY1,
128 draw_fb->_Ymin, draw_fb->_Ymax))) {
129 /* Everything got clipped/scissored away, so the blit was successful. */
130 return true;
131 }
132
133 /* If the source rectangle needs to be clipped or scissored, do so. */
134 if (!(clip_or_scissor(*mirror_x, dstX0, dstX1, srcX0, srcX1,
135 0, read_fb->Width) &&
136 clip_or_scissor(*mirror_y, dstY0, dstY1, srcY0, srcY1,
137 0, read_fb->Height))) {
138 /* Everything got clipped/scissored away, so the blit was successful. */
139 return true;
140 }
141
142 /* Account for the fact that in the system framebuffer, the origin is at
143 * the lower left.
144 */
145 if (_mesa_is_winsys_fbo(read_fb)) {
146 GLint tmp = read_fb->Height - *srcY0;
147 *srcY0 = read_fb->Height - *srcY1;
148 *srcY1 = tmp;
149 *mirror_y = !*mirror_y;
150 }
151 if (_mesa_is_winsys_fbo(draw_fb)) {
152 GLint tmp = draw_fb->Height - *dstY0;
153 *dstY0 = draw_fb->Height - *dstY1;
154 *dstY1 = tmp;
155 *mirror_y = !*mirror_y;
156 }
157
158 return false;
159 }