Merge branch 'master' of git+ssh://joukj@git.freedesktop.org/git/mesa/mesa
[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 #define FILE_DEBUG_FLAG DEBUG_REGION
49
50 /* XXX: Thread safety?
51 */
52 GLubyte *intel_region_map(struct intel_context *intel, struct intel_region *region)
53 {
54 DBG("%s\n", __FUNCTION__);
55 if (!region->map_refcount++) {
56 region->map = bmMapBuffer(intel, region->buffer, 0);
57 if (!region->map)
58 region->map_refcount--;
59 }
60
61 return region->map;
62 }
63
64 void intel_region_unmap(struct intel_context *intel,
65 struct intel_region *region)
66 {
67 DBG("%s\n", __FUNCTION__);
68 if (!--region->map_refcount) {
69 bmUnmapBuffer(intel, region->buffer);
70 region->map = NULL;
71 }
72 }
73
74 struct intel_region *intel_region_alloc( struct intel_context *intel,
75 GLuint cpp,
76 GLuint pitch,
77 GLuint height )
78 {
79 struct intel_region *region = calloc(sizeof(*region), 1);
80
81 DBG("%s %dx%dx%d == 0x%x bytes\n", __FUNCTION__,
82 cpp, pitch, height, cpp*pitch*height);
83
84 region->cpp = cpp;
85 region->pitch = pitch;
86 region->height = height; /* needed? */
87 region->refcount = 1;
88
89 bmGenBuffers(intel, "tex", 1, &region->buffer, 6);
90 bmBufferData(intel, region->buffer, pitch * cpp * height, NULL, 0);
91
92 return region;
93 }
94
95 void intel_region_reference( struct intel_region **dst,
96 struct intel_region *src)
97 {
98 src->refcount++;
99 assert(*dst == NULL);
100 *dst = src;
101 }
102
103 void intel_region_release( struct intel_context *intel,
104 struct intel_region **region )
105 {
106 if (!*region)
107 return;
108
109 DBG("%s %d\n", __FUNCTION__, (*region)->refcount-1);
110
111 if (--(*region)->refcount == 0) {
112 assert((*region)->map_refcount == 0);
113 bmDeleteBuffers(intel, 1, &(*region)->buffer);
114 free(*region);
115 }
116 *region = NULL;
117 }
118
119
120 struct intel_region *intel_region_create_static( struct intel_context *intel,
121 GLuint mem_type,
122 GLuint offset,
123 void *virtual,
124 GLuint cpp,
125 GLuint pitch,
126 GLuint height,
127 GLuint size,
128 GLboolean tiled )
129 {
130 struct intel_region *region = calloc(sizeof(*region), 1);
131 GLint pool;
132
133 DBG("%s\n", __FUNCTION__);
134
135 region->cpp = cpp;
136 region->pitch = pitch;
137 region->height = height; /* needed? */
138 region->refcount = 1;
139 region->tiled = tiled;
140
141 /* Recipe for creating a static buffer - create a static pool with
142 * the right offset and size, generate a buffer and use a special
143 * call to bind it to all of the memory in that pool.
144 */
145 pool = bmInitPool(intel, offset, virtual, size,
146 (BM_MEM_AGP |
147 BM_NO_UPLOAD |
148 BM_NO_EVICT |
149 BM_NO_MOVE));
150 if (pool < 0) {
151 _mesa_printf("bmInitPool failed for static region\n");
152 exit(1);
153 }
154
155 region->buffer = bmGenBufferStatic(intel, pool);
156
157 return region;
158 }
159
160
161
162
163 void _mesa_copy_rect( GLubyte *dst,
164 GLuint cpp,
165 GLuint dst_pitch,
166 GLuint dst_x,
167 GLuint dst_y,
168 GLuint width,
169 GLuint height,
170 const GLubyte *src,
171 GLuint src_pitch,
172 GLuint src_x,
173 GLuint src_y )
174 {
175 GLuint i;
176
177 dst_pitch *= cpp;
178 src_pitch *= cpp;
179 dst += dst_x * cpp;
180 src += src_x * cpp;
181 dst += dst_y * dst_pitch;
182 src += src_y * dst_pitch;
183 width *= cpp;
184
185 if (width == dst_pitch &&
186 width == src_pitch)
187 do_memcpy(dst, src, height * width);
188 else {
189 for (i = 0; i < height; i++) {
190 do_memcpy(dst, src, width);
191 dst += dst_pitch;
192 src += src_pitch;
193 }
194 }
195 }
196
197
198 /* Upload data to a rectangular sub-region. Lots of choices how to do this:
199 *
200 * - memcpy by span to current destination
201 * - upload data as new buffer and blit
202 *
203 * Currently always memcpy.
204 */
205 GLboolean intel_region_data(struct intel_context *intel,
206 struct intel_region *dst,
207 GLuint dst_offset,
208 GLuint dstx, GLuint dsty,
209 const void *src, GLuint src_pitch,
210 GLuint srcx, GLuint srcy,
211 GLuint width, GLuint height)
212 {
213 DBG("%s\n", __FUNCTION__);
214
215 if (width == dst->pitch &&
216 width == src_pitch &&
217 dst_offset == 0 &&
218 height == dst->height &&
219 srcx == 0 &&
220 srcy == 0)
221 {
222 return (bmBufferData(intel,
223 dst->buffer,
224 dst->cpp * width * dst->height,
225 src, 0) == 0);
226 }
227 else {
228 GLubyte *map = intel_region_map(intel, dst);
229
230 if (map) {
231 assert (dst_offset + dstx + width +
232 (dsty + height - 1) * dst->pitch * dst->cpp <=
233 dst->pitch * dst->cpp * dst->height);
234
235 _mesa_copy_rect(map + dst_offset,
236 dst->cpp,
237 dst->pitch,
238 dstx, dsty,
239 width, height,
240 src,
241 src_pitch,
242 srcx, srcy);
243
244 intel_region_unmap(intel, dst);
245 return GL_TRUE;
246 }
247 else
248 return GL_FALSE;
249 }
250 }
251
252 /* Copy rectangular sub-regions. Need better logic about when to
253 * push buffers into AGP - will currently do so whenever possible.
254 */
255 void intel_region_copy( struct intel_context *intel,
256 struct intel_region *dst,
257 GLuint dst_offset,
258 GLuint dstx, GLuint dsty,
259 struct intel_region *src,
260 GLuint src_offset,
261 GLuint srcx, GLuint srcy,
262 GLuint width, GLuint height )
263 {
264 DBG("%s\n", __FUNCTION__);
265
266 assert(src->cpp == dst->cpp);
267
268 intelEmitCopyBlit(intel,
269 dst->cpp,
270 src->pitch, src->buffer, src_offset, src->tiled,
271 dst->pitch, dst->buffer, dst_offset, dst->tiled,
272 srcx, srcy,
273 dstx, dsty,
274 width, height,
275 GL_COPY );
276 }
277
278 /* Fill a rectangular sub-region. Need better logic about when to
279 * push buffers into AGP - will currently do so whenever possible.
280 */
281 void intel_region_fill( struct intel_context *intel,
282 struct intel_region *dst,
283 GLuint dst_offset,
284 GLuint dstx, GLuint dsty,
285 GLuint width, GLuint height,
286 GLuint color )
287 {
288 DBG("%s\n", __FUNCTION__);
289
290 intelEmitFillBlit(intel,
291 dst->cpp,
292 dst->pitch, dst->buffer, dst_offset, dst->tiled,
293 dstx, dsty,
294 width, height,
295 color );
296 }
297