1 /**************************************************************************
3 * Copyright 2007 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 **************************************************************************/
36 #include "glxheader.h"
39 #include "pipe/p_winsys.h"
40 #include "pipe/p_inlines.h"
41 #include "util/u_math.h"
42 #include "util/u_memory.h"
43 #include "i965simple/brw_winsys.h"
44 #include "i965simple/brw_screen.h"
46 #include "xm_winsys_aub.h"
56 boolean dump_on_unmap
;
61 struct aub_pipe_winsys
{
62 struct pipe_winsys winsys
;
64 struct brw_aubfile
*aubfile
;
66 /* This is simple, isn't it:
74 /* Turn a pipe winsys into an aub/pipe winsys:
76 static inline struct aub_pipe_winsys
*
77 aub_pipe_winsys( struct pipe_winsys
*winsys
)
79 return (struct aub_pipe_winsys
*)winsys
;
84 static INLINE
struct aub_buffer
*
85 aub_bo( struct pipe_buffer
*bo
)
87 return (struct aub_buffer
*)bo
;
90 static INLINE
struct pipe_buffer
*
91 pipe_bo( struct aub_buffer
*bo
)
93 return (struct pipe_buffer
*)bo
;
99 static void *aub_buffer_map(struct pipe_winsys
*winsys
,
100 struct pipe_buffer
*buf
,
103 struct aub_buffer
*sbo
= aub_bo(buf
);
107 if (flags
& PIPE_BUFFER_USAGE_CPU_WRITE
)
108 sbo
->dump_on_unmap
= 1;
114 static void aub_buffer_unmap(struct pipe_winsys
*winsys
,
115 struct pipe_buffer
*buf
)
117 struct aub_pipe_winsys
*iws
= aub_pipe_winsys(winsys
);
118 struct aub_buffer
*sbo
= aub_bo(buf
);
122 if (sbo
->map_count
== 0 &&
123 sbo
->dump_on_unmap
) {
125 sbo
->dump_on_unmap
= 0;
127 brw_aub_gtt_data( iws
->aubfile
,
138 aub_buffer_destroy(struct pipe_winsys
*winsys
,
139 struct pipe_buffer
*buf
)
145 void xmesa_buffer_subdata_aub(struct pipe_winsys
*winsys
,
146 struct pipe_buffer
*buf
,
147 unsigned long offset
,
151 unsigned aub_sub_type
)
153 struct aub_pipe_winsys
*iws
= aub_pipe_winsys(winsys
);
154 struct aub_buffer
*sbo
= aub_bo(buf
);
156 assert(sbo
->size
> offset
+ size
);
157 memcpy(sbo
->data
+ offset
, data
, size
);
159 brw_aub_gtt_data( iws
->aubfile
,
160 sbo
->offset
+ offset
,
167 void xmesa_commands_aub(struct pipe_winsys
*winsys
,
171 struct aub_pipe_winsys
*iws
= aub_pipe_winsys(winsys
);
172 unsigned size
= nr_dwords
* 4;
174 assert(iws
->used
+ size
< iws
->size
);
176 brw_aub_gtt_cmds( iws
->aubfile
,
177 AUB_BUF_START
+ iws
->used
,
179 nr_dwords
* sizeof(int) );
181 iws
->used
+= align(size
, 4096);
185 static struct aub_pipe_winsys
*global_winsys
= NULL
;
187 void xmesa_display_aub( /* struct pipe_winsys *winsys, */
188 struct pipe_surface
*surface
)
190 // struct aub_pipe_winsys *iws = aub_pipe_winsys(winsys);
191 brw_aub_dump_bmp( global_winsys
->aubfile
,
193 aub_bo(surface
->buffer
)->offset
);
198 /* Pipe has no concept of pools. We choose the tex/region pool
201 static struct pipe_buffer
*
202 aub_buffer_create(struct pipe_winsys
*winsys
,
207 struct aub_pipe_winsys
*iws
= aub_pipe_winsys(winsys
);
208 struct aub_buffer
*sbo
= CALLOC_STRUCT(aub_buffer
);
212 /* Could reuse buffers that are not referenced in current
213 * batchbuffer. Can't do that atm, so always reallocate:
215 assert(iws
->used
+ size
< iws
->size
);
216 sbo
->data
= iws
->pool
+ iws
->used
;
217 sbo
->offset
= AUB_BUF_START
+ iws
->used
;
218 iws
->used
+= align(size
, 4096);
226 static struct pipe_buffer
*
227 aub_user_buffer_create(struct pipe_winsys
*winsys
, void *ptr
, unsigned bytes
)
229 struct aub_buffer
*sbo
;
231 /* Lets hope this is meant for upload, not as a result!
233 sbo
= aub_bo(aub_buffer_create( winsys
, 0, 0, 0 ));
242 /* The state tracker (should!) keep track of whether the fake
243 * frontbuffer has been touched by any rendering since the last time
244 * we copied its contents to the real frontbuffer. Our task is easy:
247 aub_flush_frontbuffer( struct pipe_winsys
*winsys
,
248 struct pipe_surface
*surf
,
249 void *context_private
)
251 xmesa_display_aub( surf
);
254 static struct pipe_surface
*
255 aub_i915_surface_alloc(struct pipe_winsys
*winsys
)
257 struct pipe_surface
*surf
= CALLOC_STRUCT(pipe_surface
);
260 surf
->winsys
= winsys
;
267 * Round n up to next multiple.
269 static INLINE
unsigned
270 round_up(unsigned n
, unsigned multiple
)
272 return (n
+ multiple
- 1) & ~(multiple
- 1);
276 aub_i915_surface_alloc_storage(struct pipe_winsys
*winsys
,
277 struct pipe_surface
*surf
,
278 unsigned width
, unsigned height
,
279 enum pipe_format format
,
283 const unsigned alignment
= 64;
286 surf
->height
= height
;
287 surf
->format
= format
;
288 pf_get_block(format
, &surf
->block
);
289 surf
->nblocksx
= pf_get_nblocksx(&surf
->block
, width
);
290 surf
->nblocksy
= pf_get_nblocksy(&surf
->block
, height
);
291 surf
->stride
= round_up(surf
->nblocksx
* surf
->block
.size
, alignment
);
294 assert(!surf
->buffer
);
295 surf
->buffer
= winsys
->buffer_create(winsys
, alignment
,
296 PIPE_BUFFER_USAGE_PIXEL
,
297 surf
->stride
* surf
->nblocksy
);
305 aub_i915_surface_release(struct pipe_winsys
*winsys
, struct pipe_surface
**s
)
307 struct pipe_surface
*surf
= *s
;
309 if (surf
->refcount
== 0) {
311 pipe_buffer_reference(winsys
, &surf
->buffer
, NULL
);
320 aub_get_name( struct pipe_winsys
*winsys
)
326 xmesa_create_pipe_winsys_aub( void )
328 struct aub_pipe_winsys
*iws
= CALLOC_STRUCT( aub_pipe_winsys
);
330 /* Fill in this struct with callbacks that pipe will need to
331 * communicate with the window system, buffer manager, etc.
333 * Pipe would be happy with a malloc based memory manager, but
334 * the SwapBuffers implementation in this winsys driver requires
335 * that rendering be done to an appropriate _DriBufferObject.
337 iws
->winsys
.buffer_create
= aub_buffer_create
;
338 iws
->winsys
.user_buffer_create
= aub_user_buffer_create
;
339 iws
->winsys
.buffer_map
= aub_buffer_map
;
340 iws
->winsys
.buffer_unmap
= aub_buffer_unmap
;
341 iws
->winsys
.buffer_destroy
= aub_buffer_destroy
;
342 iws
->winsys
.flush_frontbuffer
= aub_flush_frontbuffer
;
343 iws
->winsys
.get_name
= aub_get_name
;
345 iws
->winsys
.surface_alloc
= aub_i915_surface_alloc
;
346 iws
->winsys
.surface_alloc_storage
= aub_i915_surface_alloc_storage
;
347 iws
->winsys
.surface_release
= aub_i915_surface_release
;
349 iws
->aubfile
= brw_aubfile_create();
350 iws
->size
= AUB_BUF_SIZE
;
351 iws
->pool
= malloc(AUB_BUF_SIZE
);
353 /* HACK: static copy of this pointer:
355 assert(global_winsys
== NULL
);
363 xmesa_destroy_pipe_winsys_aub( struct pipe_winsys
*winsys
)
366 struct aub_pipe_winsys
*iws
= aub_pipe_winsys(winsys
);
367 brw_aub_destroy(iws
->aubfile
);
378 #define IWS_BATCHBUFFER_SIZE 1024
380 struct aub_brw_winsys
{
381 struct brw_winsys winsys
; /**< batch buffer funcs */
382 struct aub_context
*aub
;
384 struct pipe_winsys
*pipe_winsys
;
386 unsigned batch_data
[IWS_BATCHBUFFER_SIZE
];
389 unsigned batch_alloc
;
393 /* Turn a i965simple winsys into an aub/i965simple winsys:
395 static inline struct aub_brw_winsys
*
396 aub_brw_winsys( struct brw_winsys
*sws
)
398 return (struct aub_brw_winsys
*)sws
;
402 /* Simple batchbuffer interface:
405 static unsigned *aub_i965_batch_start( struct brw_winsys
*sws
,
409 struct aub_brw_winsys
*iws
= aub_brw_winsys(sws
);
411 if (iws
->batch_size
< iws
->batch_nr
+ dwords
)
414 iws
->batch_alloc
= iws
->batch_nr
+ dwords
;
415 return (void *)1; /* not a valid pointer! */
418 static void aub_i965_batch_dword( struct brw_winsys
*sws
,
421 struct aub_brw_winsys
*iws
= aub_brw_winsys(sws
);
423 assert(iws
->batch_nr
< iws
->batch_alloc
);
424 iws
->batch_data
[iws
->batch_nr
++] = dword
;
427 static void aub_i965_batch_reloc( struct brw_winsys
*sws
,
428 struct pipe_buffer
*buf
,
429 unsigned access_flags
,
432 struct aub_brw_winsys
*iws
= aub_brw_winsys(sws
);
434 assert(iws
->batch_nr
< iws
->batch_alloc
);
435 iws
->batch_data
[iws
->batch_nr
++] = aub_bo(buf
)->offset
+ delta
;
438 static unsigned aub_i965_get_buffer_offset( struct brw_winsys
*sws
,
439 struct pipe_buffer
*buf
,
440 unsigned access_flags
)
442 return aub_bo(buf
)->offset
;
445 static void aub_i965_batch_end( struct brw_winsys
*sws
)
447 struct aub_brw_winsys
*iws
= aub_brw_winsys(sws
);
449 assert(iws
->batch_nr
<= iws
->batch_alloc
);
450 iws
->batch_alloc
= 0;
453 static void aub_i965_batch_flush( struct brw_winsys
*sws
,
454 struct pipe_fence_handle
**fence
)
456 struct aub_brw_winsys
*iws
= aub_brw_winsys(sws
);
457 assert(iws
->batch_nr
<= iws
->batch_size
);
460 xmesa_commands_aub( iws
->pipe_winsys
,
470 static void aub_i965_buffer_subdata_typed(struct brw_winsys
*winsys
,
471 struct pipe_buffer
*buf
,
472 unsigned long offset
,
477 struct aub_brw_winsys
*iws
= aub_brw_winsys(winsys
);
478 unsigned aub_type
= DW_GENERAL_STATE
;
479 unsigned aub_sub_type
;
483 aub_sub_type
= DWGS_COLOR_CALC_VIEWPORT_STATE
;
486 aub_sub_type
= DWGS_COLOR_CALC_STATE
;
489 aub_sub_type
= DWGS_KERNEL_INSTRUCTIONS
;
491 case BRW_SAMPLER_DEFAULT_COLOR
:
492 aub_sub_type
= DWGS_SAMPLER_DEFAULT_COLOR
;
495 aub_sub_type
= DWGS_SAMPLER_STATE
;
498 aub_sub_type
= DWGS_WINDOWER_IZ_STATE
;
501 aub_sub_type
= DWGS_KERNEL_INSTRUCTIONS
;
504 aub_sub_type
= DWGS_STRIPS_FANS_VIEWPORT_STATE
;
507 aub_sub_type
= DWGS_STRIPS_FANS_STATE
;
510 aub_sub_type
= DWGS_VERTEX_SHADER_STATE
;
513 aub_sub_type
= DWGS_KERNEL_INSTRUCTIONS
;
516 aub_sub_type
= DWGS_GEOMETRY_SHADER_STATE
;
519 aub_sub_type
= DWGS_KERNEL_INSTRUCTIONS
;
522 aub_sub_type
= DWGS_CLIPPER_VIEWPORT_STATE
;
525 aub_sub_type
= DWGS_CLIPPER_STATE
;
528 aub_sub_type
= DWGS_KERNEL_INSTRUCTIONS
;
531 aub_type
= DW_SURFACE_STATE
;
532 aub_sub_type
= DWSS_SURFACE_STATE
;
534 case BRW_SS_SURF_BIND
:
535 aub_type
= DW_SURFACE_STATE
;
536 aub_sub_type
= DWSS_BINDING_TABLE_STATE
;
538 case BRW_CONSTANT_BUFFER
:
539 aub_type
= DW_CONSTANT_URB_ENTRY
;
548 xmesa_buffer_subdata_aub( iws
->pipe_winsys
,
558 * Create i965 hardware rendering context.
560 struct pipe_context
*
561 xmesa_create_i965simple( struct pipe_winsys
*winsys
)
563 struct aub_brw_winsys
*iws
= CALLOC_STRUCT( aub_brw_winsys
);
564 struct pipe_screen
*screen
= brw_create_screen(winsys
, 0/* XXX pci_id */);
566 /* Fill in this struct with callbacks that i965simple will need to
567 * communicate with the window system, buffer manager, etc.
569 iws
->winsys
.batch_start
= aub_i965_batch_start
;
570 iws
->winsys
.batch_dword
= aub_i965_batch_dword
;
571 iws
->winsys
.batch_reloc
= aub_i965_batch_reloc
;
572 iws
->winsys
.batch_end
= aub_i965_batch_end
;
573 iws
->winsys
.batch_flush
= aub_i965_batch_flush
;
574 iws
->winsys
.buffer_subdata_typed
= aub_i965_buffer_subdata_typed
;
575 iws
->winsys
.get_buffer_offset
= aub_i965_get_buffer_offset
;
577 iws
->pipe_winsys
= winsys
;
579 iws
->batch_size
= IWS_BATCHBUFFER_SIZE
;
581 /* Create the i965simple context:
583 return brw_create( screen
,