summaryrefslogtreecommitdiff
path: root/src/mesa/drivers/dri/intel
diff options
context:
space:
mode:
Diffstat (limited to 'src/mesa/drivers/dri/intel')
-rw-r--r--src/mesa/drivers/dri/intel/intel_batchbuffer.c274
-rw-r--r--src/mesa/drivers/dri/intel/intel_batchbuffer.h127
-rw-r--r--src/mesa/drivers/dri/intel/intel_blit.c140
-rw-r--r--src/mesa/drivers/dri/intel/intel_blit.h4
-rw-r--r--src/mesa/drivers/dri/intel/intel_buffer_objects.c320
-rw-r--r--src/mesa/drivers/dri/intel/intel_buffer_objects.h23
-rw-r--r--src/mesa/drivers/dri/intel/intel_chipset.h4
-rw-r--r--src/mesa/drivers/dri/intel/intel_clear.c50
-rw-r--r--src/mesa/drivers/dri/intel/intel_context.c101
-rw-r--r--src/mesa/drivers/dri/intel/intel_context.h31
-rw-r--r--src/mesa/drivers/dri/intel/intel_decode.c2
-rw-r--r--src/mesa/drivers/dri/intel/intel_extensions.c8
-rw-r--r--src/mesa/drivers/dri/intel/intel_extensions_es2.c17
-rw-r--r--src/mesa/drivers/dri/intel/intel_fbo.c408
-rw-r--r--src/mesa/drivers/dri/intel/intel_mipmap_tree.c4
-rw-r--r--src/mesa/drivers/dri/intel/intel_mipmap_tree.h2
-rw-r--r--src/mesa/drivers/dri/intel/intel_pixel.c12
-rw-r--r--src/mesa/drivers/dri/intel/intel_pixel_bitmap.c5
-rw-r--r--src/mesa/drivers/dri/intel/intel_pixel_read.c15
-rw-r--r--src/mesa/drivers/dri/intel/intel_reg.h2
-rw-r--r--src/mesa/drivers/dri/intel/intel_regions.c20
-rw-r--r--src/mesa/drivers/dri/intel/intel_screen.c94
-rw-r--r--src/mesa/drivers/dri/intel/intel_screen.h1
-rw-r--r--src/mesa/drivers/dri/intel/intel_span.c82
-rw-r--r--src/mesa/drivers/dri/intel/intel_span.h4
-rw-r--r--src/mesa/drivers/dri/intel/intel_syncobj.c4
-rw-r--r--src/mesa/drivers/dri/intel/intel_tex.c1
-rw-r--r--src/mesa/drivers/dri/intel/intel_tex.h11
-rw-r--r--src/mesa/drivers/dri/intel/intel_tex_copy.c123
-rw-r--r--src/mesa/drivers/dri/intel/intel_tex_format.c239
-rw-r--r--src/mesa/drivers/dri/intel/intel_tex_image.c165
-rw-r--r--src/mesa/drivers/dri/intel/intel_tex_obj.h8
-rw-r--r--src/mesa/drivers/dri/intel/intel_tex_subimage.c23
-rw-r--r--src/mesa/drivers/dri/intel/intel_tex_validate.c123
34 files changed, 1328 insertions, 1119 deletions
diff --git a/src/mesa/drivers/dri/intel/intel_batchbuffer.c b/src/mesa/drivers/dri/intel/intel_batchbuffer.c
index 21fc9ece88..42b4f923e0 100644
--- a/src/mesa/drivers/dri/intel/intel_batchbuffer.c
+++ b/src/mesa/drivers/dri/intel/intel_batchbuffer.c
@@ -27,81 +27,89 @@
#include "intel_context.h"
#include "intel_batchbuffer.h"
+#include "intel_buffer_objects.h"
#include "intel_decode.h"
#include "intel_reg.h"
#include "intel_bufmgr.h"
#include "intel_buffers.h"
-void
-intel_batchbuffer_reset(struct intel_batchbuffer *batch)
+struct cached_batch_item {
+ struct cached_batch_item *next;
+ uint16_t header;
+ uint16_t size;
+};
+
+static void clear_cache( struct intel_context *intel )
{
- struct intel_context *intel = batch->intel;
+ struct cached_batch_item *item = intel->batch.cached_items;
- if (batch->buf != NULL) {
- drm_intel_bo_unreference(batch->buf);
- batch->buf = NULL;
+ while (item) {
+ struct cached_batch_item *next = item->next;
+ free(item);
+ item = next;
}
- batch->buf = drm_intel_bo_alloc(intel->bufmgr, "batchbuffer",
- intel->maxBatchSize, 4096);
- drm_intel_gem_bo_map_gtt(batch->buf);
- batch->map = batch->buf->virtual;
-
- batch->size = intel->maxBatchSize;
- batch->ptr = batch->map;
- batch->reserved_space = BATCH_RESERVED;
- batch->dirty_state = ~0;
- batch->state_batch_offset = batch->size;
+ intel->batch.cached_items = NULL;
}
-struct intel_batchbuffer *
-intel_batchbuffer_alloc(struct intel_context *intel)
+void
+intel_batchbuffer_reset(struct intel_context *intel)
{
- struct intel_batchbuffer *batch = calloc(sizeof(*batch), 1);
+ if (intel->batch.bo != NULL) {
+ drm_intel_bo_unreference(intel->batch.bo);
+ intel->batch.bo = NULL;
+ }
+ clear_cache(intel);
- batch->intel = intel;
- intel_batchbuffer_reset(batch);
+ intel->batch.bo = drm_intel_bo_alloc(intel->bufmgr, "batchbuffer",
+ intel->maxBatchSize, 4096);
- return batch;
+ intel->batch.reserved_space = BATCH_RESERVED;
+ intel->batch.state_batch_offset = intel->batch.bo->size;
+ intel->batch.used = 0;
}
void
-intel_batchbuffer_free(struct intel_batchbuffer *batch)
+intel_batchbuffer_free(struct intel_context *intel)
{
- if (batch->map) {
- drm_intel_gem_bo_unmap_gtt(batch->buf);
- batch->map = NULL;
- }
- dri_bo_unreference(batch->buf);
- batch->buf = NULL;
- free(batch);
+ drm_intel_bo_unreference(intel->batch.bo);
+ clear_cache(intel);
}
-
/* TODO: Push this whole function into bufmgr.
*/
static void
-do_flush_locked(struct intel_batchbuffer *batch, GLuint used)
+do_flush_locked(struct intel_context *intel)
{
- struct intel_context *intel = batch->intel;
+ struct intel_batchbuffer *batch = &intel->batch;
int ret = 0;
- int x_off = 0, y_off = 0;
-
- drm_intel_gem_bo_unmap_gtt(batch->buf);
-
- batch->ptr = NULL;
if (!intel->intelScreen->no_hw) {
- drm_intel_bo_exec(batch->buf, used, NULL, 0,
- (x_off & 0xffff) | (y_off << 16));
+ int ring;
+
+ if (intel->gen < 6 || !batch->is_blit) {
+ ring = I915_EXEC_RENDER;
+ } else {
+ ring = I915_EXEC_BLT;
+ }
+
+ ret = drm_intel_bo_subdata(batch->bo, 0, 4*batch->used, batch->map);
+ if (ret == 0 && batch->state_batch_offset != batch->bo->size) {
+ ret = drm_intel_bo_subdata(batch->bo,
+ batch->state_batch_offset,
+ batch->bo->size - batch->state_batch_offset,
+ (char *)batch->map + batch->state_batch_offset);
+ }
+
+ if (ret == 0)
+ ret = drm_intel_bo_mrb_exec(batch->bo, 4*batch->used, NULL, 0, 0, ring);
}
if (unlikely(INTEL_DEBUG & DEBUG_BATCH)) {
- drm_intel_bo_map(batch->buf, GL_FALSE);
- intel_decode(batch->buf->virtual, used / 4, batch->buf->offset,
+ intel_decode(batch->map, batch->used,
+ batch->bo->offset,
intel->intelScreen->deviceID, GL_TRUE);
- drm_intel_bo_unmap(batch->buf);
if (intel->vtbl.debug_batch != NULL)
intel->vtbl.debug_batch(intel);
@@ -114,80 +122,54 @@ do_flush_locked(struct intel_batchbuffer *batch, GLuint used)
}
void
-_intel_batchbuffer_flush(struct intel_batchbuffer *batch, const char *file,
- int line)
+_intel_batchbuffer_flush(struct intel_context *intel,
+ const char *file, int line)
{
- struct intel_context *intel = batch->intel;
- GLuint used = batch->ptr - batch->map;
-
- if (intel->first_post_swapbuffers_batch == NULL) {
- intel->first_post_swapbuffers_batch = intel->batch->buf;
- drm_intel_bo_reference(intel->first_post_swapbuffers_batch);
- }
-
- if (used == 0)
+ if (intel->batch.used == 0)
return;
if (unlikely(INTEL_DEBUG & DEBUG_BATCH))
fprintf(stderr, "%s:%d: Batchbuffer flush with %db used\n", file, line,
- used);
+ 4*intel->batch.used);
- batch->reserved_space = 0;
+ intel->batch.reserved_space = 0;
if (intel->always_flush_cache) {
- intel_batchbuffer_emit_mi_flush(batch);
- used = batch->ptr - batch->map;
- }
-
- /* Round batchbuffer usage to 2 DWORDs. */
-
- if ((used & 4) == 0) {
- *(GLuint *) (batch->ptr) = 0; /* noop */
- batch->ptr += 4;
- used = batch->ptr - batch->map;
+ intel_batchbuffer_emit_mi_flush(intel);
}
/* Mark the end of the buffer. */
- *(GLuint *) (batch->ptr) = MI_BATCH_BUFFER_END;
- batch->ptr += 4;
- used = batch->ptr - batch->map;
- assert (used <= batch->buf->size);
-
- /* Workaround for recursive batchbuffer flushing: If the window is
- * moved, we can get into a case where we try to flush during a
- * flush. What happens is that when we try to grab the lock for
- * the first flush, we detect that the window moved which then
- * causes another flush (from the intel_draw_buffer() call in
- * intelUpdatePageFlipping()). To work around this we reset the
- * batchbuffer tail pointer before trying to get the lock. This
- * prevent the nested buffer flush, but a better fix would be to
- * avoid that in the first place. */
- batch->ptr = batch->map;
+ intel_batchbuffer_emit_dword(intel, MI_BATCH_BUFFER_END);
+ if (intel->batch.used & 1) {
+ /* Round batchbuffer usage to 2 DWORDs. */
+ intel_batchbuffer_emit_dword(intel, MI_NOOP);
+ }
if (intel->vtbl.finish_batch)
intel->vtbl.finish_batch(intel);
+ intel_upload_finish(intel);
+
/* Check that we didn't just wrap our batchbuffer at a bad time. */
assert(!intel->no_batch_wrap);
- do_flush_locked(batch, used);
+ do_flush_locked(intel);
if (unlikely(INTEL_DEBUG & DEBUG_SYNC)) {
fprintf(stderr, "waiting for idle\n");
- drm_intel_bo_map(batch->buf, GL_TRUE);
- drm_intel_bo_unmap(batch->buf);
+ drm_intel_bo_wait_rendering(intel->batch.bo);
}
/* Reset the buffer:
*/
- intel_batchbuffer_reset(batch);
+ intel_batchbuffer_reset(intel);
}
/* This is the only way buffers get added to the validate list.
*/
GLboolean
-intel_batchbuffer_emit_reloc(struct intel_batchbuffer *batch,
+intel_batchbuffer_emit_reloc(struct intel_context *intel,
drm_intel_bo *buffer,
uint32_t read_domains, uint32_t write_domain,
uint32_t delta)
@@ -196,58 +178,98 @@ intel_batchbuffer_emit_reloc(struct intel_batchbuffer *batch,
assert(delta < buffer->size);
- if (batch->ptr - batch->map > batch->buf->size)
- printf ("bad relocation ptr %p map %p offset %d size %lu\n",
- batch->ptr, batch->map, batch->ptr - batch->map, batch->buf->size);
- ret = drm_intel_bo_emit_reloc(batch->buf, batch->ptr - batch->map,
+ ret = drm_intel_bo_emit_reloc(intel->batch.bo, 4*intel->batch.used,
buffer, delta,
read_domains, write_domain);
+ assert(ret == 0);
+ (void)ret;
/*
* Using the old buffer offset, write in what the right data would be, in case
* the buffer doesn't move and we can short-circuit the relocation processing
* in the kernel
*/
- intel_batchbuffer_emit_dword (batch, buffer->offset + delta);
+ intel_batchbuffer_emit_dword(intel, buffer->offset + delta);
return GL_TRUE;
}
GLboolean
-intel_batchbuffer_emit_reloc_fenced(struct intel_batchbuffer *batch,
+intel_batchbuffer_emit_reloc_fenced(struct intel_context *intel,
drm_intel_bo *buffer,
- uint32_t read_domains, uint32_t write_domain,
+ uint32_t read_domains,
+ uint32_t write_domain,
uint32_t delta)
{
int ret;
assert(delta < buffer->size);
- if (batch->ptr - batch->map > batch->buf->size)
- printf ("bad relocation ptr %p map %p offset %d size %lu\n",
- batch->ptr, batch->map, batch->ptr - batch->map, batch->buf->size);
- ret = drm_intel_bo_emit_reloc_fence(batch->buf, batch->ptr - batch->map,
+ ret = drm_intel_bo_emit_reloc_fence(intel->batch.bo, 4*intel->batch.used,
buffer, delta,
read_domains, write_domain);
+ assert(ret == 0);
+ (void)ret;
/*
* Using the old buffer offset, write in what the right data would
* be, in case the buffer doesn't move and we can short-circuit the
* relocation processing in the kernel
*/
- intel_batchbuffer_emit_dword (batch, buffer->offset + delta);
+ intel_batchbuffer_emit_dword(intel, buffer->offset + delta);
return GL_TRUE;
}
void
-intel_batchbuffer_data(struct intel_batchbuffer *batch,
- const void *data, GLuint bytes)
+intel_batchbuffer_data(struct intel_context *intel,
+ const void *data, GLuint bytes, bool is_blit)
{
assert((bytes & 3) == 0);
- intel_batchbuffer_require_space(batch, bytes);
- __memcpy(batch->ptr, data, bytes);
- batch->ptr += bytes;
+ intel_batchbuffer_require_space(intel, bytes, is_blit);
+ __memcpy(intel->batch.map + intel->batch.used, data, bytes);
+ intel->batch.used += bytes >> 2;
+}
+
+void
+intel_batchbuffer_cached_advance(struct intel_context *intel)
+{
+ struct cached_batch_item **prev = &intel->batch.cached_items, *item;
+ uint32_t sz = (intel->batch.used - intel->batch.emit) * sizeof(uint32_t);
+ uint32_t *start = intel->batch.map + intel->batch.emit;
+ uint16_t op = *start >> 16;
+
+ while (*prev) {
+ uint32_t *old;
+
+ item = *prev;
+ old = intel->batch.map + item->header;
+ if (op == *old >> 16) {
+ if (item->size == sz && memcmp(old, start, sz) == 0) {
+ if (prev != &intel->batch.cached_items) {
+ *prev = item->next;
+ item->next = intel->batch.cached_items;
+ intel->batch.cached_items = item;
+ }
+ intel->batch.used = intel->batch.emit;
+ return;
+ }
+
+ goto emit;
+ }
+ prev = &item->next;
+ }
+
+ item = malloc(sizeof(struct cached_batch_item));
+ if (item == NULL)
+ return;
+
+ item->next = intel->batch.cached_items;
+ intel->batch.cached_items = item;
+
+emit:
+ item->size = sz;
+ item->header = intel->batch.emit;
}
/* Emit a pipelined flush to either flush render and texture cache for
@@ -257,27 +279,35 @@ intel_batchbuffer_data(struct intel_batchbuffer *batch,
* This is also used for the always_flush_cache driconf debug option.
*/
void
-intel_batchbuffer_emit_mi_flush(struct intel_batchbuffer *batch)
+intel_batchbuffer_emit_mi_flush(struct intel_context *intel)
{
- struct intel_context *intel = batch->intel;
-
if (intel->gen >= 6) {
- BEGIN_BATCH(8);
-
- /* XXX workaround: issue any post sync != 0 before write cache flush = 1 */
- OUT_BATCH(_3DSTATE_PIPE_CONTROL);
- OUT_BATCH(PIPE_CONTROL_WRITE_IMMEDIATE);
- OUT_BATCH(0); /* write address */
- OUT_BATCH(0); /* write data */
-
- OUT_BATCH(_3DSTATE_PIPE_CONTROL);
- OUT_BATCH(PIPE_CONTROL_INSTRUCTION_FLUSH |
- PIPE_CONTROL_WRITE_FLUSH |
- PIPE_CONTROL_DEPTH_CACHE_FLUSH |
- PIPE_CONTROL_NO_WRITE);
- OUT_BATCH(0); /* write address */
- OUT_BATCH(0); /* write data */
- ADVANCE_BATCH();
+ if (intel->batch.is_blit) {
+ BEGIN_BATCH_BLT(4);
+ OUT_BATCH(MI_FLUSH_DW);
+ OUT_BATCH(0);
+ OUT_BATCH(0);
+ OUT_BATCH(0);
+ ADVANCE_BATCH();
+ } else {
+ BEGIN_BATCH(8);
+ /* XXX workaround: issue any post sync != 0 before write
+ * cache flush = 1
+ */
+ OUT_BATCH(_3DSTATE_PIPE_CONTROL);
+ OUT_BATCH(PIPE_CONTROL_WRITE_IMMEDIATE);
+ OUT_BATCH(0); /* write address */
+ OUT_BATCH(0); /* write data */
+
+ OUT_BATCH(_3DSTATE_PIPE_CONTROL);
+ OUT_BATCH(PIPE_CONTROL_INSTRUCTION_FLUSH |
+ PIPE_CONTROL_WRITE_FLUSH |
+ PIPE_CONTROL_DEPTH_CACHE_FLUSH |
+ PIPE_CONTROL_NO_WRITE);
+ OUT_BATCH(0); /* write address */
+ OUT_BATCH(0); /* write data */
+ ADVANCE_BATCH();
+ }
} else if (intel->gen >= 4) {
BEGIN_BATCH(4);
OUT_BATCH(_3DSTATE_PIPE_CONTROL |
diff --git a/src/mesa/drivers/dri/intel/intel_batchbuffer.h b/src/mesa/drivers/dri/intel/intel_batchbuffer.h
index 428c027c2f..a0a5c9841c 100644
--- a/src/mesa/drivers/dri/intel/intel_batchbuffer.h
+++ b/src/mesa/drivers/dri/intel/intel_batchbuffer.h
@@ -7,70 +7,37 @@
#include "intel_bufmgr.h"
#include "intel_reg.h"
-#define BATCH_SZ 16384
#define BATCH_RESERVED 16
+void intel_batchbuffer_reset(struct intel_context *intel);
+void intel_batchbuffer_free(struct intel_context *intel);
-struct intel_batchbuffer
-{
- struct intel_context *intel;
-
- drm_intel_bo *buf;
-
- GLubyte *map;
- GLubyte *ptr;
-
- GLuint size;
- uint32_t state_batch_offset;
-
-#ifdef DEBUG
- /** Tracking of BEGIN_BATCH()/OUT_BATCH()/ADVANCE_BATCH() debugging */
- struct {
- GLuint total;
- GLubyte *start_ptr;
- } emit;
-#endif
-
- GLuint dirty_state;
- GLuint reserved_space;
-};
-
-struct intel_batchbuffer *intel_batchbuffer_alloc(struct intel_context
- *intel);
-
-void intel_batchbuffer_free(struct intel_batchbuffer *batch);
-
-
-void _intel_batchbuffer_flush(struct intel_batchbuffer *batch,
+void _intel_batchbuffer_flush(struct intel_context *intel,
const char *file, int line);
-#define intel_batchbuffer_flush(batch) \
- _intel_batchbuffer_flush(batch, __FILE__, __LINE__)
+#define intel_batchbuffer_flush(intel) \
+ _intel_batchbuffer_flush(intel, __FILE__, __LINE__)
-void intel_batchbuffer_reset(struct intel_batchbuffer *batch);
/* Unlike bmBufferData, this currently requires the buffer be mapped.
* Consider it a convenience function wrapping multple
* intel_buffer_dword() calls.
*/
-void intel_batchbuffer_data(struct intel_batchbuffer *batch,
- const void *data, GLuint bytes);
-
-void intel_batchbuffer_release_space(struct intel_batchbuffer *batch,
- GLuint bytes);
+void intel_batchbuffer_data(struct intel_context *intel,
+ const void *data, GLuint bytes, bool is_blit);
-GLboolean intel_batchbuffer_emit_reloc(struct intel_batchbuffer *batch,
+GLboolean intel_batchbuffer_emit_reloc(struct intel_context *intel,
drm_intel_bo *buffer,
uint32_t read_domains,
uint32_t write_domain,
uint32_t offset);
-GLboolean intel_batchbuffer_emit_reloc_fenced(struct intel_batchbuffer *batch,
+GLboolean intel_batchbuffer_emit_reloc_fenced(struct intel_context *intel,
drm_intel_bo *buffer,
uint32_t read_domains,
uint32_t write_domain,
uint32_t offset);
-void intel_batchbuffer_emit_mi_flush(struct intel_batchbuffer *batch);
+void intel_batchbuffer_emit_mi_flush(struct intel_context *intel);
static INLINE uint32_t float_as_int(float f)
{
@@ -89,83 +56,93 @@ static INLINE uint32_t float_as_int(float f)
* work...
*/
static INLINE GLint
-intel_batchbuffer_space(struct intel_batchbuffer *batch)
+intel_batchbuffer_space(struct intel_context *intel)
{
- return (batch->state_batch_offset - batch->reserved_space) -
- (batch->ptr - batch->map);
+ return (intel->batch.state_batch_offset - intel->batch.reserved_space) - intel->batch.used*4;
}
static INLINE void
-intel_batchbuffer_emit_dword(struct intel_batchbuffer *batch, GLuint dword)
+intel_batchbuffer_emit_dword(struct intel_context *intel, GLuint dword)
{
#ifdef DEBUG
- assert(intel_batchbuffer_space(batch) >= 4);
+ assert(intel_batchbuffer_space(intel) >= 4);
#endif
- *(GLuint *) (batch->ptr) = dword;
- batch->ptr += 4;
+ intel->batch.map[intel->batch.used++] = dword;
}
static INLINE void
-intel_batchbuffer_emit_float(struct intel_batchbuffer *batch, float f)
+intel_batchbuffer_emit_float(struct intel_context *intel, float f)
{
- intel_batchbuffer_emit_dword(batch, float_as_int(f));
+ intel_batchbuffer_emit_dword(intel, float_as_int(f));
}
static INLINE void
-intel_batchbuffer_require_space(struct intel_batchbuffer *batch,
- GLuint sz)
+intel_batchbuffer_require_space(struct intel_context *intel,
+ GLuint sz, int is_blit)
{
+
+ if (intel->gen >= 6 &&
+ intel->batch.is_blit != is_blit && intel->batch.used) {
+ intel_batchbuffer_flush(intel);
+ }
+
+ intel->batch.is_blit = is_blit;
+
#ifdef DEBUG
- assert(sz < batch->size - 8);
+ assert(sz < sizeof(intel->batch.map) - BATCH_RESERVED);
#endif
- if (intel_batchbuffer_space(batch) < sz)
- intel_batchbuffer_flush(batch);
+ if (intel_batchbuffer_space(intel) < sz)
+ intel_batchbuffer_flush(intel);
}
static INLINE void
-intel_batchbuffer_begin(struct intel_batchbuffer *batch, int n)
+intel_batchbuffer_begin(struct intel_context *intel, int n, bool is_blit)
{
- intel_batchbuffer_require_space(batch, n * 4);
+ intel_batchbuffer_require_space(intel, n * 4, is_blit);
+
+ intel->batch.emit = intel->batch.used;
#ifdef DEBUG
- assert(batch->map);
- assert(batch->emit.start_ptr == NULL);
- batch->emit.total = n * 4;
- batch->emit.start_ptr = batch->ptr;
+ intel->batch.total = n;
#endif
}
static INLINE void
-intel_batchbuffer_advance(struct intel_batchbuffer *batch)
+intel_batchbuffer_advance(struct intel_context *intel)
{
#ifdef DEBUG
- unsigned int _n = batch->ptr - batch->emit.start_ptr;
- assert(batch->emit.start_ptr != NULL);
- if (_n != batch->emit.total) {
+ struct intel_batchbuffer *batch = &intel->batch;
+ unsigned int _n = batch->used - batch->emit;
+ assert(batch->total != 0);
+ if (_n != batch->total) {
fprintf(stderr, "ADVANCE_BATCH: %d of %d dwords emitted\n",
- _n, batch->emit.total);
+ _n, batch->total);
abort();
}
- batch->emit.start_ptr = NULL;
+ batch->total = 0;
#endif
}
+void intel_batchbuffer_cached_advance(struct intel_context *intel);
+
/* Here are the crusty old macros, to be removed:
*/
#define BATCH_LOCALS
-#define BEGIN_BATCH(n) intel_batchbuffer_begin(intel->batch, n)
-#define OUT_BATCH(d) intel_batchbuffer_emit_dword(intel->batch, d)
-#define OUT_BATCH_F(f) intel_batchbuffer_emit_float(intel->batch,f)
+#define BEGIN_BATCH(n) intel_batchbuffer_begin(intel, n, false)
+#define BEGIN_BATCH_BLT(n) intel_batchbuffer_begin(intel, n, true)
+#define OUT_BATCH(d) intel_batchbuffer_emit_dword(intel, d)
+#define OUT_BATCH_F(f) intel_batchbuffer_emit_float(intel,f)
#define OUT_RELOC(buf, read_domains, write_domain, delta) do { \
- intel_batchbuffer_emit_reloc(intel->batch, buf, \
+ intel_batchbuffer_emit_reloc(intel, buf, \
read_domains, write_domain, delta); \
} while (0)
#define OUT_RELOC_FENCED(buf, read_domains, write_domain, delta) do { \
- intel_batchbuffer_emit_reloc_fenced(intel->batch, buf, \
+ intel_batchbuffer_emit_reloc_fenced(intel, buf, \
read_domains, write_domain, delta); \
} while (0)
-#define ADVANCE_BATCH() intel_batchbuffer_advance(intel->batch);
+#define ADVANCE_BATCH() intel_batchbuffer_advance(intel);
+#define CACHED_BATCH() intel_batchbuffer_cached_advance(intel);
#endif
diff --git a/src/mesa/drivers/dri/intel/intel_blit.c b/src/mesa/drivers/dri/intel/intel_blit.c
index c2917e9b07..e1ab7f1637 100644
--- a/src/mesa/drivers/dri/intel/intel_blit.c
+++ b/src/mesa/drivers/dri/intel/intel_blit.c
@@ -38,6 +38,7 @@
#include "intel_reg.h"
#include "intel_regions.h"
#include "intel_batchbuffer.h"
+#include "intel_mipmap_tree.h"
#define FILE_DEBUG_FLAG DEBUG_BLIT
@@ -107,10 +108,6 @@ intelEmitCopyBlit(struct intel_context *intel,
drm_intel_bo *aper_array[3];
BATCH_LOCALS;
- /* Blits are in a different ringbuffer so we don't use them. */
- if (intel->gen >= 6)
- return GL_FALSE;
-
if (dst_tiling != I915_TILING_NONE) {
if (dst_offset & 4095)
return GL_FALSE;
@@ -126,12 +123,12 @@ intelEmitCopyBlit(struct intel_context *intel,
/* do space check before going any further */
do {
- aper_array[0] = intel->batch->buf;
+ aper_array[0] = intel->batch.bo;
aper_array[1] = dst_buffer;
aper_array[2] = src_buffer;
if (dri_bufmgr_check_aperture_space(aper_array, 3) != 0) {
- intel_batchbuffer_flush(intel->batch);
+ intel_batchbuffer_flush(intel);
pass++;
} else
break;
@@ -140,7 +137,7 @@ intelEmitCopyBlit(struct intel_context *intel,
if (pass >= 2)
return GL_FALSE;
- intel_batchbuffer_require_space(intel->batch, 8 * 4);
+ intel_batchbuffer_require_space(intel, 8 * 4, true);
DBG("%s src:buf(%p)/%d+%d %d,%d dst:buf(%p)/%d+%d %d,%d sz:%dx%d\n",
__FUNCTION__,
src_buffer, src_pitch, src_offset, src_x, src_y,
@@ -181,7 +178,7 @@ intelEmitCopyBlit(struct intel_context *intel,
assert(dst_x < dst_x2);
assert(dst_y < dst_y2);
- BEGIN_BATCH(8);
+ BEGIN_BATCH_BLT(8);
OUT_BATCH(CMD);
OUT_BATCH(BR13 | (uint16_t)dst_pitch);
OUT_BATCH((dst_y << 16) | dst_x);
@@ -196,7 +193,7 @@ intelEmitCopyBlit(struct intel_context *intel,
src_offset);
ADVANCE_BATCH();
- intel_batchbuffer_emit_mi_flush(intel->batch);
+ intel_batchbuffer_emit_mi_flush(intel);
return GL_TRUE;
}
@@ -209,7 +206,7 @@ intelEmitCopyBlit(struct intel_context *intel,
* which we're clearing with triangles.
* \param mask bitmask of BUFFER_BIT_* values indicating buffers to clear
*/
-void
+GLbitfield
intelClearWithBlit(struct gl_context *ctx, GLbitfield mask)
{
struct intel_context *intel = intel_context(ctx);
@@ -217,11 +214,9 @@ intelClearWithBlit(struct gl_context *ctx, GLbitfield mask)
GLuint clear_depth;
GLboolean all;
GLint cx, cy, cw, ch;
+ GLbitfield fail_mask = 0;
BATCH_LOCALS;
- /* Blits are in a different ringbuffer so we don't use them. */
- assert(intel->gen < 6);
-
/*
* Compute values for clearing the buffers.
*/
@@ -242,7 +237,7 @@ intelClearWithBlit(struct gl_context *ctx, GLbitfield mask)
ch = fb->_Ymax - fb->_Ymin;
if (cw == 0 || ch == 0)
- return;
+ return 0;
GLuint buf;
all = (cw == fb->Width && ch == fb->Height);
@@ -338,9 +333,9 @@ intelClearWithBlit(struct gl_context *ctx, GLbitfield mask)
clear[3], clear[3]);
break;
default:
- _mesa_problem(ctx, "Unexpected renderbuffer format: %d\n",
- irb->Base.Format);
- clear_val = 0;
+ fail_mask |= bufBit;
+ mask &= ~bufBit;
+ continue;
}
}
@@ -348,15 +343,15 @@ intelClearWithBlit(struct gl_context *ctx, GLbitfield mask)
assert(y1 < y2);
/* do space check before going any further */
- aper_array[0] = intel->batch->buf;
+ aper_array[0] = intel->batch.bo;
aper_array[1] = write_buffer;
if (drm_intel_bufmgr_check_aperture_space(aper_array,
ARRAY_SIZE(aper_array)) != 0) {
- intel_batchbuffer_flush(intel->batch);
+ intel_batchbuffer_flush(intel);
}
- BEGIN_BATCH(6);
+ BEGIN_BATCH_BLT(6);
OUT_BATCH(CMD);
OUT_BATCH(BR13);
OUT_BATCH((y1 << 16) | x1);
@@ -368,13 +363,15 @@ intelClearWithBlit(struct gl_context *ctx, GLbitfield mask)
ADVANCE_BATCH();
if (intel->always_flush_cache)
- intel_batchbuffer_emit_mi_flush(intel->batch);
+ intel_batchbuffer_emit_mi_flush(intel);
if (buf == BUFFER_DEPTH || buf == BUFFER_STENCIL)
mask &= ~(BUFFER_BIT_DEPTH | BUFFER_BIT_STENCIL);
else
mask &= ~bufBit; /* turn off bit, for faster loop exit */
}
+
+ return fail_mask;
}
GLboolean
@@ -393,10 +390,6 @@ intelEmitImmediateColorExpandBlit(struct intel_context *intel,
int dwords = ALIGN(src_size, 8) / 4;
uint32_t opcode, br13, blit_cmd;
- /* Blits are in a different ringbuffer so we don't use them. */
- if (intel->gen >= 6)
- return GL_FALSE;
-
if (dst_tiling != I915_TILING_NONE) {
if (dst_offset & 4095)
return GL_FALSE;
@@ -417,10 +410,10 @@ intelEmitImmediateColorExpandBlit(struct intel_context *intel,
__FUNCTION__,
dst_buffer, dst_pitch, dst_offset, x, y, w, h, src_size, dwords);
- intel_batchbuffer_require_space( intel->batch,
- (8 * 4) +
- (3 * 4) +
- dwords * 4 );
+ intel_batchbuffer_require_space(intel,
+ (8 * 4) +
+ (3 * 4) +
+ dwords * 4, true);
opcode = XY_SETUP_BLT_CMD;
if (cpp == 4)
@@ -439,7 +432,7 @@ intelEmitImmediateColorExpandBlit(struct intel_context *intel,
if (dst_tiling != I915_TILING_NONE)
blit_cmd |= XY_DST_TILED;
- BEGIN_BATCH(8 + 3);
+ BEGIN_BATCH_BLT(8 + 3);
OUT_BATCH(opcode);
OUT_BATCH(br13);
OUT_BATCH((0 << 16) | 0); /* clip x1, y1 */
@@ -456,11 +449,9 @@ intelEmitImmediateColorExpandBlit(struct intel_context *intel,
OUT_BATCH(((y + h) << 16) | (x + w));
ADVANCE_BATCH();
- intel_batchbuffer_data( intel->batch,
- src_bits,
- dwords * 4 );
+ intel_batchbuffer_data(intel, src_bits, dwords * 4, true);
- intel_batchbuffer_emit_mi_flush(intel->batch);
+ intel_batchbuffer_emit_mi_flush(intel);
return GL_TRUE;
}
@@ -480,9 +471,6 @@ intel_emit_linear_blit(struct intel_context *intel,
GLuint pitch, height;
GLboolean ok;
- /* Blits are in a different ringbuffer so we don't use them. */
- assert(intel->gen < 6);
-
/* The pitch given to the GPU must be DWORD aligned, and
* we want width to match pitch. Max width is (1 << 15 - 1),
* rounding that down to the nearest DWORD is 1 << 15 - 4
@@ -514,3 +502,81 @@ intel_emit_linear_blit(struct intel_context *intel,
assert(ok);
}
}
+
+/**
+ * Used to initialize the alpha value of an ARGB8888 teximage after
+ * loading it from an XRGB8888 source.
+ *
+ * This is very common with glCopyTexImage2D().
+ */
+void
+intel_set_teximage_alpha_to_one(struct gl_context *ctx,
+ struct intel_texture_image *intel_image)
+{
+ struct intel_context *intel = intel_context(ctx);
+ unsigned int image_x, image_y;
+ uint32_t x1, y1, x2, y2;
+ uint32_t BR13, CMD;
+ int pitch, cpp;
+ drm_intel_bo *aper_array[2];
+ struct intel_region *region = intel_image->mt->region;
+ BATCH_LOCALS;
+
+ assert(intel_image->base.TexFormat == MESA_FORMAT_ARGB8888);
+
+ /* get dest x/y in destination texture */
+ intel_miptree_get_image_offset(intel_image->mt,
+ intel_image->level,
+ intel_image->face,
+ 0,
+ &image_x, &image_y);
+
+ x1 = image_x;
+ y1 = image_y;
+ x2 = image_x + intel_image->base.Width;
+ y2 = image_y + intel_image->base.Height;
+
+ pitch = region->pitch;
+ cpp = region->cpp;
+
+ DBG("%s dst:buf(%p)/%d %d,%d sz:%dx%d\n",
+ __FUNCTION__,
+ intel_image->mt->region->buffer, (pitch * cpp),
+ x1, y1, x2 - x1, y2 - y1);
+
+ BR13 = br13_for_cpp(cpp) | 0xf0 << 16;
+ CMD = XY_COLOR_BLT_CMD;
+ CMD |= XY_BLT_WRITE_ALPHA;
+
+ assert(region->tiling != I915_TILING_Y);
+
+#ifndef I915
+ if (region->tiling != I915_TILING_NONE) {
+ CMD |= XY_DST_TILED;
+ pitch /= 4;
+ }
+#endif
+ BR13 |= (pitch * cpp);
+
+ /* do space check before going any further */
+ aper_array[0] = intel->batch.bo;
+ aper_array[1] = region->buffer;
+
+ if (drm_intel_bufmgr_check_aperture_space(aper_array,
+ ARRAY_SIZE(aper_array)) != 0) {
+ intel_batchbuffer_flush(intel);
+ }
+
+ BEGIN_BATCH_BLT(6);
+ OUT_BATCH(CMD);
+ OUT_BATCH(BR13);
+ OUT_BATCH((y1 << 16) | x1);
+ OUT_BATCH((y2 << 16) | x2);
+ OUT_RELOC_FENCED(region->buffer,
+ I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER,
+ 0);
+ OUT_BATCH(0xffffffff); /* white, but only alpha gets written */
+ ADVANCE_BATCH();
+
+ intel_batchbuffer_emit_mi_flush(intel);
+}
diff --git a/src/mesa/drivers/dri/intel/intel_blit.h b/src/mesa/drivers/dri/intel/intel_blit.h
index 0163146573..88322c7b49 100644
--- a/src/mesa/drivers/dri/intel/intel_blit.h
+++ b/src/mesa/drivers/dri/intel/intel_blit.h
@@ -33,7 +33,7 @@
extern void intelCopyBuffer(const __DRIdrawable * dpriv,
const drm_clip_rect_t * rect);
-extern void intelClearWithBlit(struct gl_context * ctx, GLbitfield mask);
+extern GLbitfield intelClearWithBlit(struct gl_context * ctx, GLbitfield mask);
GLboolean
intelEmitCopyBlit(struct intel_context *intel,
@@ -69,5 +69,7 @@ void intel_emit_linear_blit(struct intel_context *intel,
drm_intel_bo *src_bo,
unsigned int src_offset,
unsigned int size);
+void intel_set_teximage_alpha_to_one(struct gl_context *ctx,
+ struct intel_texture_image *intel_image);
#endif
diff --git a/src/mesa/drivers/dri/intel/intel_buffer_objects.c b/src/mesa/drivers/dri/intel/intel_buffer_objects.c
index 87da60a771..439d6fc824 100644
--- a/src/mesa/drivers/dri/intel/intel_buffer_objects.c
+++ b/src/mesa/drivers/dri/intel/intel_buffer_objects.c
@@ -27,6 +27,7 @@
#include "main/imports.h"
+#include "main/mfeatures.h"
#include "main/mtypes.h"
#include "main/macros.h"
#include "main/bufferobj.h"
@@ -52,6 +53,15 @@ intel_bufferobj_alloc_buffer(struct intel_context *intel,
intel_obj->Base.Size, 64);
}
+static void
+release_buffer(struct intel_buffer_object *intel_obj)
+{
+ drm_intel_bo_unreference(intel_obj->buffer);
+ intel_obj->buffer = NULL;
+ intel_obj->offset = 0;
+ intel_obj->source = 0;
+}
+
/**
* There is some duplication between mesa's bufferobjects and our
* bufmgr buffers. Both have an integer handle and a hashtable to
@@ -80,8 +90,7 @@ intel_bufferobj_release_region(struct intel_context *intel,
intel_obj->region->pbo = NULL;
intel_obj->region = NULL;
- drm_intel_bo_unreference(intel_obj->buffer);
- intel_obj->buffer = NULL;
+ release_buffer(intel_obj);
}
/* Break the COW tie to the region. Both the pbo and the region end
@@ -119,10 +128,8 @@ intel_bufferobj_free(struct gl_context * ctx, struct gl_buffer_object *obj)
if (intel_obj->region) {
intel_bufferobj_release_region(intel, intel_obj);
}
- else if (intel_obj->buffer) {
- drm_intel_bo_unreference(intel_obj->buffer);
- }
+ drm_intel_bo_unreference(intel_obj->buffer);
free(intel_obj);
}
@@ -153,19 +160,22 @@ intel_bufferobj_data(struct gl_context * ctx,
if (intel_obj->region)
intel_bufferobj_release_region(intel, intel_obj);
- if (intel_obj->buffer != NULL) {
- drm_intel_bo_unreference(intel_obj->buffer);
- intel_obj->buffer = NULL;
- }
+ if (intel_obj->buffer != NULL)
+ release_buffer(intel_obj);
+
free(intel_obj->sys_buffer);
intel_obj->sys_buffer = NULL;
if (size != 0) {
+ if (usage == GL_DYNAMIC_DRAW
#ifdef I915
- /* On pre-965, stick VBOs in system memory, as we're always doing swtnl
- * with their contents anyway.
- */
- if (target == GL_ARRAY_BUFFER || target == GL_ELEMENT_ARRAY_BUFFER) {
+ /* On pre-965, stick VBOs in system memory, as we're always doing
+ * swtnl with their contents anyway.
+ */
+ || target == GL_ARRAY_BUFFER || target == GL_ELEMENT_ARRAY_BUFFER
+#endif
+ )
+ {
intel_obj->sys_buffer = malloc(size);
if (intel_obj->sys_buffer != NULL) {
if (data != NULL)
@@ -173,7 +183,6 @@ intel_bufferobj_data(struct gl_context * ctx,
return GL_TRUE;
}
}
-#endif
intel_bufferobj_alloc_buffer(intel, intel_obj);
if (!intel_obj->buffer)
return GL_FALSE;
@@ -201,6 +210,7 @@ intel_bufferobj_subdata(struct gl_context * ctx,
{
struct intel_context *intel = intel_context(ctx);
struct intel_buffer_object *intel_obj = intel_buffer_object(obj);
+ bool busy;
if (size == 0)
return;
@@ -210,34 +220,53 @@ intel_bufferobj_subdata(struct gl_context * ctx,
if (intel_obj->region)
intel_bufferobj_cow(intel, intel_obj);
- if (intel_obj->sys_buffer)
- memcpy((char *)intel_obj->sys_buffer + offset, data, size);
- else {
- /* Flush any existing batchbuffer that might reference this data. */
- if (intel->gen < 6) {
- if (drm_intel_bo_busy(intel_obj->buffer) ||
- drm_intel_bo_references(intel->batch->buf, intel_obj->buffer)) {
- drm_intel_bo *temp_bo;
+ /* If we have a single copy in system memory, update that */
+ if (intel_obj->sys_buffer) {
+ if (intel_obj->source)
+ release_buffer(intel_obj);
- temp_bo = drm_intel_bo_alloc(intel->bufmgr, "subdata temp", size, 64);
+ if (intel_obj->buffer == NULL) {
+ memcpy((char *)intel_obj->sys_buffer + offset, data, size);
+ return;
+ }
- drm_intel_bo_subdata(temp_bo, 0, size, data);
+ free(intel_obj->sys_buffer);
+ intel_obj->sys_buffer = NULL;
+ }
- intel_emit_linear_blit(intel,
- intel_obj->buffer, offset,
- temp_bo, 0,
- size);
+ /* Otherwise we need to update the copy in video memory. */
+ busy =
+ drm_intel_bo_busy(intel_obj->buffer) ||
+ drm_intel_bo_references(intel->batch.bo, intel_obj->buffer);
- drm_intel_bo_unreference(temp_bo);
- } else {
- drm_intel_bo_subdata(intel_obj->buffer, offset, size, data);
- }
+ /* replace the current busy bo with fresh data */
+ if (busy && size == intel_obj->Base.Size) {
+ drm_intel_bo_unreference(intel_obj->buffer);
+ intel_bufferobj_alloc_buffer(intel, intel_obj);
+ drm_intel_bo_subdata(intel_obj->buffer, 0, size, data);
+ } else if (intel->gen < 6) {
+ if (busy) {
+ drm_intel_bo *temp_bo;
+
+ temp_bo = drm_intel_bo_alloc(intel->bufmgr, "subdata temp", size, 64);
+
+ drm_intel_bo_subdata(temp_bo, 0, size, data);
+
+ intel_emit_linear_blit(intel,
+ intel_obj->buffer, offset,
+ temp_bo, 0,
+ size);
+
+ drm_intel_bo_unreference(temp_bo);
} else {
- if (drm_intel_bo_references(intel->batch->buf, intel_obj->buffer)) {
- intel_batchbuffer_flush(intel->batch);
- }
drm_intel_bo_subdata(intel_obj->buffer, offset, size, data);
}
+ } else {
+ /* Can't use the blit to modify the buffer in the middle of batch. */
+ if (drm_intel_bo_references(intel->batch.bo, intel_obj->buffer)) {
+ intel_batchbuffer_flush(intel);
+ }
+ drm_intel_bo_subdata(intel_obj->buffer, offset, size, data);
}
}
@@ -279,14 +308,23 @@ intel_bufferobj_map(struct gl_context * ctx,
assert(intel_obj);
if (intel_obj->sys_buffer) {
- obj->Pointer = intel_obj->sys_buffer;
- obj->Length = obj->Size;
- obj->Offset = 0;
- return obj->Pointer;
+ if (!read_only && intel_obj->source) {
+ release_buffer(intel_obj);
+ }
+
+ if (!intel_obj->buffer || intel_obj->source) {
+ obj->Pointer = intel_obj->sys_buffer;
+ obj->Length = obj->Size;
+ obj->Offset = 0;
+ return obj->Pointer;
+ }
+
+ free(intel_obj->sys_buffer);
+ intel_obj->sys_buffer = NULL;
}
/* Flush any existing batchbuffer that might reference this data. */
- if (drm_intel_bo_references(intel->batch->buf, intel_obj->buffer))
+ if (drm_intel_bo_references(intel->batch.bo, intel_obj->buffer))
intel_flush(ctx);
if (intel_obj->region)
@@ -335,6 +373,7 @@ intel_bufferobj_map_range(struct gl_context * ctx,
{
struct intel_context *intel = intel_context(ctx);
struct intel_buffer_object *intel_obj = intel_buffer_object(obj);
+ GLboolean read_only = (access == GL_READ_ONLY_ARB);
assert(intel_obj);
@@ -346,8 +385,16 @@ intel_bufferobj_map_range(struct gl_context * ctx,
obj->AccessFlags = access;
if (intel_obj->sys_buffer) {
- obj->Pointer = intel_obj->sys_buffer + offset;
- return obj->Pointer;
+ if (!read_only && intel_obj->source)
+ release_buffer(intel_obj);
+
+ if (!intel_obj->buffer || intel_obj->source) {
+ obj->Pointer = intel_obj->sys_buffer + offset;
+ return obj->Pointer;
+ }
+
+ free(intel_obj->sys_buffer);
+ intel_obj->sys_buffer = NULL;
}
if (intel_obj->region)
@@ -358,7 +405,7 @@ intel_bufferobj_map_range(struct gl_context * ctx,
* syncing.
*/
if (!(access & GL_MAP_UNSYNCHRONIZED_BIT) &&
- drm_intel_bo_references(intel->batch->buf, intel_obj->buffer))
+ drm_intel_bo_references(intel->batch.bo, intel_obj->buffer))
intel_flush(ctx);
if (intel_obj->buffer == NULL) {
@@ -373,8 +420,7 @@ intel_bufferobj_map_range(struct gl_context * ctx,
(access & GL_MAP_INVALIDATE_BUFFER_BIT) &&
drm_intel_bo_busy(intel_obj->buffer)) {
drm_intel_bo_unreference(intel_obj->buffer);
- intel_obj->buffer = drm_intel_bo_alloc(intel->bufmgr, "bufferobj",
- intel_obj->Base.Size, 64);
+ intel_bufferobj_alloc_buffer(intel, intel_obj);
}
/* If the user is mapping a range of an active buffer object but
@@ -472,7 +518,7 @@ intel_bufferobj_unmap(struct gl_context * ctx,
* flush. Once again, we wish for a domain tracker in libdrm to cover
* usage inside of a batchbuffer.
*/
- intel_batchbuffer_emit_mi_flush(intel->batch);
+ intel_batchbuffer_emit_mi_flush(intel);
free(intel_obj->range_map_buffer);
intel_obj->range_map_buffer = NULL;
} else if (intel_obj->range_map_bo != NULL) {
@@ -492,7 +538,7 @@ intel_bufferobj_unmap(struct gl_context * ctx,
* flush. Once again, we wish for a domain tracker in libdrm to cover
* usage inside of a batchbuffer.
*/
- intel_batchbuffer_emit_mi_flush(intel->batch);
+ intel_batchbuffer_emit_mi_flush(intel);
drm_intel_bo_unreference(intel_obj->range_map_bo);
intel_obj->range_map_bo = NULL;
@@ -512,7 +558,8 @@ intel_bufferobj_unmap(struct gl_context * ctx,
drm_intel_bo *
intel_bufferobj_buffer(struct intel_context *intel,
- struct intel_buffer_object *intel_obj, GLuint flag)
+ struct intel_buffer_object *intel_obj,
+ GLuint flag)
{
if (intel_obj->region) {
if (flag == INTEL_WRITE_PART)
@@ -523,23 +570,169 @@ intel_bufferobj_buffer(struct intel_context *intel,
}
}
- if (intel_obj->buffer == NULL) {
- void *sys_buffer = intel_obj->sys_buffer;
+ if (intel_obj->source)
+ release_buffer(intel_obj);
- /* only one of buffer and sys_buffer could be non-NULL */
+ if (intel_obj->buffer == NULL) {
intel_bufferobj_alloc_buffer(intel, intel_obj);
- intel_obj->sys_buffer = NULL;
+ drm_intel_bo_subdata(intel_obj->buffer,
+ 0, intel_obj->Base.Size,
+ intel_obj->sys_buffer);
- intel_bufferobj_subdata(&intel->ctx,
- GL_ARRAY_BUFFER_ARB,
- 0,
- intel_obj->Base.Size,
- sys_buffer,
- &intel_obj->Base);
- free(sys_buffer);
+ free(intel_obj->sys_buffer);
intel_obj->sys_buffer = NULL;
+ intel_obj->offset = 0;
+ }
+
+ return intel_obj->buffer;
+}
+
+#define INTEL_UPLOAD_SIZE (64*1024)
+
+void
+intel_upload_finish(struct intel_context *intel)
+{
+ if (!intel->upload.bo)
+ return;
+
+ if (intel->upload.buffer_len) {
+ drm_intel_bo_subdata(intel->upload.bo,
+ intel->upload.buffer_offset,
+ intel->upload.buffer_len,
+ intel->upload.buffer);
+ intel->upload.buffer_len = 0;
+ }
+
+ drm_intel_bo_unreference(intel->upload.bo);
+ intel->upload.bo = NULL;
+}
+
+static void wrap_buffers(struct intel_context *intel, GLuint size)
+{
+ intel_upload_finish(intel);
+
+ if (size < INTEL_UPLOAD_SIZE)
+ size = INTEL_UPLOAD_SIZE;
+
+ intel->upload.bo = drm_intel_bo_alloc(intel->bufmgr, "upload", size, 0);
+ intel->upload.offset = 0;
+}
+
+void intel_upload_data(struct intel_context *intel,
+ const void *ptr, GLuint size, GLuint align,
+ drm_intel_bo **return_bo,
+ GLuint *return_offset)
+{
+ GLuint base, delta;
+
+ base = (intel->upload.offset + align - 1) / align * align;
+ if (intel->upload.bo == NULL || base + size > intel->upload.bo->size) {
+ wrap_buffers(intel, size);
+ base = 0;
+ }
+
+ drm_intel_bo_reference(intel->upload.bo);
+ *return_bo = intel->upload.bo;
+ *return_offset = base;
+
+ delta = base - intel->upload.offset;
+ if (intel->upload.buffer_len &&
+ intel->upload.buffer_len + delta + size > sizeof(intel->upload.buffer))
+ {
+ drm_intel_bo_subdata(intel->upload.bo,
+ intel->upload.buffer_offset,
+ intel->upload.buffer_len,
+ intel->upload.buffer);
+ intel->upload.buffer_len = 0;
+ }
+
+ if (size < sizeof(intel->upload.buffer))
+ {
+ if (intel->upload.buffer_len == 0)
+ intel->upload.buffer_offset = base;
+ else
+ intel->upload.buffer_len += delta;
+
+ memcpy(intel->upload.buffer + intel->upload.buffer_len, ptr, size);
+ intel->upload.buffer_len += size;
+ }
+ else
+ {
+ drm_intel_bo_subdata(intel->upload.bo, base, size, ptr);
+ }
+
+ intel->upload.offset = base + size;
+}
+
+void *intel_upload_map(struct intel_context *intel, GLuint size, GLuint align)
+{
+ GLuint base, delta;
+ char *ptr;
+
+ base = (intel->upload.offset + align - 1) / align * align;
+ if (intel->upload.bo == NULL || base + size > intel->upload.bo->size) {
+ wrap_buffers(intel, size);
+ base = 0;
+ }
+
+ delta = base - intel->upload.offset;
+ if (intel->upload.buffer_len &&
+ intel->upload.buffer_len + delta + size > sizeof(intel->upload.buffer))
+ {
+ drm_intel_bo_subdata(intel->upload.bo,
+ intel->upload.buffer_offset,
+ intel->upload.buffer_len,
+ intel->upload.buffer);
+ intel->upload.buffer_len = 0;
+ }
+
+ if (size <= sizeof(intel->upload.buffer)) {
+ if (intel->upload.buffer_len == 0)
+ intel->upload.buffer_offset = base;
+ else
+ intel->upload.buffer_len += delta;
+
+ ptr = intel->upload.buffer + intel->upload.buffer_len;
+ intel->upload.buffer_len += size;
+ } else
+ ptr = malloc(size);
+
+ return ptr;
+}
+
+void intel_upload_unmap(struct intel_context *intel,
+ const void *ptr, GLuint size, GLuint align,
+ drm_intel_bo **return_bo,
+ GLuint *return_offset)
+{
+ GLuint base;
+
+ base = (intel->upload.offset + align - 1) / align * align;
+ if (size > sizeof(intel->upload.buffer)) {
+ drm_intel_bo_subdata(intel->upload.bo, base, size, ptr);
+ free((void*)ptr);
+ }
+
+ drm_intel_bo_reference(intel->upload.bo);
+ *return_bo = intel->upload.bo;
+ *return_offset = base;
+
+ intel->upload.offset = base + size;
+}
+
+drm_intel_bo *
+intel_bufferobj_source(struct intel_context *intel,
+ struct intel_buffer_object *intel_obj,
+ GLuint align, GLuint *offset)
+{
+ if (intel_obj->buffer == NULL) {
+ intel_upload_data(intel,
+ intel_obj->sys_buffer, intel_obj->Base.Size, align,
+ &intel_obj->buffer, &intel_obj->offset);
+ intel_obj->source = 1;
}
+ *offset = intel_obj->offset;
return intel_obj->buffer;
}
@@ -554,6 +747,7 @@ intel_bufferobj_copy_subdata(struct gl_context *ctx,
struct intel_buffer_object *intel_src = intel_buffer_object(src);
struct intel_buffer_object *intel_dst = intel_buffer_object(dst);
drm_intel_bo *src_bo, *dst_bo;
+ GLuint src_offset;
if (size == 0)
return;
@@ -566,7 +760,7 @@ intel_bufferobj_copy_subdata(struct gl_context *ctx,
if (src == dst) {
char *ptr = intel_bufferobj_map(ctx, GL_COPY_WRITE_BUFFER,
GL_READ_WRITE, dst);
- memcpy(ptr + write_offset, ptr + read_offset, size);
+ memmove(ptr + write_offset, ptr + read_offset, size);
intel_bufferobj_unmap(ctx, GL_COPY_WRITE_BUFFER, dst);
} else {
const char *src_ptr;
@@ -588,18 +782,18 @@ intel_bufferobj_copy_subdata(struct gl_context *ctx,
/* Otherwise, we have real BOs, so blit them. */
dst_bo = intel_bufferobj_buffer(intel, intel_dst, INTEL_WRITE_PART);
- src_bo = intel_bufferobj_buffer(intel, intel_src, INTEL_READ);
+ src_bo = intel_bufferobj_source(intel, intel_src, 64, &src_offset);
intel_emit_linear_blit(intel,
dst_bo, write_offset,
- src_bo, read_offset, size);
+ src_bo, read_offset + src_offset, size);
/* Since we've emitted some blits to buffers that will (likely) be used
* in rendering operations in other cache domains in this batch, emit a
* flush. Once again, we wish for a domain tracker in libdrm to cover
* usage inside of a batchbuffer.
*/
- intel_batchbuffer_emit_mi_flush(intel->batch);
+ intel_batchbuffer_emit_mi_flush(intel);
}
#if FEATURE_APPLE_object_purgeable
diff --git a/src/mesa/drivers/dri/intel/intel_buffer_objects.h b/src/mesa/drivers/dri/intel/intel_buffer_objects.h
index b15c192106..81ee21f062 100644
--- a/src/mesa/drivers/dri/intel/intel_buffer_objects.h
+++ b/src/mesa/drivers/dri/intel/intel_buffer_objects.h
@@ -42,6 +42,8 @@ struct intel_buffer_object
{
struct gl_buffer_object Base;
drm_intel_bo *buffer; /* the low-level buffer manager's buffer handle */
+ GLuint offset; /* any offset into that buffer */
+
/** System memory buffer data, if not using a BO to store the data. */
void *sys_buffer;
@@ -55,6 +57,7 @@ struct intel_buffer_object
GLsizei range_map_size;
GLboolean mapped_gtt;
+ GLboolean source;
};
@@ -63,8 +66,26 @@ struct intel_buffer_object
drm_intel_bo *intel_bufferobj_buffer(struct intel_context *intel,
struct intel_buffer_object *obj,
GLuint flag);
+drm_intel_bo *intel_bufferobj_source(struct intel_context *intel,
+ struct intel_buffer_object *obj,
+ GLuint align,
+ GLuint *offset);
+
+void intel_upload_data(struct intel_context *intel,
+ const void *ptr, GLuint size, GLuint align,
+ drm_intel_bo **return_bo,
+ GLuint *return_offset);
+
+void *intel_upload_map(struct intel_context *intel,
+ GLuint size, GLuint align);
+void intel_upload_unmap(struct intel_context *intel,
+ const void *ptr, GLuint size, GLuint align,
+ drm_intel_bo **return_bo,
+ GLuint *return_offset);
+
+void intel_upload_finish(struct intel_context *intel);
-/* Hook the bufferobject implementation into mesa:
+/* Hook the bufferobject implementation into mesa:
*/
void intelInitBufferObjectFuncs(struct dd_function_table *functions);
diff --git a/src/mesa/drivers/dri/intel/intel_chipset.h b/src/mesa/drivers/dri/intel/intel_chipset.h
index 4fecdbed20..4ff9140d56 100644
--- a/src/mesa/drivers/dri/intel/intel_chipset.h
+++ b/src/mesa/drivers/dri/intel/intel_chipset.h
@@ -133,6 +133,10 @@
devid == PCI_CHIP_SANDYBRIDGE_M_GT2_PLUS || \
devid == PCI_CHIP_SANDYBRIDGE_S)
+#define IS_GT1(devid) (devid == PCI_CHIP_SANDYBRIDGE_GT1 || \
+ devid == PCI_CHIP_SANDYBRIDGE_M_GT1 || \
+ devid == PCI_CHIP_SANDYBRIDGE_S)
+
#define IS_965(devid) (IS_GEN4(devid) || \
IS_G4X(devid) || \
IS_GEN5(devid) || \
diff --git a/src/mesa/drivers/dri/intel/intel_clear.c b/src/mesa/drivers/dri/intel/intel_clear.c
index fa451f0045..82d29e7671 100644
--- a/src/mesa/drivers/dri/intel/intel_clear.c
+++ b/src/mesa/drivers/dri/intel/intel_clear.c
@@ -85,6 +85,8 @@ intelClear(struct gl_context *ctx, GLbitfield mask)
GLbitfield blit_mask = 0;
GLbitfield swrast_mask = 0;
struct gl_framebuffer *fb = ctx->DrawBuffer;
+ struct intel_renderbuffer *irb;
+ int i;
if (mask & (BUFFER_BIT_FRONT_LEFT | BUFFER_BIT_FRONT_RIGHT)) {
intel->front_buffer_dirty = GL_TRUE;
@@ -93,6 +95,22 @@ intelClear(struct gl_context *ctx, GLbitfield mask)
if (0)
fprintf(stderr, "%s\n", __FUNCTION__);
+ /* Get SW clears out of the way: Anything without an intel_renderbuffer */
+ for (i = 0; i < BUFFER_COUNT; i++) {
+ if (!(mask & (1 << i)))
+ continue;
+
+ irb = intel_get_renderbuffer(fb, i);
+ if (unlikely(!irb)) {
+ swrast_mask |= (1 << i);
+ mask &= ~(1 << i);
+ }
+ }
+ if (unlikely(swrast_mask)) {
+ debug_mask("swrast", swrast_mask);
+ _swrast_Clear(ctx, swrast_mask);
+ }
+
/* HW color buffers (front, back, aux, generic FBO, etc) */
if (colorMask == ~0) {
/* clear all R,G,B,A */
@@ -151,44 +169,18 @@ intelClear(struct gl_context *ctx, GLbitfield mask)
}
}
- if (intel->gen >= 6) {
- /* Blits are in a different ringbuffer so we don't use them. */
- tri_mask |= blit_mask;
- blit_mask = 0;
- }
-
- /* SW fallback clearing */
- swrast_mask = mask & ~tri_mask & ~blit_mask;
-
- {
- /* look for non-Intel renderbuffers (clear them with swrast) */
- GLbitfield blit_or_tri = blit_mask | tri_mask;
- while (blit_or_tri) {
- GLuint i = _mesa_ffs(blit_or_tri) - 1;
- GLbitfield bufBit = 1 << i;
- if (!fb->Attachment[i].Renderbuffer->ClassID) {
- blit_mask &= ~bufBit;
- tri_mask &= ~bufBit;
- swrast_mask |= bufBit;
- }
- blit_or_tri ^= bufBit;
- }
- }
+ /* Anything left, just use tris */
+ tri_mask |= mask & ~blit_mask;
if (blit_mask) {
debug_mask("blit", blit_mask);
- intelClearWithBlit(ctx, blit_mask);
+ tri_mask |= intelClearWithBlit(ctx, blit_mask);
}
if (tri_mask) {
debug_mask("tri", tri_mask);
_mesa_meta_Clear(&intel->ctx, tri_mask);
}
-
- if (swrast_mask) {
- debug_mask("swrast", swrast_mask);
- _swrast_Clear(ctx, swrast_mask);
- }
}
diff --git a/src/mesa/drivers/dri/intel/intel_context.c b/src/mesa/drivers/dri/intel/intel_context.c
index 968f3c6e46..7c422c4c3a 100644
--- a/src/mesa/drivers/dri/intel/intel_context.c
+++ b/src/mesa/drivers/dri/intel/intel_context.c
@@ -496,11 +496,9 @@ intel_prepare_render(struct intel_context *intel)
* the swap, and getting our hands on that doesn't seem worth it,
* so we just us the first batch we emitted after the last swap.
*/
- if (intel->need_throttle && intel->first_post_swapbuffers_batch) {
- drm_intel_bo_wait_rendering(intel->first_post_swapbuffers_batch);
- drm_intel_bo_unreference(intel->first_post_swapbuffers_batch);
- intel->first_post_swapbuffers_batch = NULL;
- intel->need_throttle = GL_FALSE;
+ if (intel->need_throttle) {
+ drmCommandNone(intel->driFd, DRM_I915_GEM_THROTTLE);
+ intel->need_throttle = GL_FALSE;
}
}
@@ -513,7 +511,7 @@ intel_viewport(struct gl_context *ctx, GLint x, GLint y, GLsizei w, GLsizei h)
if (intel->saved_viewport)
intel->saved_viewport(ctx, x, y, w, h);
- if (!intel->meta.internal_viewport_call && ctx->DrawBuffer->Name == 0) {
+ if (ctx->DrawBuffer->Name == 0) {
dri2InvalidateDrawable(driContext->driDrawablePriv);
dri2InvalidateDrawable(driContext->driReadablePriv);
}
@@ -580,8 +578,8 @@ intel_flush(struct gl_context *ctx)
if (intel->gen < 4)
INTEL_FIREVERTICES(intel);
- if (intel->batch->map != intel->batch->ptr)
- intel_batchbuffer_flush(intel->batch);
+ if (intel->batch.used)
+ intel_batchbuffer_flush(intel);
}
static void
@@ -591,7 +589,8 @@ intel_glFlush(struct gl_context *ctx)
intel_flush(ctx);
intel_flush_front(ctx);
- intel->need_throttle = GL_TRUE;
+ if (intel->is_front_buffer_rendering)
+ intel->need_throttle = GL_TRUE;
}
void
@@ -608,7 +607,7 @@ intelFinish(struct gl_context * ctx)
irb = intel_renderbuffer(fb->_ColorDrawBuffers[i]);
- if (irb && irb->region)
+ if (irb && irb->region && irb->region->buffer)
drm_intel_bo_wait_rendering(irb->region->buffer);
}
if (fb->_DepthBuffer) {
@@ -669,8 +668,8 @@ intelInitContext(struct intel_context *intel,
mesaVis = &visual;
}
- if (!_mesa_initialize_context_for_api(&intel->ctx, api, mesaVis, shareCtx,
- functions, (void *) intel)) {
+ if (!_mesa_initialize_context(&intel->ctx, api, mesaVis, shareCtx,
+ functions, (void *) intel)) {
printf("%s: failed to init mesa context\n", __FUNCTION__);
return GL_FALSE;
}
@@ -708,12 +707,75 @@ intelInitContext(struct intel_context *intel,
}
}
+ memset(&ctx->TextureFormatSupported, 0,
+ sizeof(ctx->TextureFormatSupported));
+ ctx->TextureFormatSupported[MESA_FORMAT_ARGB8888] = GL_TRUE;
+ if (intel->has_xrgb_textures)
+ ctx->TextureFormatSupported[MESA_FORMAT_XRGB8888] = GL_TRUE;
+ ctx->TextureFormatSupported[MESA_FORMAT_ARGB4444] = GL_TRUE;
+ ctx->TextureFormatSupported[MESA_FORMAT_ARGB1555] = GL_TRUE;
+ ctx->TextureFormatSupported[MESA_FORMAT_RGB565] = GL_TRUE;
+ ctx->TextureFormatSupported[MESA_FORMAT_L8] = GL_TRUE;
+ ctx->TextureFormatSupported[MESA_FORMAT_A8] = GL_TRUE;
+ ctx->TextureFormatSupported[MESA_FORMAT_I8] = GL_TRUE;
+ ctx->TextureFormatSupported[MESA_FORMAT_AL88] = GL_TRUE;
+ if (intel->gen >= 4)
+ ctx->TextureFormatSupported[MESA_FORMAT_AL1616] = GL_TRUE;
+ ctx->TextureFormatSupported[MESA_FORMAT_S8_Z24] = GL_TRUE;
+ /*
+ * This was disabled in initial FBO enabling to avoid combinations
+ * of depth+stencil that wouldn't work together. We since decided
+ * that it was OK, since it's up to the app to come up with the
+ * combo that actually works, so this can probably be re-enabled.
+ */
+ /*
+ ctx->TextureFormatSupported[MESA_FORMAT_Z16] = GL_TRUE;
+ ctx->TextureFormatSupported[MESA_FORMAT_Z24] = GL_TRUE;
+ */
+
+ /* ctx->Extensions.MESA_ycbcr_texture */
+ ctx->TextureFormatSupported[MESA_FORMAT_YCBCR] = GL_TRUE;
+ ctx->TextureFormatSupported[MESA_FORMAT_YCBCR_REV] = GL_TRUE;
+
+ /* GL_3DFX_texture_compression_FXT1 */
+ ctx->TextureFormatSupported[MESA_FORMAT_RGB_FXT1] = GL_TRUE;
+ ctx->TextureFormatSupported[MESA_FORMAT_RGBA_FXT1] = GL_TRUE;
+
+ /* GL_EXT_texture_compression_s3tc */
+ ctx->TextureFormatSupported[MESA_FORMAT_RGB_DXT1] = GL_TRUE;
+ ctx->TextureFormatSupported[MESA_FORMAT_RGBA_DXT1] = GL_TRUE;
+ ctx->TextureFormatSupported[MESA_FORMAT_RGBA_DXT3] = GL_TRUE;
+ ctx->TextureFormatSupported[MESA_FORMAT_RGBA_DXT5] = GL_TRUE;
+
+#ifndef I915
+ /* GL_ARB_texture_rg */
+ ctx->TextureFormatSupported[MESA_FORMAT_R8] = GL_TRUE;
+ ctx->TextureFormatSupported[MESA_FORMAT_R16] = GL_TRUE;
+ ctx->TextureFormatSupported[MESA_FORMAT_RG88] = GL_TRUE;
+ ctx->TextureFormatSupported[MESA_FORMAT_RG1616] = GL_TRUE;
+
+ ctx->TextureFormatSupported[MESA_FORMAT_DUDV8] = GL_TRUE;
+ ctx->TextureFormatSupported[MESA_FORMAT_SIGNED_RGBA8888_REV] = GL_TRUE;
+
+ /* GL_EXT_texture_sRGB */
+ ctx->TextureFormatSupported[MESA_FORMAT_SARGB8] = GL_TRUE;
+ if (intel->gen >= 5 || intel->is_g4x)
+ ctx->TextureFormatSupported[MESA_FORMAT_SRGB_DXT1] = GL_TRUE;
+ ctx->TextureFormatSupported[MESA_FORMAT_SRGBA_DXT1] = GL_TRUE;
+ ctx->TextureFormatSupported[MESA_FORMAT_SRGBA_DXT3] = GL_TRUE;
+ ctx->TextureFormatSupported[MESA_FORMAT_SRGBA_DXT5] = GL_TRUE;
+ if (intel->has_luminance_srgb) {
+ ctx->TextureFormatSupported[MESA_FORMAT_SL8] = GL_TRUE;
+ ctx->TextureFormatSupported[MESA_FORMAT_SLA8] = GL_TRUE;
+ }
+#endif
+
driParseConfigFiles(&intel->optionCache, &intelScreen->optionCache,
sPriv->myNum, (intel->gen >= 4) ? "i965" : "i915");
- if (intelScreen->deviceID == PCI_CHIP_I865_G)
+ if (intel->gen < 4)
intel->maxBatchSize = 4096;
else
- intel->maxBatchSize = BATCH_SZ;
+ intel->maxBatchSize = sizeof(intel->batch.map);
intel->bufmgr = intelScreen->bufmgr;
@@ -767,8 +829,8 @@ intelInitContext(struct intel_context *intel,
*/
_mesa_init_point(ctx);
- meta_init_metaops(ctx, &intel->meta);
if (intel->gen >= 4) {
+ ctx->Const.sRGBCapable = GL_TRUE;
if (MAX_WIDTH > 8192)
ctx->Const.MaxRenderbufferSize = 8192;
} else {
@@ -826,7 +888,7 @@ intelInitContext(struct intel_context *intel,
if (INTEL_DEBUG & DEBUG_BUFMGR)
dri_bufmgr_set_debug(intel->bufmgr, GL_TRUE);
- intel->batch = intel_batchbuffer_alloc(intel);
+ intel_batchbuffer_reset(intel);
intel_fbo_init(intel);
@@ -874,8 +936,6 @@ intelDestroyContext(__DRIcontext * driContextPriv)
_mesa_meta_free(&intel->ctx);
- meta_destroy_metaops(&intel->meta);
-
intel->vtbl.destroy(intel);
_swsetup_DestroyContext(&intel->ctx);
@@ -885,15 +945,12 @@ intelDestroyContext(__DRIcontext * driContextPriv)
_swrast_DestroyContext(&intel->ctx);
intel->Fallback = 0x0; /* don't call _swrast_Flush later */
- intel_batchbuffer_free(intel->batch);
- intel->batch = NULL;
+ intel_batchbuffer_free(intel);
free(intel->prim.vb);
intel->prim.vb = NULL;
drm_intel_bo_unreference(intel->prim.vb_bo);
intel->prim.vb_bo = NULL;
- drm_intel_bo_unreference(intel->first_post_swapbuffers_batch);
- intel->first_post_swapbuffers_batch = NULL;
driDestroyOptionCache(&intel->optionCache);
diff --git a/src/mesa/drivers/dri/intel/intel_context.h b/src/mesa/drivers/dri/intel/intel_context.h
index 96493c0f2b..772b2fba5a 100644
--- a/src/mesa/drivers/dri/intel/intel_context.h
+++ b/src/mesa/drivers/dri/intel/intel_context.h
@@ -29,10 +29,9 @@
#define INTELCONTEXT_INC
-
+#include <stdbool.h>
#include "main/mtypes.h"
#include "main/mm.h"
-#include "dri_metaops.h"
#ifdef __cplusplus
extern "C" {
@@ -149,10 +148,9 @@ struct intel_context
void (*assert_not_dirty) (struct intel_context *intel);
void (*debug_batch)(struct intel_context *intel);
+ bool (*render_target_supported)(gl_format format);
} vtbl;
- struct dri_metaops meta;
-
GLbitfield Fallback; /**< mask of INTEL_FALLBACK_x bits */
GLuint NewGLState;
@@ -171,17 +169,28 @@ struct intel_context
int urb_size;
- struct intel_batchbuffer *batch;
- drm_intel_bo *first_post_swapbuffers_batch;
+ struct intel_batchbuffer {
+ drm_intel_bo *bo;
+ struct cached_batch_item *cached_items;
+
+ uint16_t emit, total;
+ uint16_t used, reserved_space;
+ uint32_t map[8192];
+#define BATCH_SZ (8192*sizeof(uint32_t))
+
+ uint32_t state_batch_offset;
+ bool is_blit;
+ } batch;
+
GLboolean need_throttle;
GLboolean no_batch_wrap;
struct
{
GLuint id;
+ uint32_t start_ptr; /**< for i8xx */
uint32_t primitive; /**< Current hardware primitive type */
void (*flush) (struct intel_context *);
- GLubyte *start_ptr; /**< for i8xx */
drm_intel_bo *vb_bo;
uint8_t *vb;
unsigned int start_offset; /**< Byte offset of primitive sequence */
@@ -189,6 +198,14 @@ struct intel_context
unsigned int count; /**< Number of vertices in current primitive */
} prim;
+ struct {
+ drm_intel_bo *bo;
+ GLuint offset;
+ uint32_t buffer_len;
+ uint32_t buffer_offset;
+ char buffer[4096];
+ } upload;
+
GLuint stats_wm;
/* Offsets of fields within the current vertex:
diff --git a/src/mesa/drivers/dri/intel/intel_decode.c b/src/mesa/drivers/dri/intel/intel_decode.c
index 25b4131594..688b8fee64 100644
--- a/src/mesa/drivers/dri/intel/intel_decode.c
+++ b/src/mesa/drivers/dri/intel/intel_decode.c
@@ -1601,10 +1601,12 @@ decode_3d_965(uint32_t *data, int count, uint32_t hw_offset, uint32_t devid, int
{ 0x790a, 3, 3, "3DSTATE_AA_LINE_PARAMETERS" },
{ 0x790b, 4, 4, "3DSTATE_GS_SVB_INDEX" },
{ 0x790d, 3, 3, "3DSTATE_MULTISAMPLE" },
+ { 0x7910, 2, 2, "3DSTATE_CLEAR_PARAMS" },
{ 0x7b00, 6, 6, "3DPRIMITIVE" },
{ 0x7802, 4, 4, "3DSTATE_SAMPLER_STATE_POINTERS" },
{ 0x7805, 3, 3, "3DSTATE_URB" },
{ 0x780e, 4, 4, "3DSTATE_CC_STATE_POINTERS" },
+ { 0x780f, 2, 2, "3DSTATE_SCISSOR_STATE_POINTERS" },
{ 0x7810, 6, 6, "3DSTATE_VS_STATE" },
{ 0x7811, 7, 7, "3DSTATE_GS_STATE" },
{ 0x7812, 4, 4, "3DSTATE_CLIP_STATE" },
diff --git a/src/mesa/drivers/dri/intel/intel_extensions.c b/src/mesa/drivers/dri/intel/intel_extensions.c
index 556a4195bd..febc1d4f85 100644
--- a/src/mesa/drivers/dri/intel/intel_extensions.c
+++ b/src/mesa/drivers/dri/intel/intel_extensions.c
@@ -25,12 +25,15 @@
*
**************************************************************************/
+#include "main/mfeatures.h"
+
#include "intel_chipset.h"
#include "intel_context.h"
#include "intel_extensions.h"
#include "utils.h"
+#define need_GL_ARB_ES2_compatibility
#define need_GL_ARB_draw_elements_base_vertex
#define need_GL_ARB_framebuffer_object
#define need_GL_ARB_map_buffer_range
@@ -78,8 +81,10 @@
* i965_dri.
*/
static const struct dri_extension card_extensions[] = {
+ { "GL_ARB_ES2_compatibility", GL_ARB_ES2_compatibility_functions },
{ "GL_ARB_draw_elements_base_vertex", GL_ARB_draw_elements_base_vertex_functions },
{ "GL_ARB_explicit_attrib_location", NULL },
+ { "GL_ARB_framebuffer_object", GL_ARB_framebuffer_object_functions},
{ "GL_ARB_half_float_pixel", NULL },
{ "GL_ARB_map_buffer_range", GL_ARB_map_buffer_range_functions },
{ "GL_ARB_multitexture", NULL },
@@ -161,7 +166,6 @@ static const struct dri_extension brw_extensions[] = {
{ "GL_ARB_fragment_program", NULL },
{ "GL_ARB_fragment_program_shadow", NULL },
{ "GL_ARB_fragment_shader", NULL },
- { "GL_ARB_framebuffer_object", GL_ARB_framebuffer_object_functions},
{ "GL_ARB_half_float_vertex", NULL },
{ "GL_ARB_occlusion_query", GL_ARB_occlusion_query_functions },
{ "GL_ARB_point_sprite", NULL },
@@ -171,9 +175,11 @@ static const struct dri_extension brw_extensions[] = {
{ "GL_ARB_texture_non_power_of_two", NULL },
{ "GL_ARB_texture_rg", NULL },
{ "GL_EXT_draw_buffers2", GL_EXT_draw_buffers2_functions },
+ { "GL_EXT_framebuffer_sRGB", NULL },
{ "GL_EXT_shadow_funcs", NULL },
{ "GL_EXT_stencil_two_side", GL_EXT_stencil_two_side_functions },
{ "GL_EXT_texture_sRGB", NULL },
+ { "GL_EXT_texture_sRGB_decode", NULL },
{ "GL_EXT_texture_swizzle", NULL },
{ "GL_EXT_vertex_array_bgra", NULL },
{ "GL_ATI_envmap_bumpmap", GL_ATI_envmap_bumpmap_functions },
diff --git a/src/mesa/drivers/dri/intel/intel_extensions_es2.c b/src/mesa/drivers/dri/intel/intel_extensions_es2.c
index 54b0517deb..747ddf7644 100644
--- a/src/mesa/drivers/dri/intel/intel_extensions_es2.c
+++ b/src/mesa/drivers/dri/intel/intel_extensions_es2.c
@@ -26,6 +26,7 @@
**************************************************************************/
#include "main/extensions.h"
+#include "main/mfeatures.h"
#include "intel_extensions.h"
@@ -62,6 +63,7 @@ static const char *es2_extensions[] = {
"GL_EXT_blend_minmax",
"GL_EXT_blend_subtract",
"GL_EXT_stencil_wrap",
+ "GL_NV_blend_square",
/* Optional GLES2 */
"GL_ARB_framebuffer_object",
@@ -95,9 +97,22 @@ intelInitExtensionsES1(struct gl_context *ctx)
_mesa_enable_extension(ctx, "GL_ARB_point_parameters");
_mesa_enable_extension(ctx, "GL_OES_draw_texture");
+
+ _mesa_enable_extension(ctx, "GL_OES_point_sprite");
}
/**
+ * \brief Extensions to disable.
+ *
+ * These extensions must be manually disabled because they may have been
+ * enabled by default.
+ */
+static const char* es2_extensions_disabled[] = {
+ "GL_OES_standard_derivatives",
+ NULL,
+};
+
+/**
* Initializes potential list of extensions if ctx == NULL, or actually enables
* extensions for a context.
*/
@@ -111,4 +126,6 @@ intelInitExtensionsES2(struct gl_context *ctx)
for (i = 0; es2_extensions[i]; i++)
_mesa_enable_extension(ctx, es2_extensions[i]);
+ for (i = 0; es2_extensions_disabled[i]; i++)
+ _mesa_disable_extension(ctx, es2_extensions_disabled[i]);
}
diff --git a/src/mesa/drivers/dri/intel/intel_fbo.c b/src/mesa/drivers/dri/intel/intel_fbo.c
index 18e796a118..8b57eb19f5 100644
--- a/src/mesa/drivers/dri/intel/intel_fbo.c
+++ b/src/mesa/drivers/dri/intel/intel_fbo.c
@@ -28,11 +28,13 @@
#include "main/imports.h"
#include "main/macros.h"
+#include "main/mfeatures.h"
#include "main/mtypes.h"
#include "main/fbobject.h"
#include "main/framebuffer.h"
#include "main/renderbuffer.h"
#include "main/context.h"
+#include "main/teximage.h"
#include "main/texrender.h"
#include "drivers/common/meta.h"
@@ -42,6 +44,11 @@
#include "intel_fbo.h"
#include "intel_mipmap_tree.h"
#include "intel_regions.h"
+#include "intel_tex.h"
+#include "intel_span.h"
+#ifndef I915
+#include "brw_context.h"
+#endif
#define FILE_DEBUG_FLAG DEBUG_FBO
@@ -107,79 +114,27 @@ intel_alloc_renderbuffer_storage(struct gl_context * ctx, struct gl_renderbuffer
ASSERT(rb->Name != 0);
switch (internalFormat) {
- case GL_RED:
- case GL_R8:
- rb->Format = MESA_FORMAT_R8;
- rb->DataType = GL_UNSIGNED_BYTE;
- break;
- case GL_R16:
- rb->Format = MESA_FORMAT_R16;
- rb->DataType = GL_UNSIGNED_SHORT;
- break;
- case GL_RG:
- case GL_RG8:
- rb->Format = MESA_FORMAT_RG88;
- rb->DataType = GL_UNSIGNED_BYTE;
- break;
- case GL_RG16:
- rb->Format = MESA_FORMAT_RG1616;
- rb->DataType = GL_UNSIGNED_SHORT;
- break;
- case GL_R3_G3_B2:
- case GL_RGB4:
- case GL_RGB5:
- rb->Format = MESA_FORMAT_RGB565;
- rb->DataType = GL_UNSIGNED_BYTE;
- break;
- case GL_RGB:
- case GL_RGB8:
- case GL_RGB10:
- case GL_RGB12:
- case GL_RGB16:
- rb->Format = MESA_FORMAT_XRGB8888;
- rb->DataType = GL_UNSIGNED_BYTE;
- break;
- case GL_RGBA:
- case GL_RGBA2:
- case GL_RGBA4:
- case GL_RGB5_A1:
- case GL_RGBA8:
- case GL_RGB10_A2:
- case GL_RGBA12:
- case GL_RGBA16:
- rb->Format = MESA_FORMAT_ARGB8888;
- rb->DataType = GL_UNSIGNED_BYTE;
- break;
- case GL_ALPHA:
- case GL_ALPHA8:
- rb->Format = MESA_FORMAT_A8;
- rb->DataType = GL_UNSIGNED_BYTE;
- break;
- case GL_DEPTH_COMPONENT16:
- rb->Format = MESA_FORMAT_Z16;
- rb->DataType = GL_UNSIGNED_SHORT;
+ default:
+ /* Use the same format-choice logic as for textures.
+ * Renderbuffers aren't any different from textures for us,
+ * except they're less useful because you can't texture with
+ * them.
+ */
+ rb->Format = intel->ctx.Driver.ChooseTextureFormat(ctx, internalFormat,
+ GL_NONE, GL_NONE);
break;
case GL_STENCIL_INDEX:
case GL_STENCIL_INDEX1_EXT:
case GL_STENCIL_INDEX4_EXT:
case GL_STENCIL_INDEX8_EXT:
case GL_STENCIL_INDEX16_EXT:
- case GL_DEPTH_COMPONENT:
- case GL_DEPTH_COMPONENT24:
- case GL_DEPTH_COMPONENT32:
- case GL_DEPTH_STENCIL_EXT:
- case GL_DEPTH24_STENCIL8_EXT:
- /* alloc a depth+stencil buffer */
+ /* These aren't actual texture formats, so force them here. */
rb->Format = MESA_FORMAT_S8_Z24;
- rb->DataType = GL_UNSIGNED_INT_24_8_EXT;
break;
- default:
- _mesa_problem(ctx,
- "Unexpected format in intel_alloc_renderbuffer_storage");
- return GL_FALSE;
}
rb->_BaseFormat = _mesa_base_fbo_format(ctx, internalFormat);
+ rb->DataType = intel_mesa_format_to_rb_datatype(rb->Format);
cpp = _mesa_get_format_bytes(rb->Format);
intel_flush(ctx);
@@ -195,10 +150,15 @@ intel_alloc_renderbuffer_storage(struct gl_context * ctx, struct gl_renderbuffer
DBG("Allocating %d x %d Intel RBO\n", width, height);
tiling = I915_TILING_NONE;
+ if (intel->use_texture_tiling) {
+ GLenum base_format = _mesa_get_format_base_format(rb->Format);
- /* Gen6 requires depth must be tiling */
- if (intel->gen >= 6 && rb->Format == MESA_FORMAT_S8_Z24)
- tiling = I915_TILING_Y;
+ if (intel->gen >= 4 && (base_format == GL_DEPTH_COMPONENT ||
+ base_format == GL_DEPTH_STENCIL))
+ tiling = I915_TILING_Y;
+ else
+ tiling = I915_TILING_X;
+ }
irb->region = intel_region_alloc(intel->intelScreen, tiling, cpp,
width, height, GL_TRUE);
@@ -334,53 +294,10 @@ intel_create_renderbuffer(gl_format format)
_mesa_init_renderbuffer(&irb->Base, 0);
irb->Base.ClassID = INTEL_RB_CLASS;
-
- switch (format) {
- case MESA_FORMAT_RGB565:
- irb->Base._BaseFormat = GL_RGB;
- irb->Base.DataType = GL_UNSIGNED_BYTE;
- break;
- case MESA_FORMAT_XRGB8888:
- irb->Base._BaseFormat = GL_RGB;
- irb->Base.DataType = GL_UNSIGNED_BYTE;
- break;
- case MESA_FORMAT_ARGB8888:
- irb->Base._BaseFormat = GL_RGBA;
- irb->Base.DataType = GL_UNSIGNED_BYTE;
- break;
- case MESA_FORMAT_Z16:
- irb->Base._BaseFormat = GL_DEPTH_COMPONENT;
- irb->Base.DataType = GL_UNSIGNED_SHORT;
- break;
- case MESA_FORMAT_X8_Z24:
- irb->Base._BaseFormat = GL_DEPTH_COMPONENT;
- irb->Base.DataType = GL_UNSIGNED_INT;
- break;
- case MESA_FORMAT_S8_Z24:
- irb->Base._BaseFormat = GL_DEPTH_STENCIL;
- irb->Base.DataType = GL_UNSIGNED_INT_24_8_EXT;
- break;
- case MESA_FORMAT_A8:
- irb->Base._BaseFormat = GL_ALPHA;
- irb->Base.DataType = GL_UNSIGNED_BYTE;
- break;
- case MESA_FORMAT_R8:
- irb->Base._BaseFormat = GL_RED;
- irb->Base.DataType = GL_UNSIGNED_BYTE;
- break;
- case MESA_FORMAT_RG88:
- irb->Base._BaseFormat = GL_RG;
- irb->Base.DataType = GL_UNSIGNED_BYTE;
- break;
- default:
- _mesa_problem(NULL,
- "Unexpected intFormat in intel_create_renderbuffer");
- free(irb);
- return NULL;
- }
-
+ irb->Base._BaseFormat = _mesa_get_format_base_format(format);
irb->Base.Format = format;
irb->Base.InternalFormat = irb->Base._BaseFormat;
+ irb->Base.DataType = intel_mesa_format_to_rb_datatype(format);
/* intel-specific methods */
irb->Base.Delete = intel_delete_renderbuffer;
@@ -457,70 +374,16 @@ static GLboolean
intel_update_wrapper(struct gl_context *ctx, struct intel_renderbuffer *irb,
struct gl_texture_image *texImage)
{
- if (texImage->TexFormat == MESA_FORMAT_ARGB8888) {
- irb->Base.DataType = GL_UNSIGNED_BYTE;
- DBG("Render to RGBA8 texture OK\n");
- }
- else if (texImage->TexFormat == MESA_FORMAT_XRGB8888) {
- irb->Base.DataType = GL_UNSIGNED_BYTE;
- DBG("Render to XGBA8 texture OK\n");
- }
-#ifndef I915
- else if (texImage->TexFormat == MESA_FORMAT_SARGB8) {
- irb->Base.DataType = GL_UNSIGNED_BYTE;
- DBG("Render to SARGB8 texture OK\n");
- }
-#endif
- else if (texImage->TexFormat == MESA_FORMAT_RGB565) {
- irb->Base.DataType = GL_UNSIGNED_BYTE;
- DBG("Render to RGB5 texture OK\n");
- }
- else if (texImage->TexFormat == MESA_FORMAT_ARGB1555) {
- irb->Base.DataType = GL_UNSIGNED_BYTE;
- DBG("Render to ARGB1555 texture OK\n");
- }
- else if (texImage->TexFormat == MESA_FORMAT_ARGB4444) {
- irb->Base.DataType = GL_UNSIGNED_BYTE;
- DBG("Render to ARGB4444 texture OK\n");
- }
-#ifndef I915
- else if (texImage->TexFormat == MESA_FORMAT_A8) {
- irb->Base.DataType = GL_UNSIGNED_BYTE;
- DBG("Render to A8 texture OK\n");
- }
- else if (texImage->TexFormat == MESA_FORMAT_R8) {
- irb->Base.DataType = GL_UNSIGNED_BYTE;
- DBG("Render to R8 texture OK\n");
- }
- else if (texImage->TexFormat == MESA_FORMAT_RG88) {
- irb->Base.DataType = GL_UNSIGNED_BYTE;
- DBG("Render to RG88 texture OK\n");
- }
- else if (texImage->TexFormat == MESA_FORMAT_R16) {
- irb->Base.DataType = GL_UNSIGNED_SHORT;
- DBG("Render to R8 texture OK\n");
- }
- else if (texImage->TexFormat == MESA_FORMAT_RG1616) {
- irb->Base.DataType = GL_UNSIGNED_SHORT;
- DBG("Render to RG88 texture OK\n");
- }
-#endif
- else if (texImage->TexFormat == MESA_FORMAT_Z16) {
- irb->Base.DataType = GL_UNSIGNED_SHORT;
- DBG("Render to DEPTH16 texture OK\n");
- }
- else if (texImage->TexFormat == MESA_FORMAT_S8_Z24) {
- irb->Base.DataType = GL_UNSIGNED_INT_24_8_EXT;
- DBG("Render to DEPTH_STENCIL texture OK\n");
- }
- else {
+ if (!intel_span_supports_format(texImage->TexFormat)) {
DBG("Render to texture BAD FORMAT %s\n",
_mesa_get_format_name(texImage->TexFormat));
return GL_FALSE;
+ } else {
+ DBG("Render to texture %s\n", _mesa_get_format_name(texImage->TexFormat));
}
irb->Base.Format = texImage->TexFormat;
-
+ irb->Base.DataType = intel_mesa_format_to_rb_datatype(texImage->TexFormat);
irb->Base.InternalFormat = texImage->InternalFormat;
irb->Base._BaseFormat = _mesa_base_fbo_format(ctx, irb->Base.InternalFormat);
irb->Base.Width = texImage->Width;
@@ -562,6 +425,24 @@ intel_wrap_texture(struct gl_context * ctx, struct gl_texture_image *texImage)
return irb;
}
+static void
+intel_set_draw_offset_for_image(struct intel_texture_image *intel_image,
+ int zoffset)
+{
+ struct intel_mipmap_tree *mt = intel_image->mt;
+ unsigned int dst_x, dst_y;
+
+ /* compute offset of the particular 2D image within the texture region */
+ intel_miptree_get_image_offset(intel_image->mt,
+ intel_image->level,
+ intel_image->face,
+ zoffset,
+ &dst_x, &dst_y);
+
+ mt->region->draw_offset = (dst_y * mt->region->pitch + dst_x) * mt->cpp;
+ mt->region->draw_x = dst_x;
+ mt->region->draw_y = dst_y;
+}
/**
* Called by glFramebufferTexture[123]DEXT() (and other places) to
@@ -578,7 +459,6 @@ intel_render_texture(struct gl_context * ctx,
= att->Texture->Image[att->CubeMapFace][att->TextureLevel];
struct intel_renderbuffer *irb = intel_renderbuffer(att->Renderbuffer);
struct intel_texture_image *intel_image;
- GLuint dst_x, dst_y;
(void) fb;
@@ -624,19 +504,53 @@ intel_render_texture(struct gl_context * ctx,
intel_region_reference(&irb->region, intel_image->mt->region);
}
- /* compute offset of the particular 2D image within the texture region */
- intel_miptree_get_image_offset(intel_image->mt,
- att->TextureLevel,
- att->CubeMapFace,
- att->Zoffset,
- &dst_x, &dst_y);
-
- intel_image->mt->region->draw_offset = (dst_y * intel_image->mt->region->pitch +
- dst_x) * intel_image->mt->cpp;
- intel_image->mt->region->draw_x = dst_x;
- intel_image->mt->region->draw_y = dst_y;
+ intel_set_draw_offset_for_image(intel_image, att->Zoffset);
intel_image->used_as_render_target = GL_TRUE;
+#ifndef I915
+ if (!brw_context(ctx)->has_surface_tile_offset &&
+ (intel_image->mt->region->draw_offset & 4095) != 0) {
+ /* Original gen4 hardware couldn't draw to a non-tile-aligned
+ * destination in a miptree unless you actually setup your
+ * renderbuffer as a miptree and used the fragile
+ * lod/array_index/etc. controls to select the image. So,
+ * instead, we just make a new single-level miptree and render
+ * into that.
+ */
+ struct intel_context *intel = intel_context(ctx);
+ struct intel_mipmap_tree *old_mt = intel_image->mt;
+ struct intel_mipmap_tree *new_mt;
+ int comp_byte = 0, texel_bytes;
+
+ if (_mesa_is_format_compressed(intel_image->base.TexFormat))
+ comp_byte = intel_compressed_num_bytes(intel_image->base.TexFormat);
+
+ texel_bytes = _mesa_get_format_bytes(intel_image->base.TexFormat);
+
+ new_mt = intel_miptree_create(intel, newImage->TexObject->Target,
+ intel_image->base._BaseFormat,
+ intel_image->base.InternalFormat,
+ intel_image->level,
+ intel_image->level,
+ intel_image->base.Width,
+ intel_image->base.Height,
+ intel_image->base.Depth,
+ texel_bytes, comp_byte, GL_TRUE);
+
+ intel_miptree_image_copy(intel,
+ new_mt,
+ intel_image->face,
+ intel_image->level,
+ old_mt);
+
+ intel_miptree_release(intel, &intel_image->mt);
+ intel_image->mt = new_mt;
+ intel_set_draw_offset_for_image(intel_image, att->Zoffset);
+
+ intel_region_release(&irb->region);
+ intel_region_reference(&irb->region, intel_image->mt->region);
+ }
+#endif
/* update drawing region, etc */
intel_draw_buffer(ctx, fb);
}
@@ -659,14 +573,15 @@ intel_finish_render_texture(struct gl_context * ctx,
_glthread_GetID(), att->Texture->Name);
/* Flag that this image may now be validated into the object's miptree. */
- intel_image->used_as_render_target = GL_FALSE;
+ if (intel_image)
+ intel_image->used_as_render_target = GL_FALSE;
/* Since we've (probably) rendered to the texture and will (likely) use
* it in the texture domain later on in this batchbuffer, flush the
* batch. Once again, we wish for a domain tracker in libdrm to cover
* usage inside of a batchbuffer like GEM does in the kernel.
*/
- intel_batchbuffer_emit_mi_flush(intel->batch);
+ intel_batchbuffer_emit_mi_flush(intel);
}
/**
@@ -675,6 +590,7 @@ intel_finish_render_texture(struct gl_context * ctx,
static void
intel_validate_framebuffer(struct gl_context *ctx, struct gl_framebuffer *fb)
{
+ struct intel_context *intel = intel_context(ctx);
const struct intel_renderbuffer *depthRb =
intel_get_renderbuffer(fb, BUFFER_DEPTH);
const struct intel_renderbuffer *stencilRb =
@@ -682,10 +598,10 @@ intel_validate_framebuffer(struct gl_context *ctx, struct gl_framebuffer *fb)
int i;
if (depthRb && stencilRb && stencilRb != depthRb) {
- if (ctx->DrawBuffer->Attachment[BUFFER_DEPTH].Type == GL_TEXTURE &&
- ctx->DrawBuffer->Attachment[BUFFER_STENCIL].Type == GL_TEXTURE &&
- (ctx->DrawBuffer->Attachment[BUFFER_DEPTH].Texture->Name ==
- ctx->DrawBuffer->Attachment[BUFFER_STENCIL].Texture->Name)) {
+ if (fb->Attachment[BUFFER_DEPTH].Type == GL_TEXTURE &&
+ fb->Attachment[BUFFER_STENCIL].Type == GL_TEXTURE &&
+ (fb->Attachment[BUFFER_DEPTH].Texture->Name ==
+ fb->Attachment[BUFFER_STENCIL].Texture->Name)) {
/* OK */
} else {
/* we only support combined depth/stencil buffers, not separate
@@ -698,40 +614,118 @@ intel_validate_framebuffer(struct gl_context *ctx, struct gl_framebuffer *fb)
}
}
- for (i = 0; i < ctx->Const.MaxDrawBuffers; i++) {
- struct gl_renderbuffer *rb = ctx->DrawBuffer->_ColorDrawBuffers[i];
- struct intel_renderbuffer *irb = intel_renderbuffer(rb);
+ for (i = 0; i < Elements(fb->Attachment); i++) {
+ struct gl_renderbuffer *rb;
+ struct intel_renderbuffer *irb;
- if (rb == NULL)
+ if (fb->Attachment[i].Type == GL_NONE)
continue;
+ /* A supported attachment will have a Renderbuffer set either
+ * from being a Renderbuffer or being a texture that got the
+ * intel_wrap_texture() treatment.
+ */
+ rb = fb->Attachment[i].Renderbuffer;
+ if (rb == NULL) {
+ DBG("attachment without renderbuffer\n");
+ fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED_EXT;
+ continue;
+ }
+
+ irb = intel_renderbuffer(rb);
if (irb == NULL) {
DBG("software rendering renderbuffer\n");
fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED_EXT;
continue;
}
- switch (irb->Base.Format) {
- case MESA_FORMAT_ARGB8888:
- case MESA_FORMAT_XRGB8888:
- case MESA_FORMAT_RGB565:
- case MESA_FORMAT_ARGB1555:
- case MESA_FORMAT_ARGB4444:
-#ifndef I915
- case MESA_FORMAT_SARGB8:
- case MESA_FORMAT_A8:
- case MESA_FORMAT_R8:
- case MESA_FORMAT_R16:
- case MESA_FORMAT_RG88:
- case MESA_FORMAT_RG1616:
-#endif
- break;
- default:
+ if (!intel_span_supports_format(irb->Base.Format) ||
+ !intel->vtbl.render_target_supported(irb->Base.Format)) {
+ DBG("Unsupported texture/renderbuffer format attached: %s\n",
+ _mesa_get_format_name(irb->Base.Format));
fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED_EXT;
}
}
}
+/**
+ * Try to do a glBlitFramebuffer using glCopyTexSubImage2D
+ * We can do this when the dst renderbuffer is actually a texture and
+ * there is no scaling, mirroring or scissoring.
+ *
+ * \return new buffer mask indicating the buffers left to blit using the
+ * normal path.
+ */
+static GLbitfield
+intel_blit_framebuffer_copy_tex_sub_image(struct gl_context *ctx,
+ GLint srcX0, GLint srcY0,
+ GLint srcX1, GLint srcY1,
+ GLint dstX0, GLint dstY0,
+ GLint dstX1, GLint dstY1,
+ GLbitfield mask, GLenum filter)
+{
+ if (mask & GL_COLOR_BUFFER_BIT) {
+ const struct gl_framebuffer *drawFb = ctx->DrawBuffer;
+ const struct gl_framebuffer *readFb = ctx->ReadBuffer;
+ const struct gl_renderbuffer_attachment *drawAtt =
+ &drawFb->Attachment[drawFb->_ColorDrawBufferIndexes[0]];
+
+ /* If the source and destination are the same size with no
+ mirroring, the rectangles are within the size of the
+ texture and there is no scissor then we can use
+ glCopyTexSubimage2D to implement the blit. This will end
+ up as a fast hardware blit on some drivers */
+ if (drawAtt && drawAtt->Texture &&
+ srcX0 - srcX1 == dstX0 - dstX1 &&
+ srcY0 - srcY1 == dstY0 - dstY1 &&
+ srcX1 >= srcX0 &&
+ srcY1 >= srcY0 &&
+ srcX0 >= 0 && srcX1 <= readFb->Width &&
+ srcY0 >= 0 && srcY1 <= readFb->Height &&
+ dstX0 >= 0 && dstX1 <= drawFb->Width &&
+ dstY0 >= 0 && dstY1 <= drawFb->Height &&
+ !ctx->Scissor.Enabled) {
+ const struct gl_texture_object *texObj = drawAtt->Texture;
+ const GLuint dstLevel = drawAtt->TextureLevel;
+ const GLenum target = texObj->Target;
+
+ struct gl_texture_image *texImage =
+ _mesa_select_tex_image(ctx, texObj, target, dstLevel);
+ GLenum internalFormat = texImage->InternalFormat;
+
+ if (intel_copy_texsubimage(intel_context(ctx), target,
+ intel_texture_image(texImage),
+ internalFormat,
+ dstX0, dstY0,
+ srcX0, srcY0,
+ srcX1 - srcX0, /* width */
+ srcY1 - srcY0))
+ mask &= ~GL_COLOR_BUFFER_BIT;
+ }
+ }
+
+ return mask;
+}
+
+static void
+intel_blit_framebuffer(struct gl_context *ctx,
+ GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
+ GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
+ GLbitfield mask, GLenum filter)
+{
+ /* Try faster, glCopyTexSubImage2D approach first which uses the BLT. */
+ mask = intel_blit_framebuffer_copy_tex_sub_image(ctx,
+ srcX0, srcY0, srcX1, srcY1,
+ dstX0, dstY0, dstX1, dstY1,
+ mask, filter);
+ if (mask == 0x0)
+ return;
+
+ _mesa_meta_BlitFramebuffer(ctx,
+ srcX0, srcY0, srcX1, srcY1,
+ dstX0, dstY0, dstX1, dstY1,
+ mask, filter);
+}
/**
* Do one-time context initializations related to GL_EXT_framebuffer_object.
@@ -748,7 +742,7 @@ intel_fbo_init(struct intel_context *intel)
intel->ctx.Driver.FinishRenderTexture = intel_finish_render_texture;
intel->ctx.Driver.ResizeBuffers = intel_resize_buffers;
intel->ctx.Driver.ValidateFramebuffer = intel_validate_framebuffer;
- intel->ctx.Driver.BlitFramebuffer = _mesa_meta_BlitFramebuffer;
+ intel->ctx.Driver.BlitFramebuffer = intel_blit_framebuffer;
#if FEATURE_OES_EGL_image
intel->ctx.Driver.EGLImageTargetRenderbufferStorage =
diff --git a/src/mesa/drivers/dri/intel/intel_mipmap_tree.c b/src/mesa/drivers/dri/intel/intel_mipmap_tree.c
index 9c4e5c5ee8..a3409274fb 100644
--- a/src/mesa/drivers/dri/intel/intel_mipmap_tree.c
+++ b/src/mesa/drivers/dri/intel/intel_mipmap_tree.c
@@ -157,8 +157,6 @@ struct intel_mipmap_tree *
intel_miptree_create_for_region(struct intel_context *intel,
GLenum target,
GLenum internal_format,
- GLuint first_level,
- GLuint last_level,
struct intel_region *region,
GLuint depth0,
GLuint compress_byte)
@@ -166,7 +164,7 @@ intel_miptree_create_for_region(struct intel_context *intel,
struct intel_mipmap_tree *mt;
mt = intel_miptree_create_internal(intel, target, internal_format,
- first_level, last_level,
+ 0, 0,
region->width, region->height, 1,
region->cpp, compress_byte,
I915_TILING_NONE);
diff --git a/src/mesa/drivers/dri/intel/intel_mipmap_tree.h b/src/mesa/drivers/dri/intel/intel_mipmap_tree.h
index 21db2f4d3b..760a8bce60 100644
--- a/src/mesa/drivers/dri/intel/intel_mipmap_tree.h
+++ b/src/mesa/drivers/dri/intel/intel_mipmap_tree.h
@@ -137,8 +137,6 @@ struct intel_mipmap_tree *
intel_miptree_create_for_region(struct intel_context *intel,
GLenum target,
GLenum internal_format,
- GLuint first_level,
- GLuint last_level,
struct intel_region *region,
GLuint depth0,
GLuint compress_byte);
diff --git a/src/mesa/drivers/dri/intel/intel_pixel.c b/src/mesa/drivers/dri/intel/intel_pixel.c
index d5c35775ce..f97256e59b 100644
--- a/src/mesa/drivers/dri/intel/intel_pixel.c
+++ b/src/mesa/drivers/dri/intel/intel_pixel.c
@@ -66,12 +66,12 @@ intel_check_blit_fragment_ops(struct gl_context * ctx, GLboolean src_alpha_is_on
}
if (ctx->Color.BlendEnabled &&
- (effective_func(ctx->Color.BlendSrcRGB, src_alpha_is_one) != GL_ONE ||
- effective_func(ctx->Color.BlendDstRGB, src_alpha_is_one) != GL_ZERO ||
- ctx->Color.BlendEquationRGB != GL_FUNC_ADD ||
- effective_func(ctx->Color.BlendSrcA, src_alpha_is_one) != GL_ONE ||
- effective_func(ctx->Color.BlendDstA, src_alpha_is_one) != GL_ZERO ||
- ctx->Color.BlendEquationA != GL_FUNC_ADD)) {
+ (effective_func(ctx->Color.Blend[0].SrcRGB, src_alpha_is_one) != GL_ONE ||
+ effective_func(ctx->Color.Blend[0].DstRGB, src_alpha_is_one) != GL_ZERO ||
+ ctx->Color.Blend[0].EquationRGB != GL_FUNC_ADD ||
+ effective_func(ctx->Color.Blend[0].SrcA, src_alpha_is_one) != GL_ONE ||
+ effective_func(ctx->Color.Blend[0].DstA, src_alpha_is_one) != GL_ZERO ||
+ ctx->Color.Blend[0].EquationA != GL_FUNC_ADD)) {
DBG("fallback due to blend\n");
return GL_FALSE;
}
diff --git a/src/mesa/drivers/dri/intel/intel_pixel_bitmap.c b/src/mesa/drivers/dri/intel/intel_pixel_bitmap.c
index e7356a6da0..43cdd0d2ba 100644
--- a/src/mesa/drivers/dri/intel/intel_pixel_bitmap.c
+++ b/src/mesa/drivers/dri/intel/intel_pixel_bitmap.c
@@ -31,6 +31,7 @@
#include "main/colormac.h"
#include "main/mtypes.h"
#include "main/macros.h"
+#include "main/pbo.h"
#include "main/bufferobj.h"
#include "main/state.h"
#include "main/texobj.h"
@@ -207,7 +208,7 @@ do_blit_bitmap( struct gl_context *ctx,
COPY_4V(tmpColor, ctx->Current.RasterColor);
- if (NEED_SECONDARY_COLOR(ctx)) {
+ if (_mesa_need_secondary_color(ctx)) {
ADD_3V(tmpColor, tmpColor, ctx->Current.RasterSecondaryColor);
}
@@ -285,7 +286,7 @@ do_blit_bitmap( struct gl_context *ctx,
out:
if (unlikely(INTEL_DEBUG & DEBUG_SYNC))
- intel_batchbuffer_flush(intel->batch);
+ intel_batchbuffer_flush(intel);
if (_mesa_is_bufferobj(unpack->BufferObj)) {
/* done with PBO so unmap it now */
diff --git a/src/mesa/drivers/dri/intel/intel_pixel_read.c b/src/mesa/drivers/dri/intel/intel_pixel_read.c
index 54da29236d..b2e77c7986 100644
--- a/src/mesa/drivers/dri/intel/intel_pixel_read.c
+++ b/src/mesa/drivers/dri/intel/intel_pixel_read.c
@@ -80,6 +80,7 @@ do_blit_readpixels(struct gl_context * ctx,
drm_intel_bo *dst_buffer;
GLboolean all;
GLint dst_x, dst_y;
+ GLuint dirty;
DBG("%s\n", __FUNCTION__);
@@ -129,7 +130,9 @@ do_blit_readpixels(struct gl_context * ctx,
return GL_TRUE;
}
+ dirty = intel->front_buffer_dirty;
intel_prepare_render(intel);
+ intel->front_buffer_dirty = dirty;
all = (width * height * src->cpp == dst->Base.Size &&
x == 0 && dst_offset == 0);
@@ -138,8 +141,8 @@ do_blit_readpixels(struct gl_context * ctx,
dst_y = 0;
dst_buffer = intel_bufferobj_buffer(intel, dst,
- all ? INTEL_WRITE_FULL :
- INTEL_WRITE_PART);
+ all ? INTEL_WRITE_FULL :
+ INTEL_WRITE_PART);
if (ctx->ReadBuffer->Name == 0)
y = ctx->ReadBuffer->Height - (y + height);
@@ -171,6 +174,10 @@ intelReadPixels(struct gl_context * ctx,
DBG("%s\n", __FUNCTION__);
+ if (do_blit_readpixels
+ (ctx, x, y, width, height, format, type, pack, pixels))
+ return;
+
intel_flush(ctx);
/* glReadPixels() wont dirty the front buffer, so reset the dirty
@@ -179,10 +186,6 @@ intelReadPixels(struct gl_context * ctx,
intel_prepare_render(intel);
intel->front_buffer_dirty = dirty;
- if (do_blit_readpixels
- (ctx, x, y, width, height, format, type, pack, pixels))
- return;
-
fallback_debug("%s: fallback to swrast\n", __FUNCTION__);
/* Update Mesa state before calling down into _swrast_ReadPixels, as
diff --git a/src/mesa/drivers/dri/intel/intel_reg.h b/src/mesa/drivers/dri/intel/intel_reg.h
index 955b100b21..5258699d3f 100644
--- a/src/mesa/drivers/dri/intel/intel_reg.h
+++ b/src/mesa/drivers/dri/intel/intel_reg.h
@@ -37,6 +37,8 @@
#define FLUSH_MAP_CACHE (1 << 0)
#define INHIBIT_FLUSH_RENDER_CACHE (1 << 2)
+#define MI_FLUSH_DW (CMD_MI | (0x26 << 23) | 2)
+
/* Stalls command execution waiting for the given events to have occurred. */
#define MI_WAIT_FOR_EVENT (CMD_MI | (0x3 << 23))
#define MI_WAIT_FOR_PLANE_B_FLIP (1<<6)
diff --git a/src/mesa/drivers/dri/intel/intel_regions.c b/src/mesa/drivers/dri/intel/intel_regions.c
index e87e29462c..a4da1ce4fa 100644
--- a/src/mesa/drivers/dri/intel/intel_regions.c
+++ b/src/mesa/drivers/dri/intel/intel_regions.c
@@ -149,11 +149,6 @@ intel_region_alloc_internal(struct intel_screen *screen,
{
struct intel_region *region;
- if (buffer == NULL) {
- _DBG("%s <-- NULL\n", __FUNCTION__);
- return NULL;
- }
-
region = calloc(sizeof(*region), 1);
if (region == NULL)
return region;
@@ -180,6 +175,7 @@ intel_region_alloc(struct intel_screen *screen,
drm_intel_bo *buffer;
unsigned long flags = 0;
unsigned long aligned_pitch;
+ struct intel_region *region;
if (expect_accelerated_upload)
flags |= BO_ALLOC_FOR_RENDER;
@@ -187,9 +183,17 @@ intel_region_alloc(struct intel_screen *screen,
buffer = drm_intel_bo_alloc_tiled(screen->bufmgr, "region",
width, height, cpp,
&tiling, &aligned_pitch, flags);
+ if (buffer == NULL)
+ return NULL;
- return intel_region_alloc_internal(screen, cpp, width, height,
- aligned_pitch / cpp, tiling, buffer);
+ region = intel_region_alloc_internal(screen, cpp, width, height,
+ aligned_pitch / cpp, tiling, buffer);
+ if (region == NULL) {
+ drm_intel_bo_unreference(buffer);
+ return NULL;
+ }
+
+ return region;
}
GLboolean
@@ -491,7 +495,7 @@ intel_region_cow(struct intel_context *intel, struct intel_region *region)
assert(region->cpp * region->pitch * region->height == pbo->Base.Size);
- _DBG("%s %p (%d bytes)\n", __FUNCTION__, region, pbo->Base.Size);
+ _DBG("%s %p (%d bytes)\n", __FUNCTION__, region, (int)pbo->Base.Size);
/* Now blit from the texture buffer to the new buffer:
*/
diff --git a/src/mesa/drivers/dri/intel/intel_screen.c b/src/mesa/drivers/dri/intel/intel_screen.c
index e5b6c9f0e4..c8cff0147e 100644
--- a/src/mesa/drivers/dri/intel/intel_screen.c
+++ b/src/mesa/drivers/dri/intel/intel_screen.c
@@ -25,29 +25,18 @@
*
**************************************************************************/
+#include <errno.h>
#include "main/glheader.h"
#include "main/context.h"
#include "main/framebuffer.h"
#include "main/renderbuffer.h"
#include "main/hash.h"
#include "main/fbobject.h"
+#include "main/mfeatures.h"
#include "utils.h"
#include "xmlpool.h"
-#include "intel_batchbuffer.h"
-#include "intel_buffers.h"
-#include "intel_bufmgr.h"
-#include "intel_chipset.h"
-#include "intel_fbo.h"
-#include "intel_screen.h"
-#include "intel_tex.h"
-#include "intel_regions.h"
-
-#include "i915_drm.h"
-
-#define DRI_CONF_TEXTURE_TILING(def) \
-
PUBLIC const char __driConfigOptions[] =
DRI_CONF_BEGIN
DRI_CONF_SECTION_PERFORMANCE
@@ -92,6 +81,17 @@ DRI_CONF_END;
const GLuint __driNConfigOptions = 11;
+#include "intel_batchbuffer.h"
+#include "intel_buffers.h"
+#include "intel_bufmgr.h"
+#include "intel_chipset.h"
+#include "intel_fbo.h"
+#include "intel_screen.h"
+#include "intel_tex.h"
+#include "intel_regions.h"
+
+#include "i915_drm.h"
+
#ifdef USE_NEW_INTERFACE
static PFNGLXCREATECONTEXTMODES create_context_modes = NULL;
#endif /*USE_NEW_INTERFACE */
@@ -105,15 +105,16 @@ static const __DRItexBufferExtension intelTexBufferExtension = {
static void
intelDRI2Flush(__DRIdrawable *drawable)
{
- struct intel_context *intel = drawable->driContextPriv->driverPrivate;
+ GET_CURRENT_CONTEXT(ctx);
+ struct intel_context *intel = intel_context(ctx);
if (intel->gen < 4)
INTEL_FIREVERTICES(intel);
intel->need_throttle = GL_TRUE;
- if (intel->batch->map != intel->batch->ptr)
- intel_batchbuffer_flush(intel->batch);
+ if (intel->batch.used)
+ intel_batchbuffer_flush(intel);
}
static const struct __DRI2flushExtensionRec intelFlushExtension = {
@@ -312,13 +313,21 @@ intel_get_param(__DRIscreen *psp, int param, int *value)
ret = drmCommandWriteRead(psp->fd, DRM_I915_GETPARAM, &gp, sizeof(gp));
if (ret) {
- _mesa_warning(NULL, "drm_i915_getparam: %d", ret);
+ if (ret != -EINVAL)
+ _mesa_warning(NULL, "drm_i915_getparam: %d", ret);
return GL_FALSE;
}
return GL_TRUE;
}
+static GLboolean
+intel_get_boolean(__DRIscreen *psp, int param)
+{
+ int value = 0;
+ return intel_get_param(psp, param, &value) && value;
+}
+
static void
nop_callback(GLuint key, void *data, void *userData)
{
@@ -492,6 +501,10 @@ intel_init_bufmgr(struct intel_screen *intelScreen)
intelScreen->named_regions = _mesa_NewHashTable();
+ intelScreen->relaxed_relocations = 0;
+ intelScreen->relaxed_relocations |=
+ intel_get_boolean(spriv, I915_PARAM_HAS_RELAXED_DELTA) << 0;
+
return GL_TRUE;
}
@@ -645,6 +658,51 @@ __DRIconfig **intelInitScreen2(__DRIscreen *psp)
return (const __DRIconfig **)configs;
}
+struct intel_buffer {
+ __DRIbuffer base;
+ struct intel_region *region;
+};
+
+static __DRIbuffer *
+intelAllocateBuffer(__DRIscreen *screen,
+ unsigned attachment, unsigned format,
+ int width, int height)
+{
+ struct intel_buffer *intelBuffer;
+ struct intel_screen *intelScreen = screen->private;
+
+ intelBuffer = CALLOC(sizeof *intelBuffer);
+ if (intelBuffer == NULL)
+ return NULL;
+
+ intelBuffer->region = intel_region_alloc(intelScreen, I915_TILING_NONE,
+ format / 8, width, height, GL_TRUE);
+
+ if (intelBuffer->region == NULL) {
+ FREE(intelBuffer);
+ return NULL;
+ }
+
+ intel_region_flink(intelBuffer->region, &intelBuffer->base.name);
+
+ intelBuffer->base.attachment = attachment;
+ intelBuffer->base.cpp = intelBuffer->region->cpp;
+ intelBuffer->base.pitch =
+ intelBuffer->region->pitch * intelBuffer->region->cpp;
+
+ return &intelBuffer->base;
+}
+
+static void
+intelReleaseBuffer(__DRIscreen *screen, __DRIbuffer *buffer)
+{
+ struct intel_buffer *intelBuffer = (struct intel_buffer *) buffer;
+
+ intel_region_release(&intelBuffer->region);
+ free(intelBuffer);
+}
+
+
const struct __DriverAPIRec driDriverAPI = {
.DestroyScreen = intelDestroyScreen,
.CreateContext = intelCreateContext,
@@ -654,6 +712,8 @@ const struct __DriverAPIRec driDriverAPI = {
.MakeCurrent = intelMakeCurrent,
.UnbindContext = intelUnbindContext,
.InitScreen2 = intelInitScreen2,
+ .AllocateBuffer = intelAllocateBuffer,
+ .ReleaseBuffer = intelReleaseBuffer
};
/* This is the table of extensions that the loader will dlsym() for. */
diff --git a/src/mesa/drivers/dri/intel/intel_screen.h b/src/mesa/drivers/dri/intel/intel_screen.h
index 5863093f00..0f0b5be56d 100644
--- a/src/mesa/drivers/dri/intel/intel_screen.h
+++ b/src/mesa/drivers/dri/intel/intel_screen.h
@@ -43,6 +43,7 @@ struct intel_screen
__DRIscreen *driScrnPriv;
GLboolean no_hw;
+ GLuint relaxed_relocations;
GLboolean no_vbo;
dri_bufmgr *bufmgr;
diff --git a/src/mesa/drivers/dri/intel/intel_span.c b/src/mesa/drivers/dri/intel/intel_span.c
index 104cadf0f9..1f41518535 100644
--- a/src/mesa/drivers/dri/intel/intel_span.c
+++ b/src/mesa/drivers/dri/intel/intel_span.c
@@ -25,6 +25,7 @@
*
**************************************************************************/
+#include <stdbool.h>
#include "main/glheader.h"
#include "main/macros.h"
#include "main/mtypes.h"
@@ -113,6 +114,26 @@ intel_set_span_functions(struct intel_context *intel,
#define TAG2(x,y) intel_##x##y##_A8
#include "spantmp2.h"
+#define SPANTMP_MESA_FMT MESA_FORMAT_R8
+#define TAG(x) intel_##x##_R8
+#define TAG2(x,y) intel_##x##y##_R8
+#include "spantmp2.h"
+
+#define SPANTMP_MESA_FMT MESA_FORMAT_RG88
+#define TAG(x) intel_##x##_RG88
+#define TAG2(x,y) intel_##x##y##_RG88
+#include "spantmp2.h"
+
+#define SPANTMP_MESA_FMT MESA_FORMAT_R16
+#define TAG(x) intel_##x##_R16
+#define TAG2(x,y) intel_##x##y##_R16
+#include "spantmp2.h"
+
+#define SPANTMP_MESA_FMT MESA_FORMAT_RG1616
+#define TAG(x) intel_##x##_RG1616
+#define TAG2(x,y) intel_##x##y##_RG1616
+#include "spantmp2.h"
+
#define LOCAL_DEPTH_VARS \
struct intel_renderbuffer *irb = intel_renderbuffer(rb); \
const GLint yScale = rb->Name ? 1 : -1; \
@@ -339,6 +360,32 @@ intel_unmap_vertex_shader_textures(struct gl_context *ctx)
}
}
+typedef void (*span_init_func)(struct gl_renderbuffer *rb);
+
+static span_init_func intel_span_init_funcs[MESA_FORMAT_COUNT] =
+{
+ [MESA_FORMAT_A8] = intel_InitPointers_A8,
+ [MESA_FORMAT_RGB565] = intel_InitPointers_RGB565,
+ [MESA_FORMAT_ARGB4444] = intel_InitPointers_ARGB4444,
+ [MESA_FORMAT_ARGB1555] = intel_InitPointers_ARGB1555,
+ [MESA_FORMAT_XRGB8888] = intel_InitPointers_xRGB8888,
+ [MESA_FORMAT_ARGB8888] = intel_InitPointers_ARGB8888,
+ [MESA_FORMAT_SARGB8] = intel_InitPointers_ARGB8888,
+ [MESA_FORMAT_Z16] = intel_InitDepthPointers_z16,
+ [MESA_FORMAT_X8_Z24] = intel_InitDepthPointers_z24_s8,
+ [MESA_FORMAT_S8_Z24] = intel_InitDepthPointers_z24_s8,
+ [MESA_FORMAT_R8] = intel_InitPointers_R8,
+ [MESA_FORMAT_RG88] = intel_InitPointers_RG88,
+ [MESA_FORMAT_R16] = intel_InitPointers_R16,
+ [MESA_FORMAT_RG1616] = intel_InitPointers_RG1616,
+};
+
+bool
+intel_span_supports_format(gl_format format)
+{
+ return intel_span_init_funcs[format] != NULL;
+}
+
/**
* Plug in appropriate span read/write functions for the given renderbuffer.
* These are used for the software fallbacks.
@@ -349,37 +396,6 @@ intel_set_span_functions(struct intel_context *intel,
{
struct intel_renderbuffer *irb = (struct intel_renderbuffer *) rb;
- switch (irb->Base.Format) {
- case MESA_FORMAT_A8:
- intel_InitPointers_A8(rb);
- break;
- case MESA_FORMAT_RGB565:
- intel_InitPointers_RGB565(rb);
- break;
- case MESA_FORMAT_ARGB4444:
- intel_InitPointers_ARGB4444(rb);
- break;
- case MESA_FORMAT_ARGB1555:
- intel_InitPointers_ARGB1555(rb);
- break;
- case MESA_FORMAT_XRGB8888:
- intel_InitPointers_xRGB8888(rb);
- break;
- case MESA_FORMAT_ARGB8888:
- case MESA_FORMAT_SARGB8:
- intel_InitPointers_ARGB8888(rb);
- break;
- case MESA_FORMAT_Z16:
- intel_InitDepthPointers_z16(rb);
- break;
- case MESA_FORMAT_X8_Z24:
- case MESA_FORMAT_S8_Z24:
- intel_InitDepthPointers_z24_s8(rb);
- break;
- default:
- _mesa_problem(NULL,
- "Unexpected MesaFormat %d in intelSetSpanFunctions",
- irb->Base.Format);
- break;
- }
+ assert(intel_span_init_funcs[irb->Base.Format]);
+ intel_span_init_funcs[irb->Base.Format](rb);
}
diff --git a/src/mesa/drivers/dri/intel/intel_span.h b/src/mesa/drivers/dri/intel/intel_span.h
index aa8d08e843..5a4c4e8e52 100644
--- a/src/mesa/drivers/dri/intel/intel_span.h
+++ b/src/mesa/drivers/dri/intel/intel_span.h
@@ -28,6 +28,9 @@
#ifndef _INTEL_SPAN_H
#define _INTEL_SPAN_H
+#include "main/formats.h"
+#include <stdbool.h>
+
extern void intelInitSpanFuncs(struct gl_context * ctx);
extern void intelSpanRenderFinish(struct gl_context * ctx);
@@ -38,5 +41,6 @@ void intel_renderbuffer_unmap(struct intel_context *intel,
struct gl_renderbuffer *rb);
void intel_map_vertex_shader_textures(struct gl_context *ctx);
void intel_unmap_vertex_shader_textures(struct gl_context *ctx);
+bool intel_span_supports_format(gl_format format);
#endif
diff --git a/src/mesa/drivers/dri/intel/intel_syncobj.c b/src/mesa/drivers/dri/intel/intel_syncobj.c
index bbfac74b60..b303ea84dd 100644
--- a/src/mesa/drivers/dri/intel/intel_syncobj.c
+++ b/src/mesa/drivers/dri/intel/intel_syncobj.c
@@ -72,9 +72,9 @@ intel_fence_sync(struct gl_context *ctx, struct gl_sync_object *s,
struct intel_sync_object *sync = (struct intel_sync_object *)s;
assert(condition == GL_SYNC_GPU_COMMANDS_COMPLETE);
- intel_batchbuffer_emit_mi_flush(intel->batch);
+ intel_batchbuffer_emit_mi_flush(intel);
- sync->bo = intel->batch->buf;
+ sync->bo = intel->batch.bo;
drm_intel_bo_reference(sync->bo);
intel_flush(ctx);
diff --git a/src/mesa/drivers/dri/intel/intel_tex.c b/src/mesa/drivers/dri/intel/intel_tex.c
index 646e55bdff..077c611901 100644
--- a/src/mesa/drivers/dri/intel/intel_tex.c
+++ b/src/mesa/drivers/dri/intel/intel_tex.c
@@ -113,7 +113,6 @@ intelGenerateMipmap(struct gl_context *ctx, GLenum target,
void
intelInitTextureFuncs(struct dd_function_table *functions)
{
- functions->ChooseTextureFormat = intelChooseTextureFormat;
functions->GenerateMipmap = intelGenerateMipmap;
functions->NewTextureObject = intelNewTextureObject;
diff --git a/src/mesa/drivers/dri/intel/intel_tex.h b/src/mesa/drivers/dri/intel/intel_tex.h
index 7906554e45..52462f39d5 100644
--- a/src/mesa/drivers/dri/intel/intel_tex.h
+++ b/src/mesa/drivers/dri/intel/intel_tex.h
@@ -40,8 +40,7 @@ void intelInitTextureSubImageFuncs(struct dd_function_table *functions);
void intelInitTextureCopyImageFuncs(struct dd_function_table *functions);
-gl_format intelChooseTextureFormat(struct gl_context *ctx, GLint internalFormat,
- GLenum format, GLenum type);
+GLenum intel_mesa_format_to_rb_datatype(gl_format format);
void intelSetTexBuffer(__DRIcontext *pDRICtx,
GLint target, __DRIdrawable *pDraw);
@@ -66,4 +65,12 @@ void intel_tex_unmap_images(struct intel_context *intel,
int intel_compressed_num_bytes(GLuint mesaFormat);
+GLboolean intel_copy_texsubimage(struct intel_context *intel,
+ GLenum target,
+ struct intel_texture_image *intelImage,
+ GLenum internalFormat,
+ GLint dstx, GLint dsty,
+ GLint x, GLint y,
+ GLsizei width, GLsizei height);
+
#endif
diff --git a/src/mesa/drivers/dri/intel/intel_tex_copy.c b/src/mesa/drivers/dri/intel/intel_tex_copy.c
index 87b31bf078..62d4169acd 100644
--- a/src/mesa/drivers/dri/intel/intel_tex_copy.c
+++ b/src/mesa/drivers/dri/intel/intel_tex_copy.c
@@ -35,7 +35,6 @@
#include "intel_screen.h"
#include "intel_context.h"
-#include "intel_buffers.h"
#include "intel_mipmap_tree.h"
#include "intel_regions.h"
#include "intel_fbo.h"
@@ -50,74 +49,70 @@
* Do the best we can using the blitter. A future project is to use
* the texture engine and fragment programs for these copies.
*/
-static const struct intel_region *
-get_teximage_source(struct intel_context *intel, GLenum internalFormat)
+static struct intel_renderbuffer *
+get_teximage_readbuffer(struct intel_context *intel, GLenum internalFormat)
{
- struct intel_renderbuffer *irb;
-
DBG("%s %s\n", __FUNCTION__,
_mesa_lookup_enum_by_nr(internalFormat));
switch (internalFormat) {
case GL_DEPTH_COMPONENT:
case GL_DEPTH_COMPONENT16:
- irb = intel_get_renderbuffer(intel->ctx.ReadBuffer, BUFFER_DEPTH);
- if (irb && irb->region && irb->region->cpp == 2)
- return irb->region;
- return NULL;
case GL_DEPTH24_STENCIL8_EXT:
case GL_DEPTH_STENCIL_EXT:
- irb = intel_get_renderbuffer(intel->ctx.ReadBuffer, BUFFER_DEPTH);
- if (irb && irb->region && irb->region->cpp == 4)
- return irb->region;
- return NULL;
- case 4:
- case GL_RGBA:
- case GL_RGBA8:
- irb = intel_renderbuffer(intel->ctx.ReadBuffer->_ColorReadBuffer);
- /* We're required to set alpha to 1.0 in this case, but we can't
- * do that with the blitter, so fall back. We could use the 3D
- * engine or do two passes with the blitter, but it doesn't seem
- * worth it for this case. */
- if (irb->Base._BaseFormat == GL_RGB)
- return NULL;
- return irb->region;
- case 3:
- case GL_RGB:
- case GL_RGB8:
- return intel_readbuf_region(intel);
+ return intel_get_renderbuffer(intel->ctx.ReadBuffer, BUFFER_DEPTH);
default:
- return NULL;
+ return intel_renderbuffer(intel->ctx.ReadBuffer->_ColorReadBuffer);
}
}
-static GLboolean
-do_copy_texsubimage(struct intel_context *intel,
- GLenum target,
- struct intel_texture_image *intelImage,
- GLenum internalFormat,
- GLint dstx, GLint dsty,
- GLint x, GLint y, GLsizei width, GLsizei height)
+GLboolean
+intel_copy_texsubimage(struct intel_context *intel,
+ GLenum target,
+ struct intel_texture_image *intelImage,
+ GLenum internalFormat,
+ GLint dstx, GLint dsty,
+ GLint x, GLint y, GLsizei width, GLsizei height)
{
struct gl_context *ctx = &intel->ctx;
- const struct intel_region *src = get_teximage_source(intel, internalFormat);
+ struct intel_renderbuffer *irb;
+ bool copy_supported = false;
+ bool copy_supported_with_alpha_override = false;
+
+ intel_prepare_render(intel);
- if (!intelImage->mt || !src || !src->buffer) {
+ irb = get_teximage_readbuffer(intel, internalFormat);
+ if (!intelImage->mt || !irb || !irb->region) {
if (unlikely(INTEL_DEBUG & DEBUG_FALLBACKS))
fprintf(stderr, "%s fail %p %p (0x%08x)\n",
- __FUNCTION__, intelImage->mt, src, internalFormat);
+ __FUNCTION__, intelImage->mt, irb, internalFormat);
return GL_FALSE;
}
- if (intelImage->mt->cpp != src->cpp) {
- fallback_debug("%s fail %d vs %d cpp\n",
- __FUNCTION__, intelImage->mt->cpp, src->cpp);
+ copy_supported = intelImage->base.TexFormat == irb->Base.Format;
+
+ /* Converting ARGB8888 to XRGB8888 is trivial: ignore the alpha bits */
+ if (irb->Base.Format == MESA_FORMAT_ARGB8888 &&
+ intelImage->base.TexFormat == MESA_FORMAT_XRGB8888) {
+ copy_supported = true;
+ }
+
+ /* Converting XRGB8888 to ARGB8888 requires setting the alpha bits to 1.0 */
+ if (irb->Base.Format == MESA_FORMAT_XRGB8888 &&
+ intelImage->base.TexFormat == MESA_FORMAT_ARGB8888) {
+ copy_supported_with_alpha_override = true;
+ }
+
+ if (!copy_supported && !copy_supported_with_alpha_override) {
+ if (unlikely(INTEL_DEBUG & DEBUG_FALLBACKS))
+ fprintf(stderr, "%s mismatched formats %s, %s\n",
+ __FUNCTION__,
+ _mesa_get_format_name(intelImage->base.TexFormat),
+ _mesa_get_format_name(irb->Base.Format));
return GL_FALSE;
}
- /* intel_flush(ctx); */
- intel_prepare_render(intel);
{
drm_intel_bo *dst_bo = intel_region_buffer(intel,
intelImage->mt->region,
@@ -140,24 +135,24 @@ do_copy_texsubimage(struct intel_context *intel,
if (ctx->ReadBuffer->Name == 0) {
/* Flip vertical orientation for system framebuffers */
y = ctx->ReadBuffer->Height - (y + height);
- src_pitch = -src->pitch;
+ src_pitch = -irb->region->pitch;
} else {
/* reading from a FBO, y is already oriented the way we like */
- src_pitch = src->pitch;
+ src_pitch = irb->region->pitch;
}
/* blit from src buffer to texture */
if (!intelEmitCopyBlit(intel,
intelImage->mt->cpp,
src_pitch,
- src->buffer,
+ irb->region->buffer,
0,
- src->tiling,
+ irb->region->tiling,
intelImage->mt->region->pitch,
dst_bo,
0,
intelImage->mt->region->tiling,
- src->draw_x + x, src->draw_y + y,
+ irb->region->draw_x + x, irb->region->draw_y + y,
image_x + dstx, image_y + dsty,
width, height,
GL_COPY)) {
@@ -165,6 +160,9 @@ do_copy_texsubimage(struct intel_context *intel,
}
}
+ if (copy_supported_with_alpha_override)
+ intel_set_teximage_alpha_to_one(ctx, intelImage);
+
return GL_TRUE;
}
@@ -202,9 +200,9 @@ intelCopyTexImage1D(struct gl_context * ctx, GLenum target, GLint level,
&width, &height))
return;
- if (!do_copy_texsubimage(intel_context(ctx), target,
- intel_texture_image(texImage),
- internalFormat, 0, 0, x, y, width, height))
+ if (!intel_copy_texsubimage(intel_context(ctx), target,
+ intel_texture_image(texImage),
+ internalFormat, 0, 0, x, y, width, height))
goto fail;
return;
@@ -250,9 +248,9 @@ intelCopyTexImage2D(struct gl_context * ctx, GLenum target, GLint level,
&width, &height))
return;
- if (!do_copy_texsubimage(intel_context(ctx), target,
- intel_texture_image(texImage),
- internalFormat, 0, 0, x, y, width, height))
+ if (!intel_copy_texsubimage(intel_context(ctx), target,
+ intel_texture_image(texImage),
+ internalFormat, 0, 0, x, y, width, height))
goto fail;
return;
@@ -280,9 +278,9 @@ intelCopyTexSubImage1D(struct gl_context * ctx, GLenum target, GLint level,
/* Need to check texture is compatible with source format.
*/
- if (!do_copy_texsubimage(intel_context(ctx), target,
- intel_texture_image(texImage),
- internalFormat, xoffset, 0, x, y, width, 1)) {
+ if (!intel_copy_texsubimage(intel_context(ctx), target,
+ intel_texture_image(texImage),
+ internalFormat, xoffset, 0, x, y, width, 1)) {
fallback_debug("%s - fallback to swrast\n", __FUNCTION__);
_mesa_meta_CopyTexSubImage1D(ctx, target, level, xoffset, x, y, width);
}
@@ -304,11 +302,10 @@ intelCopyTexSubImage2D(struct gl_context * ctx, GLenum target, GLint level,
/* Need to check texture is compatible with source format.
*/
- if (!do_copy_texsubimage(intel_context(ctx), target,
- intel_texture_image(texImage),
- internalFormat,
- xoffset, yoffset, x, y, width, height)) {
-
+ if (!intel_copy_texsubimage(intel_context(ctx), target,
+ intel_texture_image(texImage),
+ internalFormat,
+ xoffset, yoffset, x, y, width, height)) {
fallback_debug("%s - fallback to swrast\n", __FUNCTION__);
_mesa_meta_CopyTexSubImage2D(ctx, target, level,
xoffset, yoffset, x, y, width, height);
diff --git a/src/mesa/drivers/dri/intel/intel_tex_format.c b/src/mesa/drivers/dri/intel/intel_tex_format.c
index 9d73a2fb37..87745bc66d 100644
--- a/src/mesa/drivers/dri/intel/intel_tex_format.c
+++ b/src/mesa/drivers/dri/intel/intel_tex_format.c
@@ -4,224 +4,35 @@
#include "main/formats.h"
/**
- * Choose hardware texture format given the user's glTexImage parameters.
- *
- * It works out that this function is fine for all the supported
- * hardware. However, there is still a need to map the formats onto
- * hardware descriptors.
- *
- * Note that the i915 can actually support many more formats than
- * these if we take the step of simply swizzling the colors
- * immediately after sampling...
+ * Returns the renderbuffer DataType for a MESA_FORMAT.
*/
-gl_format
-intelChooseTextureFormat(struct gl_context * ctx, GLint internalFormat,
- GLenum format, GLenum type)
+GLenum
+intel_mesa_format_to_rb_datatype(gl_format format)
{
- struct intel_context *intel = intel_context(ctx);
-
-#if 0
- printf("%s intFmt=0x%x format=0x%x type=0x%x\n",
- __FUNCTION__, internalFormat, format, type);
-#endif
-
- switch (internalFormat) {
- case 4:
- case GL_RGBA:
- case GL_COMPRESSED_RGBA:
- if (type == GL_UNSIGNED_SHORT_4_4_4_4_REV)
- return MESA_FORMAT_ARGB4444;
- else if (type == GL_UNSIGNED_SHORT_1_5_5_5_REV)
- return MESA_FORMAT_ARGB1555;
- else
- return MESA_FORMAT_ARGB8888;
-
- case 3:
- case GL_RGB:
- case GL_COMPRESSED_RGB:
- if (type == GL_UNSIGNED_SHORT_5_6_5)
- return MESA_FORMAT_RGB565;
- else if (intel->has_xrgb_textures)
- return MESA_FORMAT_XRGB8888;
- else
- return MESA_FORMAT_ARGB8888;
-
- case GL_RGBA8:
- case GL_RGB10_A2:
- case GL_RGBA12:
- case GL_RGBA16:
- return MESA_FORMAT_ARGB8888;
-
- case GL_RGBA4:
- case GL_RGBA2:
- return MESA_FORMAT_ARGB4444;
-
- case GL_RGB5_A1:
- return MESA_FORMAT_ARGB1555;
-
- case GL_RGB8:
- case GL_RGB10:
- case GL_RGB12:
- case GL_RGB16:
- if (intel->has_xrgb_textures)
- return MESA_FORMAT_XRGB8888;
- else
- return MESA_FORMAT_ARGB8888;
-
- case GL_RGB5:
- case GL_RGB4:
- case GL_R3_G3_B2:
- return MESA_FORMAT_RGB565;
-
- case GL_ALPHA:
- case GL_ALPHA4:
- case GL_ALPHA8:
- case GL_ALPHA12:
- case GL_ALPHA16:
- case GL_COMPRESSED_ALPHA:
- return MESA_FORMAT_A8;
-
- case 1:
- case GL_LUMINANCE:
- case GL_LUMINANCE4:
- case GL_LUMINANCE8:
- case GL_LUMINANCE12:
- case GL_LUMINANCE16:
- case GL_COMPRESSED_LUMINANCE:
- return MESA_FORMAT_L8;
-
- case GL_LUMINANCE12_ALPHA4:
- case GL_LUMINANCE12_ALPHA12:
- case GL_LUMINANCE16_ALPHA16:
- /* i915 could implement this mode using MT_32BIT_RG1616. However, this
- * would require an extra swizzle instruction in the fragment shader to
- * convert the { R, G, 1.0, 1.0 } to { R, R, R, G }.
- */
-#ifndef I915
- return MESA_FORMAT_AL1616;
-#else
- /* FALLTHROUGH */
-#endif
-
- case 2:
- case GL_LUMINANCE_ALPHA:
- case GL_LUMINANCE4_ALPHA4:
- case GL_LUMINANCE6_ALPHA2:
- case GL_LUMINANCE8_ALPHA8:
- case GL_COMPRESSED_LUMINANCE_ALPHA:
- return MESA_FORMAT_AL88;
-
- case GL_INTENSITY:
- case GL_INTENSITY4:
- case GL_INTENSITY8:
- case GL_INTENSITY12:
- case GL_INTENSITY16:
- case GL_COMPRESSED_INTENSITY:
- return MESA_FORMAT_I8;
-
- case GL_YCBCR_MESA:
- if (type == GL_UNSIGNED_SHORT_8_8_MESA || type == GL_UNSIGNED_BYTE)
- return MESA_FORMAT_YCBCR;
- else
- return MESA_FORMAT_YCBCR_REV;
-
- case GL_COMPRESSED_RGB_FXT1_3DFX:
- return MESA_FORMAT_RGB_FXT1;
- case GL_COMPRESSED_RGBA_FXT1_3DFX:
- return MESA_FORMAT_RGBA_FXT1;
-
- case GL_RGB_S3TC:
- case GL_RGB4_S3TC:
- case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
- return MESA_FORMAT_RGB_DXT1;
-
- case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
- return MESA_FORMAT_RGBA_DXT1;
-
- case GL_RGBA_S3TC:
- case GL_RGBA4_S3TC:
- case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
- return MESA_FORMAT_RGBA_DXT3;
-
- case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
- return MESA_FORMAT_RGBA_DXT5;
-
- case GL_DEPTH_COMPONENT:
- case GL_DEPTH_COMPONENT16:
- case GL_DEPTH_COMPONENT24:
- case GL_DEPTH_COMPONENT32:
-#if 0
- return MESA_FORMAT_Z16;
-#else
- /* fall-through.
- * 16bpp depth texture can't be paired with a stencil buffer so
- * always used combined depth/stencil format.
- */
-#endif
- case GL_DEPTH_STENCIL_EXT:
- case GL_DEPTH24_STENCIL8_EXT:
- return MESA_FORMAT_S8_Z24;
-
-#ifndef I915
- case GL_SRGB_EXT:
- case GL_SRGB8_EXT:
- case GL_SRGB_ALPHA_EXT:
- case GL_SRGB8_ALPHA8_EXT:
- case GL_COMPRESSED_SRGB_EXT:
- case GL_COMPRESSED_SRGB_ALPHA_EXT:
- case GL_COMPRESSED_SLUMINANCE_EXT:
- case GL_COMPRESSED_SLUMINANCE_ALPHA_EXT:
- return MESA_FORMAT_SARGB8;
- case GL_SLUMINANCE_EXT:
- case GL_SLUMINANCE8_EXT:
- if (intel->has_luminance_srgb)
- return MESA_FORMAT_SL8;
- else
- return MESA_FORMAT_SARGB8;
- case GL_SLUMINANCE_ALPHA_EXT:
- case GL_SLUMINANCE8_ALPHA8_EXT:
- if (intel->has_luminance_srgb)
- return MESA_FORMAT_SLA8;
- else
- return MESA_FORMAT_SARGB8;
- case GL_COMPRESSED_SRGB_S3TC_DXT1_EXT:
- case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT:
- case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT:
- case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT:
- return MESA_FORMAT_SRGB_DXT1;
-
- /* i915 could also do this */
- case GL_DUDV_ATI:
- case GL_DU8DV8_ATI:
- return MESA_FORMAT_DUDV8;
- case GL_RGBA_SNORM:
- case GL_RGBA8_SNORM:
- return MESA_FORMAT_SIGNED_RGBA8888_REV;
-
- /* i915 can do a RG16, but it can't do any of the other RED or RG formats.
- * In addition, it only implements the broken D3D mode where undefined
- * components are read as 1.0. I'm not sure who thought reading
- * { R, G, 1.0, 1.0 } from a red-green texture would be useful.
- */
- case GL_RED:
- case GL_R8:
- return MESA_FORMAT_R8;
- case GL_R16:
- return MESA_FORMAT_R16;
- case GL_RG:
- case GL_RG8:
- return MESA_FORMAT_RG88;
- case GL_RG16:
- return MESA_FORMAT_RG1616;
-#endif
-
+ switch (format) {
+ case MESA_FORMAT_ARGB8888:
+ case MESA_FORMAT_XRGB8888:
+ case MESA_FORMAT_SARGB8:
+ case MESA_FORMAT_R8:
+ case MESA_FORMAT_RG88:
+ case MESA_FORMAT_A8:
+ case MESA_FORMAT_AL88:
+ case MESA_FORMAT_RGB565:
+ case MESA_FORMAT_ARGB1555:
+ case MESA_FORMAT_ARGB4444:
+ return GL_UNSIGNED_BYTE;
+ case MESA_FORMAT_R16:
+ case MESA_FORMAT_RG1616:
+ case MESA_FORMAT_Z16:
+ return GL_UNSIGNED_SHORT;
+ case MESA_FORMAT_X8_Z24:
+ return GL_UNSIGNED_INT;
+ case MESA_FORMAT_S8_Z24:
+ return GL_UNSIGNED_INT_24_8_EXT;
default:
- fprintf(stderr, "unexpected texture format %s in %s\n",
- _mesa_lookup_enum_by_nr(internalFormat), __FUNCTION__);
- return MESA_FORMAT_NONE;
+ _mesa_problem(NULL, "unexpected MESA_FORMAT for renderbuffer");
+ return GL_UNSIGNED_BYTE;
}
-
- return MESA_FORMAT_NONE; /* never get here */
}
int intel_compressed_num_bytes(GLuint mesaFormat)
diff --git a/src/mesa/drivers/dri/intel/intel_tex_image.c b/src/mesa/drivers/dri/intel/intel_tex_image.c
index 41cdbfd2cb..906f8a6271 100644
--- a/src/mesa/drivers/dri/intel/intel_tex_image.c
+++ b/src/mesa/drivers/dri/intel/intel_tex_image.c
@@ -1,11 +1,13 @@
#include "main/glheader.h"
#include "main/macros.h"
+#include "main/mfeatures.h"
#include "main/mtypes.h"
#include "main/enums.h"
#include "main/bufferobj.h"
#include "main/context.h"
#include "main/formats.h"
+#include "main/pbo.h"
#include "main/texcompress.h"
#include "main/texstore.h"
#include "main/texgetimage.h"
@@ -55,11 +57,11 @@ logbase2(int n)
* 0)..(1x1). Consider pruning this tree at a validation if the
* saving is worth it.
*/
-static void
-guess_and_alloc_mipmap_tree(struct intel_context *intel,
- struct intel_texture_object *intelObj,
- struct intel_texture_image *intelImage,
- GLboolean expect_accelerated_upload)
+static struct intel_mipmap_tree *
+intel_miptree_create_for_teximage(struct intel_context *intel,
+ struct intel_texture_object *intelObj,
+ struct intel_texture_image *intelImage,
+ GLboolean expect_accelerated_upload)
{
GLuint firstLevel;
GLuint lastLevel;
@@ -72,70 +74,71 @@ guess_and_alloc_mipmap_tree(struct intel_context *intel,
DBG("%s\n", __FUNCTION__);
if (intelImage->base.Border)
- return;
+ return NULL;
if (intelImage->level > intelObj->base.BaseLevel &&
(intelImage->base.Width == 1 ||
(intelObj->base.Target != GL_TEXTURE_1D &&
intelImage->base.Height == 1) ||
(intelObj->base.Target == GL_TEXTURE_3D &&
- intelImage->base.Depth == 1)))
- return;
-
- /* If this image disrespects BaseLevel, allocate from level zero.
- * Usually BaseLevel == 0, so it's unlikely to happen.
- */
- if (intelImage->level < intelObj->base.BaseLevel)
- firstLevel = 0;
- else
- firstLevel = intelObj->base.BaseLevel;
-
-
- /* Figure out image dimensions at start level.
- */
- for (i = intelImage->level; i > firstLevel; i--) {
- width <<= 1;
- if (height != 1)
- height <<= 1;
- if (depth != 1)
- depth <<= 1;
- }
+ intelImage->base.Depth == 1))) {
+ /* For this combination, we're at some lower mipmap level and
+ * some important dimension is 1. We can't extrapolate up to a
+ * likely base level width/height/depth for a full mipmap stack
+ * from this info, so just allocate this one level.
+ */
+ firstLevel = intelImage->level;
+ lastLevel = intelImage->level;
+ } else {
+ /* If this image disrespects BaseLevel, allocate from level zero.
+ * Usually BaseLevel == 0, so it's unlikely to happen.
+ */
+ if (intelImage->level < intelObj->base.BaseLevel)
+ firstLevel = 0;
+ else
+ firstLevel = intelObj->base.BaseLevel;
+
+ /* Figure out image dimensions at start level. */
+ for (i = intelImage->level; i > firstLevel; i--) {
+ width <<= 1;
+ if (height != 1)
+ height <<= 1;
+ if (depth != 1)
+ depth <<= 1;
+ }
- /* Guess a reasonable value for lastLevel. This is probably going
- * to be wrong fairly often and might mean that we have to look at
- * resizable buffers, or require that buffers implement lazy
- * pagetable arrangements.
- */
- if ((intelObj->base.MinFilter == GL_NEAREST ||
- intelObj->base.MinFilter == GL_LINEAR) &&
- intelImage->level == firstLevel &&
- (intel->gen < 4 || firstLevel == 0)) {
- lastLevel = firstLevel;
- }
- else {
- lastLevel = firstLevel + logbase2(MAX2(MAX2(width, height), depth));
+ /* Guess a reasonable value for lastLevel. This is probably going
+ * to be wrong fairly often and might mean that we have to look at
+ * resizable buffers, or require that buffers implement lazy
+ * pagetable arrangements.
+ */
+ if ((intelObj->base.MinFilter == GL_NEAREST ||
+ intelObj->base.MinFilter == GL_LINEAR) &&
+ intelImage->level == firstLevel &&
+ (intel->gen < 4 || firstLevel == 0)) {
+ lastLevel = firstLevel;
+ } else {
+ lastLevel = firstLevel + logbase2(MAX2(MAX2(width, height), depth));
+ }
}
- assert(!intelObj->mt);
if (_mesa_is_format_compressed(intelImage->base.TexFormat))
comp_byte = intel_compressed_num_bytes(intelImage->base.TexFormat);
texelBytes = _mesa_get_format_bytes(intelImage->base.TexFormat);
- intelObj->mt = intel_miptree_create(intel,
- intelObj->base.Target,
- intelImage->base._BaseFormat,
- intelImage->base.InternalFormat,
- firstLevel,
- lastLevel,
- width,
- height,
- depth,
- texelBytes,
- comp_byte,
- expect_accelerated_upload);
-
- DBG("%s - success\n", __FUNCTION__);
+ return intel_miptree_create(intel,
+ intelObj->base.Target,
+ intelImage->base._BaseFormat,
+ intelImage->base.InternalFormat,
+ firstLevel,
+ lastLevel,
+ width,
+ height,
+ depth,
+ texelBytes,
+ comp_byte,
+ expect_accelerated_upload);
}
@@ -229,15 +232,18 @@ try_pbo_upload(struct intel_context *intel,
dst_stride = intelImage->mt->region->pitch;
- if (drm_intel_bo_references(intel->batch->buf, dst_buffer))
+ if (drm_intel_bo_references(intel->batch.bo, dst_buffer))
intel_flush(&intel->ctx);
{
- drm_intel_bo *src_buffer = intel_bufferobj_buffer(intel, pbo, INTEL_READ);
+ GLuint offset;
+ drm_intel_bo *src_buffer =
+ intel_bufferobj_source(intel, pbo, 64, &offset);
if (!intelEmitCopyBlit(intel,
intelImage->mt->cpp,
- src_stride, src_buffer, src_offset, GL_FALSE,
+ src_stride, src_buffer,
+ src_offset + offset, GL_FALSE,
dst_stride, dst_buffer, 0,
intelImage->mt->region->tiling,
0, 0, dst_x, dst_y, width, height,
@@ -343,41 +349,29 @@ intelTexImage(struct gl_context * ctx,
texImage->Data = NULL;
}
- if (!intelObj->mt) {
- guess_and_alloc_mipmap_tree(intel, intelObj, intelImage, pixels == NULL);
- if (!intelObj->mt) {
- DBG("guess_and_alloc_mipmap_tree: failed\n");
- }
- }
-
assert(!intelImage->mt);
if (intelObj->mt &&
intel_miptree_match_image(intelObj->mt, &intelImage->base)) {
-
+ /* Use an existing miptree when possible */
intel_miptree_reference(&intelImage->mt, intelObj->mt);
assert(intelImage->mt);
} else if (intelImage->base.Border == 0) {
- int comp_byte = 0;
- GLuint texelBytes = _mesa_get_format_bytes(intelImage->base.TexFormat);
- GLenum baseFormat = _mesa_get_format_base_format(intelImage->base.TexFormat);
- if (_mesa_is_format_compressed(intelImage->base.TexFormat)) {
- comp_byte =
- intel_compressed_num_bytes(intelImage->base.TexFormat);
- }
-
/* Didn't fit in the object miptree, but it's suitable for inclusion in
* a miptree, so create one just for our level and store it in the image.
* It'll get moved into the object miptree at validate time.
*/
- intelImage->mt = intel_miptree_create(intel, target,
- baseFormat,
- internalFormat,
- level, level,
- width, height, depth,
- texelBytes,
- comp_byte, pixels == NULL);
-
+ intelImage->mt = intel_miptree_create_for_teximage(intel, intelObj,
+ intelImage,
+ pixels == NULL);
+
+ /* Even if the object currently has a mipmap tree associated
+ * with it, this one is a more likely candidate to represent the
+ * whole object since our level didn't fit what was there
+ * before, and any lower levels would fit into our miptree.
+ */
+ if (intelImage->mt)
+ intel_miptree_reference(&intelObj->mt, intelImage->mt);
}
/* PBO fastpaths:
@@ -439,7 +433,7 @@ intelTexImage(struct gl_context * ctx,
if (intelImage->mt) {
if (pixels != NULL) {
/* Flush any queued rendering with the texture before mapping. */
- if (drm_intel_bo_references(intel->batch->buf,
+ if (drm_intel_bo_references(intel->batch.bo,
intelImage->mt->region->buffer)) {
intel_flush(ctx);
}
@@ -711,8 +705,7 @@ intelSetTexBuffer2(__DRIcontext *pDRICtx, GLint target,
}
mt = intel_miptree_create_for_region(intel, target,
- internalFormat,
- 0, 0, rb->region, 1, 0);
+ internalFormat, rb->region, 1, 0);
if (mt == NULL)
return;
@@ -777,7 +770,7 @@ intel_image_target_texture_2d(struct gl_context *ctx, GLenum target,
mt = intel_miptree_create_for_region(intel, target,
image->internal_format,
- 0, 0, image->region, 1, 0);
+ image->region, 1, 0);
if (mt == NULL)
return;
diff --git a/src/mesa/drivers/dri/intel/intel_tex_obj.h b/src/mesa/drivers/dri/intel/intel_tex_obj.h
index 5f60e0ea4f..e93ef4a472 100644
--- a/src/mesa/drivers/dri/intel/intel_tex_obj.h
+++ b/src/mesa/drivers/dri/intel/intel_tex_obj.h
@@ -32,11 +32,11 @@ struct intel_texture_object
{
struct gl_texture_object base; /* The "parent" object */
- /* The mipmap tree must include at least these levels once
- * validated:
+ /* This is a mirror of base._MaxLevel, updated at validate time,
+ * except that we don't bother with the non-base levels for
+ * non-mipmapped textures.
*/
- GLuint firstLevel;
- GLuint lastLevel;
+ unsigned int _MaxLevel;
/* Offset for firstLevel image:
*/
diff --git a/src/mesa/drivers/dri/intel/intel_tex_subimage.c b/src/mesa/drivers/dri/intel/intel_tex_subimage.c
index c9b992a21b..d0f8294113 100644
--- a/src/mesa/drivers/dri/intel/intel_tex_subimage.c
+++ b/src/mesa/drivers/dri/intel/intel_tex_subimage.c
@@ -27,6 +27,7 @@
**************************************************************************/
#include "main/mtypes.h"
+#include "main/pbo.h"
#include "main/texobj.h"
#include "main/texstore.h"
#include "main/texcompress.h"
@@ -89,19 +90,19 @@ intelTexSubimage(struct gl_context * ctx,
intel->gen < 6 && target == GL_TEXTURE_2D &&
drm_intel_bo_busy(dst_bo))
{
- unsigned long pitch;
- uint32_t tiling_mode = I915_TILING_NONE;
- temp_bo = drm_intel_bo_alloc_tiled(intel->bufmgr,
- "subimage blit bo",
- width, height,
- intelImage->mt->cpp,
- &tiling_mode,
- &pitch,
- 0);
- drm_intel_gem_bo_map_gtt(temp_bo);
+ dstRowStride = width * intelImage->mt->cpp;
+ temp_bo = drm_intel_bo_alloc(intel->bufmgr, "subimage blit bo",
+ dstRowStride * height, 0);
+ if (!temp_bo)
+ return;
+
+ if (drm_intel_gem_bo_map_gtt(temp_bo)) {
+ drm_intel_bo_unreference(temp_bo);
+ return;
+ }
+
texImage->Data = temp_bo->virtual;
texImage->ImageOffsets[0] = 0;
- dstRowStride = pitch;
intel_miptree_get_image_offset(intelImage->mt, level,
intelImage->face, 0,
diff --git a/src/mesa/drivers/dri/intel/intel_tex_validate.c b/src/mesa/drivers/dri/intel/intel_tex_validate.c
index ed5c5d896b..a11b07ed09 100644
--- a/src/mesa/drivers/dri/intel/intel_tex_validate.c
+++ b/src/mesa/drivers/dri/intel/intel_tex_validate.c
@@ -8,72 +8,21 @@
#define FILE_DEBUG_FLAG DEBUG_TEXTURE
/**
- * Compute which mipmap levels that really need to be sent to the hardware.
- * This depends on the base image size, GL_TEXTURE_MIN_LOD,
- * GL_TEXTURE_MAX_LOD, GL_TEXTURE_BASE_LEVEL, and GL_TEXTURE_MAX_LEVEL.
+ * When validating, we only care about the texture images that could
+ * be seen, so for non-mipmapped modes we want to ignore everything
+ * but BaseLevel.
*/
static void
-intel_calculate_first_last_level(struct intel_context *intel,
- struct intel_texture_object *intelObj)
+intel_update_max_level(struct intel_context *intel,
+ struct intel_texture_object *intelObj)
{
struct gl_texture_object *tObj = &intelObj->base;
- const struct gl_texture_image *const baseImage =
- tObj->Image[0][tObj->BaseLevel];
- /* These must be signed values. MinLod and MaxLod can be negative numbers,
- * and having firstLevel and lastLevel as signed prevents the need for
- * extra sign checks.
- */
- int firstLevel;
- int lastLevel;
-
- /* Yes, this looks overly complicated, but it's all needed.
- */
- switch (tObj->Target) {
- case GL_TEXTURE_1D:
- case GL_TEXTURE_2D:
- case GL_TEXTURE_3D:
- case GL_TEXTURE_CUBE_MAP:
- if (tObj->MinFilter == GL_NEAREST || tObj->MinFilter == GL_LINEAR) {
- /* GL_NEAREST and GL_LINEAR only care about GL_TEXTURE_BASE_LEVEL.
- */
- firstLevel = lastLevel = tObj->BaseLevel;
- }
- else {
- if (intel->gen == 2) {
- firstLevel = tObj->BaseLevel + (GLint) (tObj->MinLod + 0.5);
- firstLevel = MAX2(firstLevel, tObj->BaseLevel);
- firstLevel = MIN2(firstLevel, tObj->BaseLevel + baseImage->MaxLog2);
- lastLevel = tObj->BaseLevel + (GLint) (tObj->MaxLod + 0.5);
- lastLevel = MAX2(lastLevel, tObj->BaseLevel);
- lastLevel = MIN2(lastLevel, tObj->BaseLevel + baseImage->MaxLog2);
- lastLevel = MIN2(lastLevel, tObj->MaxLevel);
- lastLevel = MAX2(firstLevel, lastLevel); /* need at least one level */
- } else {
- /* Min/max LOD are taken into account in sampler state. We don't
- * want to re-layout textures just because clamping has been applied
- * since it means a bunch of blitting around and probably no memory
- * savings (since we have to keep the other levels around anyway).
- */
- firstLevel = tObj->BaseLevel;
- lastLevel = MIN2(tObj->BaseLevel + baseImage->MaxLog2,
- tObj->MaxLevel);
- /* need at least one level */
- lastLevel = MAX2(firstLevel, lastLevel);
- }
- }
- break;
- case GL_TEXTURE_RECTANGLE_NV:
- case GL_TEXTURE_4D_SGIS:
- firstLevel = lastLevel = 0;
- break;
- default:
- return;
+ if (tObj->MinFilter == GL_NEAREST || tObj->MinFilter == GL_LINEAR) {
+ intelObj->_MaxLevel = tObj->BaseLevel;
+ } else {
+ intelObj->_MaxLevel = tObj->_MaxLevel;
}
-
- /* save these values */
- intelObj->firstLevel = firstLevel;
- intelObj->lastLevel = lastLevel;
}
/**
@@ -135,8 +84,8 @@ intel_finalize_mipmap_tree(struct intel_context *intel, GLuint unit)
/* What levels must the tree include at a minimum?
*/
- intel_calculate_first_last_level(intel, intelObj);
- firstImage = intel_texture_image(tObj->Image[0][intelObj->firstLevel]);
+ intel_update_max_level(intel, intelObj);
+ firstImage = intel_texture_image(tObj->Image[0][tObj->BaseLevel]);
/* Fallback case:
*/
@@ -147,23 +96,6 @@ intel_finalize_mipmap_tree(struct intel_context *intel, GLuint unit)
return GL_FALSE;
}
-
- /* If both firstImage and intelObj have a tree which can contain
- * all active images, favour firstImage. Note that because of the
- * completeness requirement, we know that the image dimensions
- * will match.
- */
- if (firstImage->mt &&
- firstImage->mt != intelObj->mt &&
- firstImage->mt->first_level <= intelObj->firstLevel &&
- firstImage->mt->last_level >= intelObj->lastLevel) {
-
- if (intelObj->mt)
- intel_miptree_release(intel, &intelObj->mt);
-
- intel_miptree_reference(&intelObj->mt, firstImage->mt);
- }
-
if (_mesa_is_format_compressed(firstImage->base.TexFormat)) {
comp_byte = intel_compressed_num_bytes(firstImage->base.TexFormat);
cpp = comp_byte;
@@ -173,18 +105,17 @@ intel_finalize_mipmap_tree(struct intel_context *intel, GLuint unit)
/* Check tree can hold all active levels. Check tree matches
* target, imageFormat, etc.
- *
- * XXX: For some layouts (eg i945?), the test might have to be
- * first_level == firstLevel, as the tree isn't valid except at the
- * original start level. Hope to get around this by
- * programming minLod, maxLod, baseLevel into the hardware and
- * leaving the tree alone.
+ *
+ * For pre-gen4, we have to match first_level == tObj->BaseLevel,
+ * because we don't have the control that gen4 does to make min/mag
+ * determination happen at a nonzero (hardware) baselevel. Because
+ * of that, we just always relayout on baselevel change.
*/
if (intelObj->mt &&
(intelObj->mt->target != intelObj->base.Target ||
intelObj->mt->internal_format != firstImage->base.InternalFormat ||
- intelObj->mt->first_level != intelObj->firstLevel ||
- intelObj->mt->last_level != intelObj->lastLevel ||
+ intelObj->mt->first_level != tObj->BaseLevel ||
+ intelObj->mt->last_level < intelObj->_MaxLevel ||
intelObj->mt->width0 != firstImage->base.Width ||
intelObj->mt->height0 != firstImage->base.Height ||
intelObj->mt->depth0 != firstImage->base.Depth ||
@@ -201,25 +132,29 @@ intel_finalize_mipmap_tree(struct intel_context *intel, GLuint unit)
intelObj->base.Target,
firstImage->base._BaseFormat,
firstImage->base.InternalFormat,
- intelObj->firstLevel,
- intelObj->lastLevel,
+ tObj->BaseLevel,
+ intelObj->_MaxLevel,
firstImage->base.Width,
firstImage->base.Height,
firstImage->base.Depth,
cpp,
comp_byte,
GL_TRUE);
+ if (!intelObj->mt)
+ return GL_FALSE;
}
/* Pull in any images not in the object's tree:
*/
nr_faces = (intelObj->base.Target == GL_TEXTURE_CUBE_MAP) ? 6 : 1;
for (face = 0; face < nr_faces; face++) {
- for (i = intelObj->firstLevel; i <= intelObj->lastLevel; i++) {
+ for (i = tObj->BaseLevel; i <= intelObj->_MaxLevel; i++) {
struct intel_texture_image *intelImage =
intel_texture_image(intelObj->base.Image[face][i]);
-
- /* Need to import images in main memory or held in other trees.
+ /* skip too small size mipmap */
+ if (intelImage == NULL)
+ break;
+ /* Need to import images in main memory or held in other trees.
* If it's a render target, then its data isn't needed to be in
* the object tree (otherwise we'd be FBO incomplete), and we need
* to keep track of the image's MT as needing to be pulled in still,
@@ -289,7 +224,7 @@ intel_tex_map_images(struct intel_context *intel,
DBG("%s\n", __FUNCTION__);
- for (i = intelObj->firstLevel; i <= intelObj->lastLevel; i++)
+ for (i = intelObj->base.BaseLevel; i <= intelObj->_MaxLevel; i++)
intel_tex_map_level_images(intel, intelObj, i);
}
@@ -299,6 +234,6 @@ intel_tex_unmap_images(struct intel_context *intel,
{
int i;
- for (i = intelObj->firstLevel; i <= intelObj->lastLevel; i++)
+ for (i = intelObj->base.BaseLevel; i <= intelObj->_MaxLevel; i++)
intel_tex_unmap_level_images(intel, intelObj, i);
}