#include "os/os_thread.h"
#include "lp_tile_soa.h"
#include "lp_rast.h"
+#include "lp_debug.h"
+struct lp_scene_queue;
/* We're limited to 2K by 2K for 32bit fixed point rasterization.
* Will need a 64-bit version for larger framebuffers.
*/
-#define MAXHEIGHT 2048
-#define MAXWIDTH 2048
-#define TILES_X (MAXWIDTH / TILE_SIZE)
-#define TILES_Y (MAXHEIGHT / TILE_SIZE)
+#define TILES_X (LP_MAX_WIDTH / TILE_SIZE)
+#define TILES_Y (LP_MAX_HEIGHT / TILE_SIZE)
#define CMD_BLOCK_MAX 128
-#define DATA_BLOCK_SIZE (16 * 1024 - sizeof(unsigned) - sizeof(void *))
-
+#define DATA_BLOCK_SIZE (64 * 1024)
+
+/* Scene temporary storage is clamped to this size:
+ */
+#define LP_SCENE_MAX_SIZE (4*1024*1024)
+
+/* The maximum amount of texture storage referenced by a scene is
+ * clamped ot this size:
+ */
+#define LP_SCENE_MAX_RESOURCE_SIZE (64*1024*1024)
/* switch to a non-pointer value for this:
*/
-typedef void (*lp_rast_cmd)( struct lp_rasterizer *,
- unsigned thread_index,
- const union lp_rast_cmd_arg );
+typedef void (*lp_rast_cmd_func)( struct lp_rasterizer_task *,
+ const union lp_rast_cmd_arg );
+
struct cmd_block {
- lp_rast_cmd cmd[CMD_BLOCK_MAX];
+ uint8_t cmd[CMD_BLOCK_MAX];
union lp_rast_cmd_arg arg[CMD_BLOCK_MAX];
unsigned count;
struct cmd_block *next;
};
+struct cmd_block_list {
+ struct cmd_block *head;
+ struct cmd_block *tail;
+};
+
struct data_block {
ubyte data[DATA_BLOCK_SIZE];
unsigned used;
struct data_block *next;
};
-struct cmd_block_list {
- struct cmd_block *head;
- struct cmd_block *tail;
-};
+
/**
* For each screen tile we have one of these bins.
*/
struct cmd_bin {
- struct cmd_block_list commands;
+ ushort x;
+ ushort y;
+ struct cmd_block *head;
+ struct cmd_block *tail;
};
/**
- * This stores bulk data which is shared by all bins within a scene.
+ * This stores bulk data which is used for all memory allocations
+ * within a scene.
+ *
* Examples include triangle data and state data. The commands in
* the per-tile bins will point to chunks of data in this structure.
+ *
+ * Include the first block of data statically to ensure we can always
+ * initiate a scene without relying on malloc succeeding.
*/
struct data_block_list {
+ struct data_block first;
struct data_block *head;
- struct data_block *tail;
-};
-
-
-/** List of texture references */
-struct texture_ref {
- struct pipe_texture *texture;
- struct texture_ref *prev, *next; /**< linked list w/ u_simple_list.h */
};
+struct resource_ref;
/**
* All bins and bin data are contained here.
* scenes:
*/
struct lp_scene {
- struct cmd_bin tile[TILES_X][TILES_Y];
- struct data_block_list data;
+ struct pipe_context *pipe;
+ struct lp_fence *fence;
+ /* Framebuffer mappings - valid only between begin_rasterization()
+ * and end_rasterization().
+ */
+ struct {
+ uint8_t *map;
+ unsigned stride;
+ unsigned blocksize;
+ } zsbuf, cbufs[PIPE_MAX_COLOR_BUFS];
+
/** the framebuffer to render the scene into */
struct pipe_framebuffer_state fb;
- /** list of textures referenced by the scene commands */
- struct texture_ref textures;
+ /** list of resources referenced by the scene commands */
+ struct resource_ref *resources;
+
+ /** Total memory used by the scene (in bytes). This sums all the
+ * data blocks and counts all bins, state, resource references and
+ * other random allocations within the scene.
+ */
+ unsigned scene_size;
+
+ /** Sum of sizes of all resources referenced by the scene. Sums
+ * all the textures read by the scene:
+ */
+ unsigned resource_reference_size;
- boolean write_depth;
+ boolean alloc_failed;
+ boolean has_depthstencil_clear;
/**
* Number of active tiles in each dimension.
int curr_x, curr_y; /**< for iterating over bins */
pipe_mutex mutex;
+
+ struct cmd_bin tile[TILES_X][TILES_Y];
+ struct data_block_list data;
};
-struct lp_scene *lp_scene_create(void);
+struct lp_scene *lp_scene_create(struct pipe_context *pipe);
void lp_scene_destroy(struct lp_scene *scene);
-
-void lp_scene_init(struct lp_scene *scene);
-
boolean lp_scene_is_empty(struct lp_scene *scene );
+boolean lp_scene_is_oom(struct lp_scene *scene );
-void lp_scene_reset(struct lp_scene *scene );
-
-void lp_scene_free_bin_data(struct lp_scene *scene);
-
-void lp_scene_set_framebuffer_size( struct lp_scene *scene,
- unsigned width, unsigned height );
-
-void lp_bin_new_data_block( struct data_block_list *list );
-void lp_bin_new_cmd_block( struct cmd_block_list *list );
+struct data_block *lp_scene_new_data_block( struct lp_scene *scene );
-unsigned lp_scene_data_size( const struct lp_scene *scene );
+struct cmd_block *lp_scene_new_cmd_block( struct lp_scene *scene,
+ struct cmd_bin *bin );
-unsigned lp_scene_bin_size( const struct lp_scene *scene, unsigned x, unsigned y );
+boolean lp_scene_add_resource_reference(struct lp_scene *scene,
+ struct pipe_resource *resource,
+ boolean initializing_scene);
-void lp_scene_texture_reference( struct lp_scene *scene,
- struct pipe_texture *texture );
-
-boolean lp_scene_is_texture_referenced( const struct lp_scene *scene,
- const struct pipe_texture *texture );
+boolean lp_scene_is_resource_referenced(const struct lp_scene *scene,
+ const struct pipe_resource *resource );
/**
lp_scene_alloc( struct lp_scene *scene, unsigned size)
{
struct data_block_list *list = &scene->data;
-
- if (list->tail->used + size > DATA_BLOCK_SIZE) {
- lp_bin_new_data_block( list );
+ struct data_block *block = list->head;
+
+ assert(size <= DATA_BLOCK_SIZE);
+ assert(block != NULL);
+
+ if (LP_DEBUG & DEBUG_MEM)
+ debug_printf("alloc %u block %u/%u tot %u/%u\n",
+ size, block->used, DATA_BLOCK_SIZE,
+ scene->scene_size, LP_SCENE_MAX_SIZE);
+
+ if (block->used + size > DATA_BLOCK_SIZE) {
+ block = lp_scene_new_data_block( scene );
+ if (!block) {
+ /* out of memory */
+ return NULL;
+ }
}
{
- struct data_block *tail = list->tail;
- ubyte *data = tail->data + tail->used;
- tail->used += size;
+ ubyte *data = block->data + block->used;
+ block->used += size;
return data;
}
}
unsigned alignment )
{
struct data_block_list *list = &scene->data;
-
- if (list->tail->used + size + alignment - 1 > DATA_BLOCK_SIZE) {
- lp_bin_new_data_block( list );
+ struct data_block *block = list->head;
+
+ assert(block != NULL);
+
+ if (LP_DEBUG & DEBUG_MEM)
+ debug_printf("alloc %u block %u/%u tot %u/%u\n",
+ size + alignment - 1,
+ block->used, DATA_BLOCK_SIZE,
+ scene->scene_size, LP_SCENE_MAX_SIZE);
+
+ if (block->used + size + alignment - 1 > DATA_BLOCK_SIZE) {
+ block = lp_scene_new_data_block( scene );
+ if (!block)
+ return NULL;
}
{
- struct data_block *tail = list->tail;
- ubyte *data = tail->data + tail->used;
+ ubyte *data = block->data + block->used;
unsigned offset = (((uintptr_t)data + alignment - 1) & ~(alignment - 1)) - (uintptr_t)data;
- tail->used += offset + size;
+ block->used += offset + size;
return data + offset;
}
}
lp_scene_putback_data( struct lp_scene *scene, unsigned size)
{
struct data_block_list *list = &scene->data;
- assert(list->tail->used >= size);
- list->tail->used -= size;
+ assert(list->head && list->head->used >= size);
+ list->head->used -= size;
}
/* Add a command to bin[x][y].
*/
-static INLINE void
+static INLINE boolean
lp_scene_bin_command( struct lp_scene *scene,
- unsigned x, unsigned y,
- lp_rast_cmd cmd,
- union lp_rast_cmd_arg arg )
+ unsigned x, unsigned y,
+ unsigned cmd,
+ union lp_rast_cmd_arg arg )
{
struct cmd_bin *bin = lp_scene_get_bin(scene, x, y);
- struct cmd_block_list *list = &bin->commands;
+ struct cmd_block *tail = bin->tail;
assert(x < scene->tiles_x);
assert(y < scene->tiles_y);
-
- if (list->tail->count == CMD_BLOCK_MAX) {
- lp_bin_new_cmd_block( list );
+ assert(cmd <= LP_RAST_OP_END_QUERY);
+
+ if (tail == NULL || tail->count == CMD_BLOCK_MAX) {
+ tail = lp_scene_new_cmd_block( scene, bin );
+ if (!tail) {
+ return FALSE;
+ }
+ assert(tail->count == 0);
}
{
- struct cmd_block *tail = list->tail;
unsigned i = tail->count;
- tail->cmd[i] = cmd;
+ tail->cmd[i] = cmd & LP_RAST_OP_MASK;
tail->arg[i] = arg;
tail->count++;
}
+
+ return TRUE;
}
/* Add a command to all active bins.
*/
-static INLINE void
+static INLINE boolean
lp_scene_bin_everywhere( struct lp_scene *scene,
- lp_rast_cmd cmd,
+ unsigned cmd,
const union lp_rast_cmd_arg arg )
{
unsigned i, j;
- for (i = 0; i < scene->tiles_x; i++)
- for (j = 0; j < scene->tiles_y; j++)
- lp_scene_bin_command( scene, i, j, cmd, arg );
-}
-
+ for (i = 0; i < scene->tiles_x; i++) {
+ for (j = 0; j < scene->tiles_y; j++) {
+ if (!lp_scene_bin_command( scene, i, j, cmd, arg ))
+ return FALSE;
+ }
+ }
-void
-lp_scene_bin_state_command( struct lp_scene *scene,
- lp_rast_cmd cmd,
- const union lp_rast_cmd_arg arg );
+ return TRUE;
+}
static INLINE unsigned
lp_scene_bin_iter_begin( struct lp_scene *scene );
struct cmd_bin *
-lp_scene_bin_iter_next( struct lp_scene *scene, int *bin_x, int *bin_y );
+lp_scene_bin_iter_next( struct lp_scene *scene );
+
+
+
+/* Begin/end binning of a scene
+ */
+void
+lp_scene_begin_binning( struct lp_scene *scene,
+ struct pipe_framebuffer_state *fb );
+
+void
+lp_scene_end_binning( struct lp_scene *scene );
+
+
+/* Begin/end rasterization of a scene
+ */
+void
+lp_scene_begin_rasterization(struct lp_scene *scene);
+
+void
+lp_scene_end_rasterization(struct lp_scene *scene );
+
+
+
#endif /* LP_BIN_H */