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_util.h"
41 #include "pipe/p_inlines.h"
42 #include "i965simple/brw_winsys.h"
43 #include "i965simple/brw_screen.h"
45 #include "xm_winsys_aub.h"
55 boolean dump_on_unmap
;
60 struct aub_pipe_winsys
{
61 struct pipe_winsys winsys
;
63 struct brw_aubfile
*aubfile
;
65 /* This is simple, isn't it:
73 /* Turn a pipe winsys into an aub/pipe winsys:
75 static inline struct aub_pipe_winsys
*
76 aub_pipe_winsys( struct pipe_winsys
*winsys
)
78 return (struct aub_pipe_winsys
*)winsys
;
83 static INLINE
struct aub_buffer
*
84 aub_bo( struct pipe_buffer
*bo
)
86 return (struct aub_buffer
*)bo
;
89 static INLINE
struct pipe_buffer
*
90 pipe_bo( struct aub_buffer
*bo
)
92 return (struct pipe_buffer
*)bo
;
98 static void *aub_buffer_map(struct pipe_winsys
*winsys
,
99 struct pipe_buffer
*buf
,
102 struct aub_buffer
*sbo
= aub_bo(buf
);
106 if (flags
& PIPE_BUFFER_USAGE_CPU_WRITE
)
107 sbo
->dump_on_unmap
= 1;
113 static void aub_buffer_unmap(struct pipe_winsys
*winsys
,
114 struct pipe_buffer
*buf
)
116 struct aub_pipe_winsys
*iws
= aub_pipe_winsys(winsys
);
117 struct aub_buffer
*sbo
= aub_bo(buf
);
121 if (sbo
->map_count
== 0 &&
122 sbo
->dump_on_unmap
) {
124 sbo
->dump_on_unmap
= 0;
126 brw_aub_gtt_data( iws
->aubfile
,
137 aub_buffer_destroy(struct pipe_winsys
*winsys
,
138 struct pipe_buffer
*buf
)
144 void xmesa_buffer_subdata_aub(struct pipe_winsys
*winsys
,
145 struct pipe_buffer
*buf
,
146 unsigned long offset
,
150 unsigned aub_sub_type
)
152 struct aub_pipe_winsys
*iws
= aub_pipe_winsys(winsys
);
153 struct aub_buffer
*sbo
= aub_bo(buf
);
155 assert(sbo
->size
> offset
+ size
);
156 memcpy(sbo
->data
+ offset
, data
, size
);
158 brw_aub_gtt_data( iws
->aubfile
,
159 sbo
->offset
+ offset
,
166 void xmesa_commands_aub(struct pipe_winsys
*winsys
,
170 struct aub_pipe_winsys
*iws
= aub_pipe_winsys(winsys
);
171 unsigned size
= nr_dwords
* 4;
173 assert(iws
->used
+ size
< iws
->size
);
175 brw_aub_gtt_cmds( iws
->aubfile
,
176 AUB_BUF_START
+ iws
->used
,
178 nr_dwords
* sizeof(int) );
180 iws
->used
+= align(size
, 4096);
184 static struct aub_pipe_winsys
*global_winsys
= NULL
;
186 void xmesa_display_aub( /* struct pipe_winsys *winsys, */
187 struct pipe_surface
*surface
)
189 // struct aub_pipe_winsys *iws = aub_pipe_winsys(winsys);
190 brw_aub_dump_bmp( global_winsys
->aubfile
,
192 aub_bo(surface
->buffer
)->offset
);
197 /* Pipe has no concept of pools. We choose the tex/region pool
200 static struct pipe_buffer
*
201 aub_buffer_create(struct pipe_winsys
*winsys
,
206 struct aub_pipe_winsys
*iws
= aub_pipe_winsys(winsys
);
207 struct aub_buffer
*sbo
= CALLOC_STRUCT(aub_buffer
);
211 /* Could reuse buffers that are not referenced in current
212 * batchbuffer. Can't do that atm, so always reallocate:
214 assert(iws
->used
+ size
< iws
->size
);
215 sbo
->data
= iws
->pool
+ iws
->used
;
216 sbo
->offset
= AUB_BUF_START
+ iws
->used
;
217 iws
->used
+= align(size
, 4096);
225 static struct pipe_buffer
*
226 aub_user_buffer_create(struct pipe_winsys
*winsys
, void *ptr
, unsigned bytes
)
228 struct aub_buffer
*sbo
;
230 /* Lets hope this is meant for upload, not as a result!
232 sbo
= aub_bo(aub_buffer_create( winsys
, 0, 0, 0 ));
241 /* The state tracker (should!) keep track of whether the fake
242 * frontbuffer has been touched by any rendering since the last time
243 * we copied its contents to the real frontbuffer. Our task is easy:
246 aub_flush_frontbuffer( struct pipe_winsys
*winsys
,
247 struct pipe_surface
*surf
,
248 void *context_private
)
250 xmesa_display_aub( surf
);
253 static struct pipe_surface
*
254 aub_i915_surface_alloc(struct pipe_winsys
*winsys
)
256 struct pipe_surface
*surf
= CALLOC_STRUCT(pipe_surface
);
259 surf
->winsys
= winsys
;
266 * Round n up to next multiple.
268 static INLINE
unsigned
269 round_up(unsigned n
, unsigned multiple
)
271 return (n
+ multiple
- 1) & ~(multiple
- 1);
275 aub_i915_surface_alloc_storage(struct pipe_winsys
*winsys
,
276 struct pipe_surface
*surf
,
277 unsigned width
, unsigned height
,
278 enum pipe_format format
,
282 const unsigned alignment
= 64;
285 surf
->height
= height
;
286 surf
->format
= format
;
287 surf
->cpp
= pf_get_size(format
);
288 surf
->pitch
= round_up(width
, alignment
/ surf
->cpp
);
290 assert(!surf
->buffer
);
291 surf
->buffer
= winsys
->buffer_create(winsys
, alignment
,
292 PIPE_BUFFER_USAGE_PIXEL
,
293 surf
->pitch
* surf
->cpp
* height
);
301 aub_i915_surface_release(struct pipe_winsys
*winsys
, struct pipe_surface
**s
)
303 struct pipe_surface
*surf
= *s
;
305 if (surf
->refcount
== 0) {
307 pipe_buffer_reference(winsys
, &surf
->buffer
, NULL
);
316 aub_get_name( struct pipe_winsys
*winsys
)
322 xmesa_create_pipe_winsys_aub( void )
324 struct aub_pipe_winsys
*iws
= CALLOC_STRUCT( aub_pipe_winsys
);
326 /* Fill in this struct with callbacks that pipe will need to
327 * communicate with the window system, buffer manager, etc.
329 * Pipe would be happy with a malloc based memory manager, but
330 * the SwapBuffers implementation in this winsys driver requires
331 * that rendering be done to an appropriate _DriBufferObject.
333 iws
->winsys
.buffer_create
= aub_buffer_create
;
334 iws
->winsys
.user_buffer_create
= aub_user_buffer_create
;
335 iws
->winsys
.buffer_map
= aub_buffer_map
;
336 iws
->winsys
.buffer_unmap
= aub_buffer_unmap
;
337 iws
->winsys
.buffer_destroy
= aub_buffer_destroy
;
338 iws
->winsys
.flush_frontbuffer
= aub_flush_frontbuffer
;
339 iws
->winsys
.get_name
= aub_get_name
;
341 iws
->winsys
.surface_alloc
= aub_i915_surface_alloc
;
342 iws
->winsys
.surface_alloc_storage
= aub_i915_surface_alloc_storage
;
343 iws
->winsys
.surface_release
= aub_i915_surface_release
;
345 iws
->aubfile
= brw_aubfile_create();
346 iws
->size
= AUB_BUF_SIZE
;
347 iws
->pool
= malloc(AUB_BUF_SIZE
);
349 /* HACK: static copy of this pointer:
351 assert(global_winsys
== NULL
);
359 xmesa_destroy_pipe_winsys_aub( struct pipe_winsys
*winsys
)
362 struct aub_pipe_winsys
*iws
= aub_pipe_winsys(winsys
);
363 brw_aub_destroy(iws
->aubfile
);
374 #define IWS_BATCHBUFFER_SIZE 1024
376 struct aub_brw_winsys
{
377 struct brw_winsys winsys
; /**< batch buffer funcs */
378 struct aub_context
*aub
;
380 struct pipe_winsys
*pipe_winsys
;
382 unsigned batch_data
[IWS_BATCHBUFFER_SIZE
];
385 unsigned batch_alloc
;
389 /* Turn a i965simple winsys into an aub/i965simple winsys:
391 static inline struct aub_brw_winsys
*
392 aub_brw_winsys( struct brw_winsys
*sws
)
394 return (struct aub_brw_winsys
*)sws
;
398 /* Simple batchbuffer interface:
401 static unsigned *aub_i965_batch_start( struct brw_winsys
*sws
,
405 struct aub_brw_winsys
*iws
= aub_brw_winsys(sws
);
407 if (iws
->batch_size
< iws
->batch_nr
+ dwords
)
410 iws
->batch_alloc
= iws
->batch_nr
+ dwords
;
411 return (void *)1; /* not a valid pointer! */
414 static void aub_i965_batch_dword( struct brw_winsys
*sws
,
417 struct aub_brw_winsys
*iws
= aub_brw_winsys(sws
);
419 assert(iws
->batch_nr
< iws
->batch_alloc
);
420 iws
->batch_data
[iws
->batch_nr
++] = dword
;
423 static void aub_i965_batch_reloc( struct brw_winsys
*sws
,
424 struct pipe_buffer
*buf
,
425 unsigned access_flags
,
428 struct aub_brw_winsys
*iws
= aub_brw_winsys(sws
);
430 assert(iws
->batch_nr
< iws
->batch_alloc
);
431 iws
->batch_data
[iws
->batch_nr
++] = aub_bo(buf
)->offset
+ delta
;
434 static unsigned aub_i965_get_buffer_offset( struct brw_winsys
*sws
,
435 struct pipe_buffer
*buf
,
436 unsigned access_flags
)
438 return aub_bo(buf
)->offset
;
441 static void aub_i965_batch_end( struct brw_winsys
*sws
)
443 struct aub_brw_winsys
*iws
= aub_brw_winsys(sws
);
445 assert(iws
->batch_nr
<= iws
->batch_alloc
);
446 iws
->batch_alloc
= 0;
449 static void aub_i965_batch_flush( struct brw_winsys
*sws
,
450 struct pipe_fence_handle
**fence
)
452 struct aub_brw_winsys
*iws
= aub_brw_winsys(sws
);
453 assert(iws
->batch_nr
<= iws
->batch_size
);
456 xmesa_commands_aub( iws
->pipe_winsys
,
466 static void aub_i965_buffer_subdata_typed(struct brw_winsys
*winsys
,
467 struct pipe_buffer
*buf
,
468 unsigned long offset
,
473 struct aub_brw_winsys
*iws
= aub_brw_winsys(winsys
);
474 unsigned aub_type
= DW_GENERAL_STATE
;
475 unsigned aub_sub_type
;
479 aub_sub_type
= DWGS_COLOR_CALC_VIEWPORT_STATE
;
482 aub_sub_type
= DWGS_COLOR_CALC_STATE
;
485 aub_sub_type
= DWGS_KERNEL_INSTRUCTIONS
;
487 case BRW_SAMPLER_DEFAULT_COLOR
:
488 aub_sub_type
= DWGS_SAMPLER_DEFAULT_COLOR
;
491 aub_sub_type
= DWGS_SAMPLER_STATE
;
494 aub_sub_type
= DWGS_WINDOWER_IZ_STATE
;
497 aub_sub_type
= DWGS_KERNEL_INSTRUCTIONS
;
500 aub_sub_type
= DWGS_STRIPS_FANS_VIEWPORT_STATE
;
503 aub_sub_type
= DWGS_STRIPS_FANS_STATE
;
506 aub_sub_type
= DWGS_VERTEX_SHADER_STATE
;
509 aub_sub_type
= DWGS_KERNEL_INSTRUCTIONS
;
512 aub_sub_type
= DWGS_GEOMETRY_SHADER_STATE
;
515 aub_sub_type
= DWGS_KERNEL_INSTRUCTIONS
;
518 aub_sub_type
= DWGS_CLIPPER_VIEWPORT_STATE
;
521 aub_sub_type
= DWGS_CLIPPER_STATE
;
524 aub_sub_type
= DWGS_KERNEL_INSTRUCTIONS
;
527 aub_type
= DW_SURFACE_STATE
;
528 aub_sub_type
= DWSS_SURFACE_STATE
;
530 case BRW_SS_SURF_BIND
:
531 aub_type
= DW_SURFACE_STATE
;
532 aub_sub_type
= DWSS_BINDING_TABLE_STATE
;
534 case BRW_CONSTANT_BUFFER
:
535 aub_type
= DW_CONSTANT_URB_ENTRY
;
544 xmesa_buffer_subdata_aub( iws
->pipe_winsys
,
554 * Create i965 hardware rendering context.
556 struct pipe_context
*
557 xmesa_create_i965simple( struct pipe_winsys
*winsys
)
559 struct aub_brw_winsys
*iws
= CALLOC_STRUCT( aub_brw_winsys
);
560 struct pipe_screen
*screen
= brw_create_screen(winsys
, 0/* XXX pci_id */);
562 /* Fill in this struct with callbacks that i965simple will need to
563 * communicate with the window system, buffer manager, etc.
565 iws
->winsys
.batch_start
= aub_i965_batch_start
;
566 iws
->winsys
.batch_dword
= aub_i965_batch_dword
;
567 iws
->winsys
.batch_reloc
= aub_i965_batch_reloc
;
568 iws
->winsys
.batch_end
= aub_i965_batch_end
;
569 iws
->winsys
.batch_flush
= aub_i965_batch_flush
;
570 iws
->winsys
.buffer_subdata_typed
= aub_i965_buffer_subdata_typed
;
571 iws
->winsys
.get_buffer_offset
= aub_i965_get_buffer_offset
;
573 iws
->pipe_winsys
= winsys
;
575 iws
->batch_size
= IWS_BATCHBUFFER_SIZE
;
577 /* Create the i965simple context:
579 return brw_create( screen
,