1 /**************************************************************************
3 * Copyright 2006 Tungsten Graphics, Inc., Bismarck, ND., USA
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 SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
17 * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
18 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
19 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
20 * USE OR OTHER DEALINGS IN THE SOFTWARE.
22 * The above copyright notice and this permission notice (including the
23 * next paragraph) shall be included in all copies or substantial portions
27 **************************************************************************/
29 * Authors: Keith Whitwell <keithw-at-tungstengraphics-dot-com>
34 #include "dri_bufpool.h"
35 #include "dri_bufmgr.h"
37 #include "intel_context.h"
38 #include "intel_winsys.h"
39 #include "intel_swapbuffers.h"
40 #include "intel_batchbuffer.h"
42 #include "pipe/p_winsys.h"
43 #include "pipe/p_defines.h"
44 #include "pipe/p_state.h"
45 #include "pipe/p_util.h"
49 struct intel_pipe_winsys
{
50 struct pipe_winsys winsys
;
51 struct _DriBufferPool
*regionPool
;
56 /* Turn a pipe winsys into an intel/pipe winsys:
58 static inline struct intel_pipe_winsys
*
59 intel_pipe_winsys( struct pipe_winsys
*winsys
)
61 return (struct intel_pipe_winsys
*)winsys
;
65 /* Most callbacks map direcly onto dri_bufmgr operations:
67 static void *intel_buffer_map(struct pipe_winsys
*winsys
,
68 struct pipe_buffer_handle
*buf
,
71 unsigned drm_flags
= 0;
73 if (flags
& PIPE_BUFFER_FLAG_WRITE
)
74 drm_flags
|= DRM_BO_FLAG_WRITE
;
76 if (flags
& PIPE_BUFFER_FLAG_READ
)
77 drm_flags
|= DRM_BO_FLAG_READ
;
79 return driBOMap( dri_bo(buf
), drm_flags
, 0 );
82 static void intel_buffer_unmap(struct pipe_winsys
*winsys
,
83 struct pipe_buffer_handle
*buf
)
85 driBOUnmap( dri_bo(buf
) );
90 intel_buffer_reference(struct pipe_winsys
*winsys
,
91 struct pipe_buffer_handle
**ptr
,
92 struct pipe_buffer_handle
*buf
)
95 driBOUnReference( dri_bo(*ptr
) );
100 driBOReference( dri_bo(buf
) );
106 /* Grabs the hardware lock!
108 static void intel_buffer_data(struct pipe_winsys
*winsys
,
109 struct pipe_buffer_handle
*buf
,
110 unsigned size
, const void *data
,
113 driBOData( dri_bo(buf
), size
, data
, 0 );
116 static void intel_buffer_subdata(struct pipe_winsys
*winsys
,
117 struct pipe_buffer_handle
*buf
,
118 unsigned long offset
,
122 driBOSubData( dri_bo(buf
), offset
, size
, data
);
125 static void intel_buffer_get_subdata(struct pipe_winsys
*winsys
,
126 struct pipe_buffer_handle
*buf
,
127 unsigned long offset
,
131 driBOGetSubData( dri_bo(buf
), offset
, size
, data
);
134 /* Pipe has no concept of pools. We choose the tex/region pool
137 static struct pipe_buffer_handle
*
138 intel_buffer_create(struct pipe_winsys
*winsys
,
141 struct _DriBufferObject
*buffer
;
142 struct intel_pipe_winsys
*iws
= intel_pipe_winsys(winsys
);
143 driGenBuffers( iws
->regionPool
,
144 "pipe buffer", 1, &buffer
, alignment
, 0, 0 );
145 return pipe_bo(buffer
);
149 static struct pipe_buffer_handle
*
150 intel_user_buffer_create(struct pipe_winsys
*winsys
, void *ptr
, unsigned bytes
)
152 struct _DriBufferObject
*buffer
;
153 struct intel_pipe_winsys
*iws
= intel_pipe_winsys(winsys
);
154 driGenUserBuffer( iws
->regionPool
,
155 "pipe user buffer", &buffer
, ptr
, bytes
);
156 return pipe_bo(buffer
);
160 /* The state tracker (should!) keep track of whether the fake
161 * frontbuffer has been touched by any rendering since the last time
162 * we copied its contents to the real frontbuffer. Our task is easy:
165 intel_flush_frontbuffer( struct pipe_winsys
*winsys
,
166 struct pipe_surface
*surf
,
167 void *context_private
)
169 struct intel_context
*intel
= (struct intel_context
*) context_private
;
170 __DRIdrawablePrivate
*dPriv
= intel
->driDrawable
;
172 intelDisplaySurface(dPriv
, surf
, NULL
);
177 intel_i915_surface_pitch(struct pipe_winsys
*winsys
,
178 unsigned cpp
, unsigned width
, unsigned flags
)
180 /* Choose a pitch to match hardware requirements - requires 64 byte
181 * alignment of render targets.
183 * XXX: is this ok for textures??
184 * clearly want to be able to render to textures under some
185 * circumstances, but maybe not always a requirement.
188 /* XXX is the pitch different for textures vs. drawables? */
189 if (flags
& PIPE_SURFACE_FLAG_TEXTURE
) /* or PIPE_SURFACE_FLAG_RENDER? */
190 return ((cpp
* width
+ 63) & ~63) / cpp
;
192 return ((cpp
* width
+ 63) & ~63) / cpp
;
196 static struct pipe_region
*
197 intel_i915_region_alloc(struct pipe_winsys
*winsys
,
198 unsigned size
, unsigned flags
)
200 struct pipe_region
*region
= calloc(sizeof(*region
), 1);
201 const unsigned alignment
= 64;
203 region
->refcount
= 1;
205 region
->buffer
= winsys
->buffer_create( winsys
, alignment
);
207 winsys
->buffer_data( winsys
,
211 PIPE_BUFFER_USAGE_PIXEL
);
217 intel_i915_region_release(struct pipe_winsys
*winsys
,
218 struct pipe_region
**region
)
223 assert((*region
)->refcount
> 0);
224 (*region
)->refcount
--;
226 if ((*region
)->refcount
== 0) {
227 assert((*region
)->map_refcount
== 0);
229 winsys
->buffer_reference( winsys
, &((*region
)->buffer
), NULL
);
236 static struct pipe_surface
*
237 intel_i915_surface_alloc(struct pipe_winsys
*winsys
, unsigned format
)
239 struct pipe_surface
*surf
= CALLOC_STRUCT(pipe_surface
);
241 surf
->format
= format
;
243 surf
->winsys
= winsys
;
250 intel_i915_surface_release(struct pipe_winsys
*winsys
, struct pipe_surface
**s
)
252 struct pipe_surface
*surf
= *s
;
254 if (surf
->refcount
== 0) {
256 winsys
->region_release(winsys
, &surf
->region
);
265 intel_printf( struct pipe_winsys
*winsys
, const char *fmtString
, ... )
268 va_start( args
, fmtString
);
269 vfprintf(stderr
, fmtString
, args
);
274 intel_get_name( struct pipe_winsys
*winsys
)
276 return "Intel/DRI/ttm";
281 intel_create_pipe_winsys( int fd
)
283 struct intel_pipe_winsys
*iws
= CALLOC_STRUCT( intel_pipe_winsys
);
285 /* Fill in this struct with callbacks that pipe will need to
286 * communicate with the window system, buffer manager, etc.
288 * Pipe would be happy with a malloc based memory manager, but
289 * the SwapBuffers implementation in this winsys driver requires
290 * that rendering be done to an appropriate _DriBufferObject.
292 iws
->winsys
.buffer_create
= intel_buffer_create
;
293 iws
->winsys
.user_buffer_create
= intel_user_buffer_create
;
294 iws
->winsys
.buffer_map
= intel_buffer_map
;
295 iws
->winsys
.buffer_unmap
= intel_buffer_unmap
;
296 iws
->winsys
.buffer_reference
= intel_buffer_reference
;
297 iws
->winsys
.buffer_data
= intel_buffer_data
;
298 iws
->winsys
.buffer_subdata
= intel_buffer_subdata
;
299 iws
->winsys
.buffer_get_subdata
= intel_buffer_get_subdata
;
300 iws
->winsys
.flush_frontbuffer
= intel_flush_frontbuffer
;
301 iws
->winsys
.printf
= intel_printf
;
302 iws
->winsys
.get_name
= intel_get_name
;
303 iws
->winsys
.region_alloc
= intel_i915_region_alloc
;
304 iws
->winsys
.region_release
= intel_i915_region_release
;
305 iws
->winsys
.surface_pitch
= intel_i915_surface_pitch
;
306 iws
->winsys
.surface_alloc
= intel_i915_surface_alloc
;
307 iws
->winsys
.surface_release
= intel_i915_surface_release
;
310 iws
->regionPool
= driDRMPoolInit(fd
);
317 intel_destroy_pipe_winsys( struct pipe_winsys
*winsys
)
319 struct intel_pipe_winsys
*iws
= intel_pipe_winsys(winsys
);
320 if (iws
->regionPool
) {
321 driPoolTakeDown(iws
->regionPool
);