Merge git://proxy01.pd.intel.com:9419/git/mesa/mesa into crestline
[mesa.git] / src / mesa / drivers / dri / i965 / intel_regions.c
1 /**************************************************************************
2 *
3 * Copyright 2006 Tungsten Graphics, Inc., Cedar Park, Texas.
4 * All Rights Reserved.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sub license, and/or sell copies of the Software, and to
11 * permit persons to whom the Software is furnished to do so, subject to
12 * the following conditions:
13 *
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial portions
16 * of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21 * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
22 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 *
26 **************************************************************************/
27
28 /* Provide additional functionality on top of bufmgr buffers:
29 * - 2d semantics and blit operations
30 * - refcounting of buffers for multiple images in a buffer.
31 * - refcounting of buffer mappings.
32 * - some logic for moving the buffers to the best memory pools for
33 * given operations.
34 *
35 * Most of this is to make it easier to implement the fixed-layout
36 * mipmap tree required by intel hardware in the face of GL's
37 * programming interface where each image can be specifed in random
38 * order and it isn't clear what layout the tree should have until the
39 * last moment.
40 */
41
42 #include "intel_context.h"
43 #include "intel_regions.h"
44 #include "intel_blit.h"
45 #include "bufmgr.h"
46 #include "imports.h"
47
48 /* XXX: Thread safety?
49 */
50 GLubyte *intel_region_map(struct intel_context *intel, struct intel_region *region)
51 {
52 DBG("%s\n", __FUNCTION__);
53 if (!region->map_refcount++) {
54 region->map = bmMapBuffer(intel, region->buffer, 0);
55 if (!region->map)
56 region->map_refcount--;
57 }
58
59 return region->map;
60 }
61
62 void intel_region_unmap(struct intel_context *intel,
63 struct intel_region *region)
64 {
65 DBG("%s\n", __FUNCTION__);
66 if (!--region->map_refcount) {
67 bmUnmapBufferAUB(intel, region->buffer, 0, 0);
68 region->map = NULL;
69 }
70 }
71
72 struct intel_region *intel_region_alloc( struct intel_context *intel,
73 GLuint cpp,
74 GLuint pitch,
75 GLuint height )
76 {
77 struct intel_region *region = calloc(sizeof(*region), 1);
78
79 DBG("%s %dx%dx%d == 0x%x bytes\n", __FUNCTION__,
80 cpp, pitch, height, cpp*pitch*height);
81
82 region->cpp = cpp;
83 region->pitch = pitch;
84 region->height = height; /* needed? */
85 region->refcount = 1;
86
87 bmGenBuffers(intel, "tex", 1, &region->buffer, 6);
88 bmBufferData(intel, region->buffer, pitch * cpp * height, NULL, 0);
89
90 return region;
91 }
92
93 void intel_region_reference( struct intel_region **dst,
94 struct intel_region *src)
95 {
96 src->refcount++;
97 assert(*dst == NULL);
98 *dst = src;
99 }
100
101 void intel_region_release( struct intel_context *intel,
102 struct intel_region **region )
103 {
104 if (!*region)
105 return;
106
107 DBG("%s %d\n", __FUNCTION__, (*region)->refcount-1);
108
109 if (--(*region)->refcount == 0) {
110 assert((*region)->map_refcount == 0);
111 bmDeleteBuffers(intel, 1, &(*region)->buffer);
112 free(*region);
113 }
114 *region = NULL;
115 }
116
117
118 struct intel_region *intel_region_create_static( struct intel_context *intel,
119 GLuint mem_type,
120 GLuint offset,
121 void *virtual,
122 GLuint cpp,
123 GLuint pitch,
124 GLuint height,
125 GLuint size,
126 GLboolean tiled )
127 {
128 struct intel_region *region = calloc(sizeof(*region), 1);
129 GLint pool;
130
131 DBG("%s\n", __FUNCTION__);
132
133 region->cpp = cpp;
134 region->pitch = pitch;
135 region->height = height; /* needed? */
136 region->refcount = 1;
137 region->tiled = tiled;
138
139 /* Recipe for creating a static buffer - create a static pool with
140 * the right offset and size, generate a buffer and use a special
141 * call to bind it to all of the memory in that pool.
142 */
143 pool = bmInitPool(intel, offset, virtual, size,
144 (BM_MEM_AGP |
145 BM_NO_UPLOAD |
146 BM_NO_EVICT |
147 BM_NO_MOVE));
148 if (pool < 0) {
149 _mesa_printf("bmInitPool failed for static region\n");
150 exit(1);
151 }
152
153 region->buffer = bmGenBufferStatic(intel, pool);
154
155 return region;
156 }
157
158
159
160
161 void _mesa_copy_rect( GLubyte *dst,
162 GLuint cpp,
163 GLuint dst_pitch,
164 GLuint dst_x,
165 GLuint dst_y,
166 GLuint width,
167 GLuint height,
168 const GLubyte *src,
169 GLuint src_pitch,
170 GLuint src_x,
171 GLuint src_y )
172 {
173 GLuint i;
174
175 dst_pitch *= cpp;
176 src_pitch *= cpp;
177 dst += dst_x * cpp;
178 src += src_x * cpp;
179 dst += dst_y * dst_pitch;
180 src += src_y * dst_pitch;
181 width *= cpp;
182
183 if (width == dst_pitch &&
184 width == src_pitch)
185 do_memcpy(dst, src, height * width);
186 else {
187 for (i = 0; i < height; i++) {
188 do_memcpy(dst, src, width);
189 dst += dst_pitch;
190 src += src_pitch;
191 }
192 }
193 }
194
195
196 /* Upload data to a rectangular sub-region. Lots of choices how to do this:
197 *
198 * - memcpy by span to current destination
199 * - upload data as new buffer and blit
200 *
201 * Currently always memcpy.
202 */
203 GLboolean intel_region_data(struct intel_context *intel,
204 struct intel_region *dst,
205 GLuint dst_offset,
206 GLuint dstx, GLuint dsty,
207 const void *src, GLuint src_pitch,
208 GLuint srcx, GLuint srcy,
209 GLuint width, GLuint height)
210 {
211 DBG("%s\n", __FUNCTION__);
212
213 if (width == dst->pitch &&
214 width == src_pitch &&
215 dst_offset == 0 &&
216 height == dst->height &&
217 srcx == 0 &&
218 srcy == 0)
219 {
220 return (bmBufferDataAUB(intel,
221 dst->buffer,
222 dst->cpp * width * dst->height,
223 src, 0, 0, 0) == 0);
224 }
225 else {
226 GLubyte *map = intel_region_map(intel, dst);
227
228 if (map) {
229 assert (dst_offset + dstx + width +
230 (dsty + height - 1) * dst->pitch * dst->cpp <=
231 dst->pitch * dst->cpp * dst->height);
232
233 _mesa_copy_rect(map + dst_offset,
234 dst->cpp,
235 dst->pitch,
236 dstx, dsty,
237 width, height,
238 src,
239 src_pitch,
240 srcx, srcy);
241
242 intel_region_unmap(intel, dst);
243 return GL_TRUE;
244 }
245 else
246 return GL_FALSE;
247 }
248 }
249
250 /* Copy rectangular sub-regions. Need better logic about when to
251 * push buffers into AGP - will currently do so whenever possible.
252 */
253 void intel_region_copy( struct intel_context *intel,
254 struct intel_region *dst,
255 GLuint dst_offset,
256 GLuint dstx, GLuint dsty,
257 struct intel_region *src,
258 GLuint src_offset,
259 GLuint srcx, GLuint srcy,
260 GLuint width, GLuint height )
261 {
262 DBG("%s\n", __FUNCTION__);
263
264 assert(src->cpp == dst->cpp);
265
266 intelEmitCopyBlit(intel,
267 dst->cpp,
268 src->pitch, src->buffer, src_offset, src->tiled,
269 dst->pitch, dst->buffer, dst_offset, dst->tiled,
270 srcx, srcy,
271 dstx, dsty,
272 width, height,
273 GL_COPY );
274 }
275
276 /* Fill a rectangular sub-region. Need better logic about when to
277 * push buffers into AGP - will currently do so whenever possible.
278 */
279 void intel_region_fill( struct intel_context *intel,
280 struct intel_region *dst,
281 GLuint dst_offset,
282 GLuint dstx, GLuint dsty,
283 GLuint width, GLuint height,
284 GLuint color )
285 {
286 DBG("%s\n", __FUNCTION__);
287
288 intelEmitFillBlit(intel,
289 dst->cpp,
290 dst->pitch, dst->buffer, dst_offset, dst->tiled,
291 dstx, dsty,
292 width, height,
293 color );
294 }
295