1 /**************************************************************************
3 * Copyright 2006 Tungsten Graphics, Inc., Cedar Park, Texas.
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:
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial portions
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.
26 **************************************************************************/
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.
34 #include "sp_context.h"
35 #include "sp_winsys.h"
36 #include "sp_region.h"
40 sp_region_idle(struct pipe_context
*pipe
, struct pipe_region
*region
)
47 sp_region_map(struct pipe_context
*pipe
, struct pipe_region
*region
)
49 struct softpipe_context
*sp
= softpipe_context( pipe
);
51 if (!region
->map_refcount
++) {
52 region
->map
= sp
->winsys
->buffer_map( sp
->winsys
,
60 sp_region_unmap(struct pipe_context
*pipe
, struct pipe_region
*region
)
62 struct softpipe_context
*sp
= softpipe_context( pipe
);
64 if (!--region
->map_refcount
) {
65 sp
->winsys
->buffer_unmap( sp
->winsys
,
71 static struct pipe_region
*
72 sp_region_alloc(struct pipe_context
*pipe
,
73 GLuint cpp
, GLuint pitch
, GLuint height
)
75 struct softpipe_context
*sp
= softpipe_context( pipe
);
76 struct pipe_region
*region
= calloc(sizeof(*region
), 1);
79 region
->pitch
= pitch
;
80 region
->height
= height
; /* needed? */
83 region
->buffer
= sp
->winsys
->create_buffer( sp
->winsys
, 64 );
85 sp
->winsys
->buffer_data( sp
->winsys
,
94 sp_region_release(struct pipe_context
*pipe
, struct pipe_region
**region
)
96 struct softpipe_context
*sp
= softpipe_context( pipe
);
101 ASSERT((*region
)->refcount
> 0);
102 (*region
)->refcount
--;
104 if ((*region
)->refcount
== 0) {
105 assert((*region
)->map_refcount
== 0);
107 sp
->winsys
->buffer_unreference( sp
->winsys
,
116 * XXX Move this into core Mesa?
119 _mesa_copy_rect(GLubyte
* dst
,
137 dst
+= dst_y
* dst_pitch
;
138 src
+= src_y
* dst_pitch
;
141 if (width
== dst_pitch
&& width
== src_pitch
)
142 memcpy(dst
, src
, height
* width
);
144 for (i
= 0; i
< height
; i
++) {
145 memcpy(dst
, src
, width
);
153 /* Upload data to a rectangular sub-region. Lots of choices how to do this:
155 * - memcpy by span to current destination
156 * - upload data as new buffer and blit
158 * Currently always memcpy.
161 sp_region_data(struct pipe_context
*pipe
,
162 struct pipe_region
*dst
,
164 GLuint dstx
, GLuint dsty
,
165 const void *src
, GLuint src_pitch
,
166 GLuint srcx
, GLuint srcy
, GLuint width
, GLuint height
)
168 _mesa_copy_rect(pipe
->region_map(pipe
, dst
) + dst_offset
,
171 dstx
, dsty
, width
, height
, src
, src_pitch
, srcx
, srcy
);
173 pipe
->region_unmap(pipe
, dst
);
176 /* Assumes all values are within bounds -- no checking at this level -
177 * do it higher up if required.
180 sp_region_copy(struct pipe_context
*pipe
,
181 struct pipe_region
*dst
,
183 GLuint dstx
, GLuint dsty
,
184 struct pipe_region
*src
,
186 GLuint srcx
, GLuint srcy
, GLuint width
, GLuint height
)
188 assert( dst
->cpp
== src
->cpp
);
190 _mesa_copy_rect(pipe
->region_map(pipe
, dst
) + dst_offset
,
195 pipe
->region_map(pipe
, src
) + src_offset
,
199 pipe
->region_unmap(pipe
, src
);
200 pipe
->region_unmap(pipe
, dst
);
203 /* Fill a rectangular sub-region. Need better logic about when to
204 * push buffers into AGP - will currently do so whenever possible.
207 get_pointer(struct pipe_region
*dst
, GLuint x
, GLuint y
)
209 return dst
->map
+ (y
* dst
->pitch
+ x
) * dst
->cpp
;
214 sp_region_fill(struct pipe_context
*pipe
,
215 struct pipe_region
*dst
,
217 GLuint dstx
, GLuint dsty
,
218 GLuint width
, GLuint height
, GLuint value
)
222 (void)pipe
->region_map(pipe
, dst
);
226 GLubyte
*row
= get_pointer(dst
, dstx
, dsty
);
227 for (i
= 0; i
< height
; i
++) {
228 memset(row
, value
, width
);
234 GLushort
*row
= (GLushort
*) get_pointer(dst
, dstx
, dsty
);
235 for (i
= 0; i
< height
; i
++) {
236 for (j
= 0; j
< width
; j
++)
243 GLuint
*row
= (GLuint
*) get_pointer(dst
, dstx
, dsty
);
244 for (i
= 0; i
< height
; i
++) {
245 for (j
= 0; j
< width
; j
++)
256 pipe
->region_unmap( pipe
, dst
);
264 sp_init_region_functions(struct softpipe_context
*sp
)
266 sp
->pipe
.region_idle
= sp_region_idle
;
267 sp
->pipe
.region_map
= sp_region_map
;
268 sp
->pipe
.region_unmap
= sp_region_unmap
;
269 sp
->pipe
.region_alloc
= sp_region_alloc
;
270 sp
->pipe
.region_release
= sp_region_release
;
271 sp
->pipe
.region_data
= sp_region_data
;
272 sp
->pipe
.region_copy
= sp_region_copy
;
273 sp
->pipe
.region_fill
= sp_region_fill
;