int i;
int dirty_tex = 0;
- if (!(r300->dirty_state) && !(r300->dirty_hw)) {
+ if (!(r300->dirty_hw)) {
return;
}
r300_update_derived_state(r300);
/* XXX check size */
+ struct r300_texture* fb_tex =
+ (struct r300_texture*)r300->framebuffer_state.cbufs[0];
+ r300->winsys->add_buffer(r300->winsys, fb_tex->buffer,
+ 0, RADEON_GEM_DOMAIN_VRAM);
+ if (r300->winsys->validate(r300->winsys)) {
+ /* XXX */
+ r300->context.flush(&r300->context, 0, NULL);
+ }
if (r300->dirty_state & R300_NEW_BLEND) {
r300_emit_blend_state(r300, r300->blend_state);
unsigned pixpitch = tex->stride / tex->tex.block.size;
CS_LOCALS(r300);
+ /* Make sure our target BO is okay. */
+ r300->winsys->add_buffer(r300->winsys, tex->buffer,
+ 0, RADEON_GEM_DOMAIN_VRAM);
+ if (r300->winsys->validate(r300->winsys)) {
+ r300->context.flush(&r300->context, 0, NULL);
+ }
+
r300_emit_blend_state(r300, &blend_clear_state);
r300_emit_blend_color_state(r300, &blend_color_clear_state);
r300_emit_dsa_state(r300, &dsa_clear_state);
/* GB pipe count */
uint32_t gb_pipes;
+ /* GART size. */
+ uint32_t gart_size;
+
+ /* VRAM size. */
+ uint32_t vram_size;
+
+ /* Add a pipe_buffer to the list of buffer objects to validate. */
+ void (*add_buffer)(struct r300_winsys* winsys,
+ struct pipe_buffer* pbuffer,
+ uint32_t rd,
+ uint32_t wd);
+
+ /* Revalidate all currently setup pipe_buffers.
+ * Returns TRUE if a flush is required. */
+ boolean (*validate)(struct r300_winsys* winsys);
+
/* Check to see if there's room for commands. */
boolean (*check_cs)(struct r300_winsys* winsys, int size);
domain |= RADEON_GEM_DOMAIN_GTT;
}
- radeon_buffer->bo = radeon_bo_open(radeon_ws->bom, 0, size, alignment,
- domain, 0);
+ radeon_buffer->bo = radeon_bo_open(radeon_ws->priv->bom, 0, size,
+ alignment, domain, 0);
if (radeon_buffer->bo == NULL) {
FREE(radeon_buffer);
}
return NULL;
}
+ radeon_ws->priv = CALLOC_STRUCT(radeon_winsys_priv);
+ if (radeon_ws->priv == NULL) {
+ FREE(radeon_ws);
+ return NULL;
+ }
+
bom = radeon_bo_manager_gem_ctor(fd);
- radeon_ws->bom = bom;
+ radeon_ws->priv->bom = bom;
radeon_ws->base.flush_frontbuffer = radeon_flush_frontbuffer;
#include "util/u_memory.h"
#include "radeon_bo.h"
+#include "radeon_cs.h"
#include "radeon_drm.h"
struct radeon_bo *bo;
};
+#define RADEON_MAX_BOS 24
+
+struct radeon_winsys_priv {
+ /* Radeon BO manager. */
+ struct radeon_bo_manager* bom;
+
+ /* Radeon BO space checker. */
+ struct radeon_cs_space_check sc[RADEON_MAX_BOS];
+ /* Current BO count. */
+ unsigned bo_count;
+};
+
struct radeon_winsys {
/* Parent class. */
struct pipe_winsys base;
- /* Radeon BO manager.
- * This corresponds to void* radeon_winsys in r300_winsys. */
- struct radeon_bo_manager* bom;
+ /* This corresponds to void* radeon_winsys in r300_winsys. */
+ struct radeon_winsys_priv* priv;
};
struct radeon_winsys* radeon_pipe_winsys(int fb);
/* Create a pipe_screen. */
struct pipe_screen* radeon_create_screen(int drmFB,
- struct drm_create_screen_arg *arg )
+ struct drm_create_screen_arg *arg)
{
struct radeon_winsys* winsys = radeon_pipe_winsys(drmFB);
unsigned handle)
{
struct radeon_bo_manager* bom =
- ((struct radeon_winsys*)screen->winsys)->bom;
+ ((struct radeon_winsys*)screen->winsys)->priv->bom;
struct radeon_pipe_buffer* radeon_buffer;
struct radeon_bo* bo = NULL;
#include "radeon_r300.h"
+static void radeon_r300_add_buffer(struct r300_winsys* winsys,
+ struct pipe_buffer* pbuffer,
+ uint32_t rd,
+ uint32_t wd)
+{
+ int i;
+ struct radeon_winsys_priv* priv =
+ (struct radeon_winsys_priv*)winsys->radeon_winsys;
+ struct radeon_cs_space_check* sc = priv->sc;
+ struct radeon_bo* bo = ((struct radeon_pipe_buffer*)pbuffer)->bo;
+
+ /* Check to see if this BO is already in line for validation;
+ * find a slot for it otherwise. */
+ for (i = 0; i < RADEON_MAX_BOS; i++) {
+ if (sc[i].bo == bo) {
+ return;
+ } else if (sc[i].bo == NULL) {
+ sc[i].bo = bo;
+ sc[i].read_domains = rd;
+ sc[i].write_domain = wd;
+ priv->bo_count = i + 1;
+ return;
+ }
+ }
+
+ assert(FALSE && "Oh God too many BOs!");
+}
+
+static boolean radeon_r300_validate(struct r300_winsys* winsys)
+{
+ int retval;
+ struct radeon_winsys_priv* priv =
+ (struct radeon_winsys_priv*)winsys->radeon_winsys;
+ struct radeon_cs_space_check* sc = priv->sc;
+
+ retval = radeon_cs_space_check(winsys->cs, sc, priv->bo_count);
+
+ if (retval == RADEON_CS_SPACE_OP_TO_BIG) {
+ /* XXX we need to failover here */
+ } else if (retval == RADEON_CS_SPACE_FLUSH) {
+ /* We must flush before more rendering can commence. */
+ return TRUE;
+ }
+
+ /* Things are fine, we can proceed as normal. */
+ return FALSE;
+}
+
static boolean radeon_r300_check_cs(struct r300_winsys* winsys, int size)
{
/* XXX check size here, lazy ass! */
/* Helper function to do the ioctls needed for setup and init. */
static void do_ioctls(struct r300_winsys* winsys, int fd)
{
+ struct drm_radeon_gem_info info;
drm_radeon_getparam_t gp;
int target;
int retval;
exit(1);
}
winsys->pci_id = target;
+
+ /* Finally, retrieve MM info */
+ retval = drmCommandWriteRead(fd, DRM_RADEON_GEM_INFO,
+ &info, sizeof(info));
+ if (retval) {
+ fprintf(stderr, "%s: Failed to get MM info, error number %d\n",
+ __FUNCTION__, retval);
+ exit(1);
+ }
+ winsys->gart_size = info.gart_size;
+ /* XXX */
+ winsys->vram_size = info.vram_visible;
}
struct r300_winsys*
csm = radeon_cs_manager_gem_ctor(fd);
winsys->cs = radeon_cs_create(csm, 1024 * 64 / 4);
+ radeon_cs_set_limit(winsys->cs,
+ RADEON_GEM_DOMAIN_GTT, winsys->gart_size);
+ radeon_cs_set_limit(winsys->cs,
+ RADEON_GEM_DOMAIN_VRAM, winsys->vram_size);
+
+ winsys->add_buffer = radeon_r300_add_buffer;
+ winsys->validate = radeon_r300_validate;
winsys->check_cs = radeon_r300_check_cs;
winsys->begin_cs = radeon_r300_begin_cs;