Use write posting in the kickoff function too.
[mesa.git] / src / mesa / pipe / i915simple / i915_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 (XXX: remove/simplify blits??)
30 * - refcounting of buffers for multiple images in a buffer.
31 * - refcounting of buffer mappings.
32 */
33
34 #include "pipe/p_defines.h"
35 #include "pipe/p_winsys.h"
36 #include "i915_context.h"
37 #include "i915_blit.h"
38
39
40
41
42 static ubyte *
43 i915_region_map(struct pipe_context *pipe, struct pipe_region *region)
44 {
45 struct i915_context *i915 = i915_context( pipe );
46
47 if (!region->map_refcount++) {
48 region->map = i915->pipe.winsys->buffer_map( i915->pipe.winsys,
49 region->buffer,
50 PIPE_BUFFER_FLAG_WRITE |
51 PIPE_BUFFER_FLAG_READ);
52 }
53
54 return region->map;
55 }
56
57 static void
58 i915_region_unmap(struct pipe_context *pipe, struct pipe_region *region)
59 {
60 struct i915_context *i915 = i915_context( pipe );
61
62 if (region->map_refcount > 0) {
63 assert(region->map);
64 if (!--region->map_refcount) {
65 i915->pipe.winsys->buffer_unmap( i915->pipe.winsys,
66 region->buffer );
67 region->map = NULL;
68 }
69 }
70 }
71
72
73 /*
74 * XXX Move this into core Mesa?
75 */
76 static void
77 _mesa_copy_rect(ubyte * dst,
78 unsigned cpp,
79 unsigned dst_pitch,
80 unsigned dst_x,
81 unsigned dst_y,
82 unsigned width,
83 unsigned height,
84 const ubyte * src,
85 unsigned src_pitch,
86 unsigned src_x,
87 unsigned src_y)
88 {
89 unsigned i;
90
91 dst_pitch *= cpp;
92 src_pitch *= cpp;
93 dst += dst_x * cpp;
94 src += src_x * cpp;
95 dst += dst_y * dst_pitch;
96 src += src_y * dst_pitch;
97 width *= cpp;
98
99 if (width == dst_pitch && width == src_pitch)
100 memcpy(dst, src, height * width);
101 else {
102 for (i = 0; i < height; i++) {
103 memcpy(dst, src, width);
104 dst += dst_pitch;
105 src += src_pitch;
106 }
107 }
108 }
109
110
111 /* Upload data to a rectangular sub-region. Lots of choices how to do this:
112 *
113 * - memcpy by span to current destination
114 * - upload data as new buffer and blit
115 *
116 * Currently always memcpy.
117 */
118 static void
119 i915_region_data(struct pipe_context *pipe,
120 struct pipe_region *dst,
121 unsigned dst_offset,
122 unsigned dstx, unsigned dsty,
123 const void *src, unsigned src_pitch,
124 unsigned srcx, unsigned srcy, unsigned width, unsigned height)
125 {
126 _mesa_copy_rect(pipe->region_map(pipe, dst) + dst_offset,
127 dst->cpp,
128 dst->pitch,
129 dstx, dsty, width, height, src, src_pitch, srcx, srcy);
130
131 pipe->region_unmap(pipe, dst);
132 }
133
134
135 /* Assumes all values are within bounds -- no checking at this level -
136 * do it higher up if required.
137 */
138 static void
139 i915_region_copy(struct pipe_context *pipe,
140 struct pipe_region *dst,
141 unsigned dst_offset,
142 unsigned dstx, unsigned dsty,
143 struct pipe_region *src,
144 unsigned src_offset,
145 unsigned srcx, unsigned srcy, unsigned width, unsigned height)
146 {
147 assert( dst != src );
148 assert( dst->cpp == src->cpp );
149
150 if (0) {
151 _mesa_copy_rect(pipe->region_map(pipe, dst) + dst_offset,
152 dst->cpp,
153 dst->pitch,
154 dstx, dsty,
155 width, height,
156 pipe->region_map(pipe, src) + src_offset,
157 src->pitch,
158 srcx, srcy);
159
160 pipe->region_unmap(pipe, src);
161 pipe->region_unmap(pipe, dst);
162 }
163 else {
164 i915_copy_blit( i915_context(pipe),
165 dst->cpp,
166 src->pitch, src->buffer, src_offset,
167 dst->pitch, dst->buffer, dst_offset,
168 srcx, srcy, dstx, dsty, width, height );
169 }
170 }
171
172 /* Fill a rectangular sub-region. Need better logic about when to
173 * push buffers into AGP - will currently do so whenever possible.
174 */
175 static ubyte *
176 get_pointer(struct pipe_region *dst, unsigned x, unsigned y)
177 {
178 return dst->map + (y * dst->pitch + x) * dst->cpp;
179 }
180
181
182 static void
183 i915_region_fill(struct pipe_context *pipe,
184 struct pipe_region *dst,
185 unsigned dst_offset,
186 unsigned dstx, unsigned dsty,
187 unsigned width, unsigned height, unsigned value)
188 {
189 if (0) {
190 unsigned i, j;
191
192 (void)pipe->region_map(pipe, dst);
193
194 switch (dst->cpp) {
195 case 1: {
196 ubyte *row = get_pointer(dst, dstx, dsty);
197 for (i = 0; i < height; i++) {
198 memset(row, value, width);
199 row += dst->pitch;
200 }
201 }
202 break;
203 case 2: {
204 ushort *row = (ushort *) get_pointer(dst, dstx, dsty);
205 for (i = 0; i < height; i++) {
206 for (j = 0; j < width; j++)
207 row[j] = value;
208 row += dst->pitch;
209 }
210 }
211 break;
212 case 4: {
213 unsigned *row = (unsigned *) get_pointer(dst, dstx, dsty);
214 for (i = 0; i < height; i++) {
215 for (j = 0; j < width; j++)
216 row[j] = value;
217 row += dst->pitch;
218 }
219 }
220 break;
221 default:
222 assert(0);
223 break;
224 }
225 }
226 else {
227 i915_fill_blit( i915_context(pipe),
228 dst->cpp,
229 dst->pitch,
230 dst->buffer, dst_offset,
231 dstx, dsty,
232 width, height,
233 value );
234 }
235 }
236
237
238
239
240
241 void
242 i915_init_region_functions(struct i915_context *i915)
243 {
244 i915->pipe.region_map = i915_region_map;
245 i915->pipe.region_unmap = i915_region_unmap;
246 i915->pipe.region_data = i915_region_data;
247 i915->pipe.region_copy = i915_region_copy;
248 i915->pipe.region_fill = i915_region_fill;
249 }
250