1cdc920a0Smrg/**************************************************************************
2cdc920a0Smrg *
3cdc920a0Smrg * Copyright 2009 VMware, Inc.
4cdc920a0Smrg * All Rights Reserved.
5cdc920a0Smrg *
6cdc920a0Smrg * Permission is hereby granted, free of charge, to any person obtaining a
7cdc920a0Smrg * copy of this software and associated documentation files (the
8cdc920a0Smrg * "Software"), to deal in the Software without restriction, including
9cdc920a0Smrg * without limitation the rights to use, copy, modify, merge, publish,
10cdc920a0Smrg * distribute, sub license, and/or sell copies of the Software, and to
11cdc920a0Smrg * permit persons to whom the Software is furnished to do so, subject to
12cdc920a0Smrg * the following conditions:
13cdc920a0Smrg *
14cdc920a0Smrg * The above copyright notice and this permission notice (including the
15cdc920a0Smrg * next paragraph) shall be included in all copies or substantial portions
16cdc920a0Smrg * of the Software.
17cdc920a0Smrg *
18cdc920a0Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19cdc920a0Smrg * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20cdc920a0Smrg * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21cdc920a0Smrg * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
22cdc920a0Smrg * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23cdc920a0Smrg * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24cdc920a0Smrg * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25cdc920a0Smrg *
26cdc920a0Smrg **************************************************************************/
27cdc920a0Smrg
28cdc920a0Smrg
29cdc920a0Smrg/**
30cdc920a0Smrg * Binner data structures and bin-related functions.
31cdc920a0Smrg * Note: the "setup" code is concerned with building scenes while
32cdc920a0Smrg * The "rast" code is concerned with consuming/executing scenes.
33cdc920a0Smrg */
34cdc920a0Smrg
35cdc920a0Smrg#ifndef LP_SCENE_H
36cdc920a0Smrg#define LP_SCENE_H
37cdc920a0Smrg
38cdc920a0Smrg#include "os/os_thread.h"
39cdc920a0Smrg#include "lp_rast.h"
403464ebd5Sriastradh#include "lp_debug.h"
41cdc920a0Smrg
42cdc920a0Smrgstruct lp_scene_queue;
433464ebd5Sriastradhstruct lp_rast_state;
44cdc920a0Smrg
45cdc920a0Smrg/* We're limited to 2K by 2K for 32bit fixed point rasterization.
46cdc920a0Smrg * Will need a 64-bit version for larger framebuffers.
47cdc920a0Smrg */
483464ebd5Sriastradh#define TILES_X (LP_MAX_WIDTH / TILE_SIZE)
493464ebd5Sriastradh#define TILES_Y (LP_MAX_HEIGHT / TILE_SIZE)
50cdc920a0Smrg
51cdc920a0Smrg
52af69d88dSmrg/* Commands per command block (ideally so sizeof(cmd_block) is a power of
53af69d88dSmrg * two in size.)
54af69d88dSmrg */
55af69d88dSmrg#define CMD_BLOCK_MAX 29
56af69d88dSmrg
577ec681f3Smrg/* Bytes per data block.  This effectively limits the maximum constant buffer
587ec681f3Smrg * size.
59af69d88dSmrg */
603464ebd5Sriastradh#define DATA_BLOCK_SIZE (64 * 1024)
613464ebd5Sriastradh
623464ebd5Sriastradh/* Scene temporary storage is clamped to this size:
633464ebd5Sriastradh */
647ec681f3Smrg#define LP_SCENE_MAX_SIZE (36*1024*1024)
653464ebd5Sriastradh
663464ebd5Sriastradh/* The maximum amount of texture storage referenced by a scene is
6701e04c3fSmrg * clamped to this size:
683464ebd5Sriastradh */
693464ebd5Sriastradh#define LP_SCENE_MAX_RESOURCE_SIZE (64*1024*1024)
70cdc920a0Smrg
71cdc920a0Smrg
72cdc920a0Smrg/* switch to a non-pointer value for this:
73cdc920a0Smrg */
743464ebd5Sriastradhtypedef void (*lp_rast_cmd_func)( struct lp_rasterizer_task *,
753464ebd5Sriastradh                                  const union lp_rast_cmd_arg );
76cdc920a0Smrg
773464ebd5Sriastradh
78cdc920a0Smrgstruct cmd_block {
793464ebd5Sriastradh   uint8_t cmd[CMD_BLOCK_MAX];
80cdc920a0Smrg   union lp_rast_cmd_arg arg[CMD_BLOCK_MAX];
81cdc920a0Smrg   unsigned count;
82cdc920a0Smrg   struct cmd_block *next;
83cdc920a0Smrg};
84cdc920a0Smrg
853464ebd5Sriastradh
86cdc920a0Smrgstruct data_block {
87cdc920a0Smrg   ubyte data[DATA_BLOCK_SIZE];
88cdc920a0Smrg   unsigned used;
89cdc920a0Smrg   struct data_block *next;
90cdc920a0Smrg};
91cdc920a0Smrg
923464ebd5Sriastradh
93cdc920a0Smrg
94cdc920a0Smrg/**
95cdc920a0Smrg * For each screen tile we have one of these bins.
96cdc920a0Smrg */
97cdc920a0Smrgstruct cmd_bin {
983464ebd5Sriastradh   const struct lp_rast_state *last_state;       /* most recent state set in bin */
993464ebd5Sriastradh   struct cmd_block *head;
1003464ebd5Sriastradh   struct cmd_block *tail;
101cdc920a0Smrg};
102cdc920a0Smrg
103cdc920a0Smrg
104cdc920a0Smrg/**
1053464ebd5Sriastradh * This stores bulk data which is used for all memory allocations
1063464ebd5Sriastradh * within a scene.
1073464ebd5Sriastradh *
108cdc920a0Smrg * Examples include triangle data and state data.  The commands in
109cdc920a0Smrg * the per-tile bins will point to chunks of data in this structure.
1103464ebd5Sriastradh *
1113464ebd5Sriastradh * Include the first block of data statically to ensure we can always
1123464ebd5Sriastradh * initiate a scene without relying on malloc succeeding.
113cdc920a0Smrg */
114cdc920a0Smrgstruct data_block_list {
1153464ebd5Sriastradh   struct data_block first;
116cdc920a0Smrg   struct data_block *head;
117cdc920a0Smrg};
118cdc920a0Smrg
1193464ebd5Sriastradhstruct resource_ref;
120cdc920a0Smrg
1217ec681f3Smrgstruct shader_ref;
1227ec681f3Smrg
1237ec681f3Smrgstruct lp_scene_surface {
1247ec681f3Smrg   uint8_t *map;
1257ec681f3Smrg   unsigned stride;
1267ec681f3Smrg   unsigned layer_stride;
1277ec681f3Smrg   unsigned format_bytes;
1287ec681f3Smrg   unsigned sample_stride;
1297ec681f3Smrg   unsigned nr_samples;
1307ec681f3Smrg};
1317ec681f3Smrg
132cdc920a0Smrg/**
133cdc920a0Smrg * All bins and bin data are contained here.
134cdc920a0Smrg * Per-bin data goes into the 'tile' bins.
135cdc920a0Smrg * Shared data goes into the 'data' buffer.
136cdc920a0Smrg *
137cdc920a0Smrg * When there are multiple threads, will want to double-buffer between
138cdc920a0Smrg * scenes:
139cdc920a0Smrg */
140cdc920a0Smrgstruct lp_scene {
141cdc920a0Smrg   struct pipe_context *pipe;
1423464ebd5Sriastradh   struct lp_fence *fence;
143cdc920a0Smrg
144af69d88dSmrg   /* The queries still active at end of scene */
145af69d88dSmrg   struct llvmpipe_query *active_queries[LP_MAX_ACTIVE_BINNED_QUERIES];
146af69d88dSmrg   unsigned num_active_queries;
147af69d88dSmrg   /* If queries were either active or there were begin/end query commands */
148af69d88dSmrg   boolean had_queries;
149af69d88dSmrg
1503464ebd5Sriastradh   /* Framebuffer mappings - valid only between begin_rasterization()
1513464ebd5Sriastradh    * and end_rasterization().
152cdc920a0Smrg    */
1537ec681f3Smrg   struct lp_scene_surface zsbuf, cbufs[PIPE_MAX_COLOR_BUFS];
154af69d88dSmrg
155af69d88dSmrg   /* The amount of layers in the fb (minimum of all attachments) */
156af69d88dSmrg   unsigned fb_max_layer;
157af69d88dSmrg
1587ec681f3Smrg   /* fixed point sample positions. */
1597ec681f3Smrg   int32_t fixed_sample_pos[LP_MAX_SAMPLES][2];
1607ec681f3Smrg
1617ec681f3Smrg   /* max samples for bound framebuffer */
1627ec681f3Smrg   unsigned fb_max_samples;
1637ec681f3Smrg
164cdc920a0Smrg   /** the framebuffer to render the scene into */
165cdc920a0Smrg   struct pipe_framebuffer_state fb;
166cdc920a0Smrg
1673464ebd5Sriastradh   /** list of resources referenced by the scene commands */
1683464ebd5Sriastradh   struct resource_ref *resources;
1693464ebd5Sriastradh
1707ec681f3Smrg   /** list of frag shaders referenced by the scene commands */
1717ec681f3Smrg   struct shader_ref *frag_shaders;
1727ec681f3Smrg
1733464ebd5Sriastradh   /** Total memory used by the scene (in bytes).  This sums all the
1743464ebd5Sriastradh    * data blocks and counts all bins, state, resource references and
1753464ebd5Sriastradh    * other random allocations within the scene.
1763464ebd5Sriastradh    */
1773464ebd5Sriastradh   unsigned scene_size;
1783464ebd5Sriastradh
1793464ebd5Sriastradh   /** Sum of sizes of all resources referenced by the scene.  Sums
1803464ebd5Sriastradh    * all the textures read by the scene:
1813464ebd5Sriastradh    */
1823464ebd5Sriastradh   unsigned resource_reference_size;
183cdc920a0Smrg
1843464ebd5Sriastradh   boolean alloc_failed;
1857ec681f3Smrg   boolean permit_linear_rasterizer;
1867ec681f3Smrg
187cdc920a0Smrg   /**
188cdc920a0Smrg    * Number of active tiles in each dimension.
189cdc920a0Smrg    * This basically the framebuffer size divided by tile size
190cdc920a0Smrg    */
191cdc920a0Smrg   unsigned tiles_x, tiles_y;
192cdc920a0Smrg
193cdc920a0Smrg   int curr_x, curr_y;  /**< for iterating over bins */
19401e04c3fSmrg   mtx_t mutex;
195cdc920a0Smrg
196cdc920a0Smrg   struct cmd_bin tile[TILES_X][TILES_Y];
197cdc920a0Smrg   struct data_block_list data;
198cdc920a0Smrg};
199cdc920a0Smrg
200cdc920a0Smrg
201cdc920a0Smrg
2023464ebd5Sriastradhstruct lp_scene *lp_scene_create(struct pipe_context *pipe);
203cdc920a0Smrg
204cdc920a0Smrgvoid lp_scene_destroy(struct lp_scene *scene);
205cdc920a0Smrg
206cdc920a0Smrgboolean lp_scene_is_empty(struct lp_scene *scene );
2073464ebd5Sriastradhboolean lp_scene_is_oom(struct lp_scene *scene );
208cdc920a0Smrg
209cdc920a0Smrg
2103464ebd5Sriastradhstruct data_block *lp_scene_new_data_block( struct lp_scene *scene );
211cdc920a0Smrg
2123464ebd5Sriastradhstruct cmd_block *lp_scene_new_cmd_block( struct lp_scene *scene,
2133464ebd5Sriastradh                                          struct cmd_bin *bin );
214cdc920a0Smrg
2153464ebd5Sriastradhboolean lp_scene_add_resource_reference(struct lp_scene *scene,
2163464ebd5Sriastradh                                        struct pipe_resource *resource,
2173464ebd5Sriastradh                                        boolean initializing_scene);
218cdc920a0Smrg
2193464ebd5Sriastradhboolean lp_scene_is_resource_referenced(const struct lp_scene *scene,
2203464ebd5Sriastradh                                        const struct pipe_resource *resource );
221cdc920a0Smrg
2227ec681f3Smrgboolean lp_scene_add_frag_shader_reference(struct lp_scene *scene,
2237ec681f3Smrg                                           struct lp_fragment_shader_variant *variant);
2247ec681f3Smrg
2257ec681f3Smrg
226cdc920a0Smrg
227cdc920a0Smrg/**
228cdc920a0Smrg * Allocate space for a command/data in the bin's data buffer.
229cdc920a0Smrg * Grow the block list if needed.
230cdc920a0Smrg */
23101e04c3fSmrgstatic inline void *
232cdc920a0Smrglp_scene_alloc( struct lp_scene *scene, unsigned size)
233cdc920a0Smrg{
234cdc920a0Smrg   struct data_block_list *list = &scene->data;
2353464ebd5Sriastradh   struct data_block *block = list->head;
2363464ebd5Sriastradh
2373464ebd5Sriastradh   assert(size <= DATA_BLOCK_SIZE);
2383464ebd5Sriastradh   assert(block != NULL);
2393464ebd5Sriastradh
2403464ebd5Sriastradh   if (LP_DEBUG & DEBUG_MEM)
2413464ebd5Sriastradh      debug_printf("alloc %u block %u/%u tot %u/%u\n",
2427ec681f3Smrg		   size, block->used, (unsigned)DATA_BLOCK_SIZE,
2433464ebd5Sriastradh		   scene->scene_size, LP_SCENE_MAX_SIZE);
2443464ebd5Sriastradh
2453464ebd5Sriastradh   if (block->used + size > DATA_BLOCK_SIZE) {
2463464ebd5Sriastradh      block = lp_scene_new_data_block( scene );
2473464ebd5Sriastradh      if (!block) {
2483464ebd5Sriastradh         /* out of memory */
2493464ebd5Sriastradh         return NULL;
2503464ebd5Sriastradh      }
251cdc920a0Smrg   }
252cdc920a0Smrg
253cdc920a0Smrg   {
2543464ebd5Sriastradh      ubyte *data = block->data + block->used;
2553464ebd5Sriastradh      block->used += size;
256cdc920a0Smrg      return data;
257cdc920a0Smrg   }
258cdc920a0Smrg}
259cdc920a0Smrg
260cdc920a0Smrg
261cdc920a0Smrg/**
262cdc920a0Smrg * As above, but with specific alignment.
263cdc920a0Smrg */
26401e04c3fSmrgstatic inline void *
265cdc920a0Smrglp_scene_alloc_aligned( struct lp_scene *scene, unsigned size,
266cdc920a0Smrg			unsigned alignment )
267cdc920a0Smrg{
268cdc920a0Smrg   struct data_block_list *list = &scene->data;
2693464ebd5Sriastradh   struct data_block *block = list->head;
2703464ebd5Sriastradh
2713464ebd5Sriastradh   assert(block != NULL);
2723464ebd5Sriastradh
2733464ebd5Sriastradh   if (LP_DEBUG & DEBUG_MEM)
2743464ebd5Sriastradh      debug_printf("alloc %u block %u/%u tot %u/%u\n",
2753464ebd5Sriastradh		   size + alignment - 1,
2767ec681f3Smrg		   block->used, (unsigned)DATA_BLOCK_SIZE,
2773464ebd5Sriastradh		   scene->scene_size, LP_SCENE_MAX_SIZE);
2783464ebd5Sriastradh
2793464ebd5Sriastradh   if (block->used + size + alignment - 1 > DATA_BLOCK_SIZE) {
2803464ebd5Sriastradh      block = lp_scene_new_data_block( scene );
2813464ebd5Sriastradh      if (!block)
2823464ebd5Sriastradh         return NULL;
283cdc920a0Smrg   }
284cdc920a0Smrg
285cdc920a0Smrg   {
2863464ebd5Sriastradh      ubyte *data = block->data + block->used;
287cdc920a0Smrg      unsigned offset = (((uintptr_t)data + alignment - 1) & ~(alignment - 1)) - (uintptr_t)data;
2883464ebd5Sriastradh      block->used += offset + size;
289cdc920a0Smrg      return data + offset;
290cdc920a0Smrg   }
291cdc920a0Smrg}
292cdc920a0Smrg
293cdc920a0Smrg
294cdc920a0Smrg/** Return pointer to a particular tile's bin. */
29501e04c3fSmrgstatic inline struct cmd_bin *
296cdc920a0Smrglp_scene_get_bin(struct lp_scene *scene, unsigned x, unsigned y)
297cdc920a0Smrg{
298cdc920a0Smrg   return &scene->tile[x][y];
299cdc920a0Smrg}
300cdc920a0Smrg
301cdc920a0Smrg
302cdc920a0Smrg/** Remove all commands from a bin */
303cdc920a0Smrgvoid
304cdc920a0Smrglp_scene_bin_reset(struct lp_scene *scene, unsigned x, unsigned y);
305cdc920a0Smrg
306cdc920a0Smrg
307cdc920a0Smrg/* Add a command to bin[x][y].
308cdc920a0Smrg */
30901e04c3fSmrgstatic inline boolean
310cdc920a0Smrglp_scene_bin_command( struct lp_scene *scene,
3113464ebd5Sriastradh                      unsigned x, unsigned y,
3123464ebd5Sriastradh                      unsigned cmd,
3133464ebd5Sriastradh                      union lp_rast_cmd_arg arg )
314cdc920a0Smrg{
315cdc920a0Smrg   struct cmd_bin *bin = lp_scene_get_bin(scene, x, y);
3163464ebd5Sriastradh   struct cmd_block *tail = bin->tail;
317cdc920a0Smrg
318cdc920a0Smrg   assert(x < scene->tiles_x);
319cdc920a0Smrg   assert(y < scene->tiles_y);
3203464ebd5Sriastradh   assert(cmd < LP_RAST_OP_MAX);
3213464ebd5Sriastradh
3223464ebd5Sriastradh   if (tail == NULL || tail->count == CMD_BLOCK_MAX) {
3233464ebd5Sriastradh      tail = lp_scene_new_cmd_block( scene, bin );
3243464ebd5Sriastradh      if (!tail) {
3253464ebd5Sriastradh         return FALSE;
3263464ebd5Sriastradh      }
3273464ebd5Sriastradh      assert(tail->count == 0);
328cdc920a0Smrg   }
329cdc920a0Smrg
330cdc920a0Smrg   {
331cdc920a0Smrg      unsigned i = tail->count;
3323464ebd5Sriastradh      tail->cmd[i] = cmd & LP_RAST_OP_MASK;
333cdc920a0Smrg      tail->arg[i] = arg;
334cdc920a0Smrg      tail->count++;
335cdc920a0Smrg   }
3363464ebd5Sriastradh
3373464ebd5Sriastradh   return TRUE;
3383464ebd5Sriastradh}
3393464ebd5Sriastradh
3403464ebd5Sriastradh
34101e04c3fSmrgstatic inline boolean
3423464ebd5Sriastradhlp_scene_bin_cmd_with_state( struct lp_scene *scene,
3433464ebd5Sriastradh                             unsigned x, unsigned y,
3443464ebd5Sriastradh                             const struct lp_rast_state *state,
3453464ebd5Sriastradh                             unsigned cmd,
3463464ebd5Sriastradh                             union lp_rast_cmd_arg arg )
3473464ebd5Sriastradh{
3483464ebd5Sriastradh   struct cmd_bin *bin = lp_scene_get_bin(scene, x, y);
3493464ebd5Sriastradh
3503464ebd5Sriastradh   if (state != bin->last_state) {
3513464ebd5Sriastradh      bin->last_state = state;
3523464ebd5Sriastradh      if (!lp_scene_bin_command(scene, x, y,
3533464ebd5Sriastradh                                LP_RAST_OP_SET_STATE,
3543464ebd5Sriastradh                                lp_rast_arg_state(state)))
3553464ebd5Sriastradh         return FALSE;
3563464ebd5Sriastradh   }
3573464ebd5Sriastradh
3583464ebd5Sriastradh   if (!lp_scene_bin_command( scene, x, y, cmd, arg ))
3593464ebd5Sriastradh      return FALSE;
3603464ebd5Sriastradh
3613464ebd5Sriastradh   return TRUE;
362cdc920a0Smrg}
363cdc920a0Smrg
364cdc920a0Smrg
365cdc920a0Smrg/* Add a command to all active bins.
366cdc920a0Smrg */
36701e04c3fSmrgstatic inline boolean
368cdc920a0Smrglp_scene_bin_everywhere( struct lp_scene *scene,
3693464ebd5Sriastradh			 unsigned cmd,
370cdc920a0Smrg			 const union lp_rast_cmd_arg arg )
371cdc920a0Smrg{
372cdc920a0Smrg   unsigned i, j;
3733464ebd5Sriastradh   for (i = 0; i < scene->tiles_x; i++) {
3743464ebd5Sriastradh      for (j = 0; j < scene->tiles_y; j++) {
3753464ebd5Sriastradh         if (!lp_scene_bin_command( scene, i, j, cmd, arg ))
3763464ebd5Sriastradh            return FALSE;
3773464ebd5Sriastradh      }
3783464ebd5Sriastradh   }
379cdc920a0Smrg
3803464ebd5Sriastradh   return TRUE;
3813464ebd5Sriastradh}
382cdc920a0Smrg
383cdc920a0Smrg
38401e04c3fSmrgstatic inline unsigned
385cdc920a0Smrglp_scene_get_num_bins( const struct lp_scene *scene )
386cdc920a0Smrg{
387cdc920a0Smrg   return scene->tiles_x * scene->tiles_y;
388cdc920a0Smrg}
389cdc920a0Smrg
390cdc920a0Smrg
391cdc920a0Smrgvoid
392cdc920a0Smrglp_scene_bin_iter_begin( struct lp_scene *scene );
393cdc920a0Smrg
394cdc920a0Smrgstruct cmd_bin *
395af69d88dSmrglp_scene_bin_iter_next( struct lp_scene *scene, int *x, int *y );
396cdc920a0Smrg
397cdc920a0Smrg
3983464ebd5Sriastradh
3993464ebd5Sriastradh/* Begin/end binning of a scene
4003464ebd5Sriastradh */
401cdc920a0Smrgvoid
40201e04c3fSmrglp_scene_begin_binning(struct lp_scene *scene,
40301e04c3fSmrg                       struct pipe_framebuffer_state *fb);
404cdc920a0Smrg
4053464ebd5Sriastradhvoid
40601e04c3fSmrglp_scene_end_binning(struct lp_scene *scene);
4073464ebd5Sriastradh
4083464ebd5Sriastradh
4093464ebd5Sriastradh/* Begin/end rasterization of a scene
4103464ebd5Sriastradh */
4113464ebd5Sriastradhvoid
4123464ebd5Sriastradhlp_scene_begin_rasterization(struct lp_scene *scene);
4133464ebd5Sriastradh
4143464ebd5Sriastradhvoid
41501e04c3fSmrglp_scene_end_rasterization(struct lp_scene *scene);
4163464ebd5Sriastradh
4173464ebd5Sriastradh
4183464ebd5Sriastradh
4193464ebd5Sriastradh
4203464ebd5Sriastradh
421cdc920a0Smrg#endif /* LP_BIN_H */
422