i915: Fork the shared code from i965.

Of this 15000 lines of code in intel/, we've identified 4000 lines that
are trivially unnecessary for i915, and another 1000 that are pointless for
i965, and expect to find more as time goes on.  Split the i915 driver off,
so that we can continue active development on i965 without worrying about
breaking i915.

Acked-by: Kenneth Graunke <kenneth@whitecape.org>
Acked-by: Chad Versace <chad.versace@linux.intel.com>
Acked-by: Adam Jackson <ajax@redhat.com>
(and I hear second hand that idr is OK with it, too)
This commit is contained in:
Eric Anholt 2013-06-20 10:00:18 -07:00
parent 43a6795a1f
commit 733d32f376
43 changed files with 14731 additions and 25 deletions

View file

@ -30,7 +30,6 @@ AM_CFLAGS = \
-I$(top_srcdir)/src/mapi \
-I$(top_srcdir)/src/mesa/ \
-I$(top_srcdir)/src/mesa/drivers/dri/common \
-I$(top_srcdir)/src/mesa/drivers/dri/intel \
-I$(top_srcdir)/src/mesa/drivers/dri/intel/server \
-I$(top_builddir)/src/mesa/drivers/dri/common \
$(DEFINES) \

View file

@ -1 +0,0 @@
../intel/intel_batchbuffer.c

View file

@ -0,0 +1,560 @@
/**************************************************************************
*
* Copyright 2006 Tungsten Graphics, Inc., Cedar Park, Texas.
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sub license, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial portions
* of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
**************************************************************************/
#include "intel_context.h"
#include "intel_batchbuffer.h"
#include "intel_buffer_objects.h"
#include "intel_reg.h"
#include "intel_bufmgr.h"
#include "intel_buffers.h"
static void
intel_batchbuffer_reset(struct intel_context *intel);
struct cached_batch_item {
struct cached_batch_item *next;
uint16_t header;
uint16_t size;
};
static void clear_cache( struct intel_context *intel )
{
struct cached_batch_item *item = intel->batch.cached_items;
while (item) {
struct cached_batch_item *next = item->next;
free(item);
item = next;
}
intel->batch.cached_items = NULL;
}
void
intel_batchbuffer_init(struct intel_context *intel)
{
intel_batchbuffer_reset(intel);
if (intel->gen >= 6) {
/* We can't just use brw_state_batch to get a chunk of space for
* the gen6 workaround because it involves actually writing to
* the buffer, and the kernel doesn't let us write to the batch.
*/
intel->batch.workaround_bo = drm_intel_bo_alloc(intel->bufmgr,
"pipe_control workaround",
4096, 4096);
}
if (!intel->has_llc) {
intel->batch.cpu_map = malloc(intel->maxBatchSize);
intel->batch.map = intel->batch.cpu_map;
}
}
static void
intel_batchbuffer_reset(struct intel_context *intel)
{
if (intel->batch.last_bo != NULL) {
drm_intel_bo_unreference(intel->batch.last_bo);
intel->batch.last_bo = NULL;
}
intel->batch.last_bo = intel->batch.bo;
clear_cache(intel);
intel->batch.bo = drm_intel_bo_alloc(intel->bufmgr, "batchbuffer",
intel->maxBatchSize, 4096);
if (intel->has_llc) {
drm_intel_bo_map(intel->batch.bo, true);
intel->batch.map = intel->batch.bo->virtual;
}
intel->batch.reserved_space = BATCH_RESERVED;
intel->batch.state_batch_offset = intel->batch.bo->size;
intel->batch.used = 0;
intel->batch.needs_sol_reset = false;
}
void
intel_batchbuffer_save_state(struct intel_context *intel)
{
intel->batch.saved.used = intel->batch.used;
intel->batch.saved.reloc_count =
drm_intel_gem_bo_get_reloc_count(intel->batch.bo);
}
void
intel_batchbuffer_reset_to_saved(struct intel_context *intel)
{
drm_intel_gem_bo_clear_relocs(intel->batch.bo, intel->batch.saved.reloc_count);
intel->batch.used = intel->batch.saved.used;
/* Cached batch state is dead, since we just cleared some unknown part of the
* batchbuffer. Assume that the caller resets any other state necessary.
*/
clear_cache(intel);
}
void
intel_batchbuffer_free(struct intel_context *intel)
{
free(intel->batch.cpu_map);
drm_intel_bo_unreference(intel->batch.last_bo);
drm_intel_bo_unreference(intel->batch.bo);
drm_intel_bo_unreference(intel->batch.workaround_bo);
clear_cache(intel);
}
static void
do_batch_dump(struct intel_context *intel)
{
struct drm_intel_decode *decode;
struct intel_batchbuffer *batch = &intel->batch;
int ret;
decode = drm_intel_decode_context_alloc(intel->intelScreen->deviceID);
if (!decode)
return;
ret = drm_intel_bo_map(batch->bo, false);
if (ret == 0) {
drm_intel_decode_set_batch_pointer(decode,
batch->bo->virtual,
batch->bo->offset,
batch->used);
} else {
fprintf(stderr,
"WARNING: failed to map batchbuffer (%s), "
"dumping uploaded data instead.\n", strerror(ret));
drm_intel_decode_set_batch_pointer(decode,
batch->map,
batch->bo->offset,
batch->used);
}
drm_intel_decode(decode);
drm_intel_decode_context_free(decode);
if (ret == 0) {
drm_intel_bo_unmap(batch->bo);
if (intel->vtbl.debug_batch != NULL)
intel->vtbl.debug_batch(intel);
}
}
/* TODO: Push this whole function into bufmgr.
*/
static int
do_flush_locked(struct intel_context *intel)
{
struct intel_batchbuffer *batch = &intel->batch;
int ret = 0;
if (intel->has_llc) {
drm_intel_bo_unmap(batch->bo);
} else {
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 (!intel->intelScreen->no_hw) {
int flags;
if (intel->gen < 6 || !batch->is_blit) {
flags = I915_EXEC_RENDER;
} else {
flags = I915_EXEC_BLT;
}
if (batch->needs_sol_reset)
flags |= I915_EXEC_GEN7_SOL_RESET;
if (ret == 0) {
if (unlikely(INTEL_DEBUG & DEBUG_AUB) && intel->vtbl.annotate_aub)
intel->vtbl.annotate_aub(intel);
if (intel->hw_ctx == NULL || batch->is_blit) {
ret = drm_intel_bo_mrb_exec(batch->bo, 4 * batch->used, NULL, 0, 0,
flags);
} else {
ret = drm_intel_gem_bo_context_exec(batch->bo, intel->hw_ctx,
4 * batch->used, flags);
}
}
}
if (unlikely(INTEL_DEBUG & DEBUG_BATCH))
do_batch_dump(intel);
if (ret != 0) {
fprintf(stderr, "intel_do_flush_locked failed: %s\n", strerror(-ret));
exit(1);
}
intel->vtbl.new_batch(intel);
return ret;
}
int
_intel_batchbuffer_flush(struct intel_context *intel,
const char *file, int line)
{
int ret;
if (intel->batch.used == 0)
return 0;
if (intel->first_post_swapbuffers_batch == NULL) {
intel->first_post_swapbuffers_batch = intel->batch.bo;
drm_intel_bo_reference(intel->first_post_swapbuffers_batch);
}
if (unlikely(INTEL_DEBUG & DEBUG_BATCH))
fprintf(stderr, "%s:%d: Batchbuffer flush with %db used\n", file, line,
4*intel->batch.used);
intel->batch.reserved_space = 0;
if (intel->vtbl.finish_batch)
intel->vtbl.finish_batch(intel);
/* Mark the end of the buffer. */
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);
}
intel_upload_finish(intel);
/* Check that we didn't just wrap our batchbuffer at a bad time. */
assert(!intel->no_batch_wrap);
ret = do_flush_locked(intel);
if (unlikely(INTEL_DEBUG & DEBUG_SYNC)) {
fprintf(stderr, "waiting for idle\n");
drm_intel_bo_wait_rendering(intel->batch.bo);
}
/* Reset the buffer:
*/
intel_batchbuffer_reset(intel);
return ret;
}
/* This is the only way buffers get added to the validate list.
*/
bool
intel_batchbuffer_emit_reloc(struct intel_context *intel,
drm_intel_bo *buffer,
uint32_t read_domains, uint32_t write_domain,
uint32_t delta)
{
int ret;
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(intel, buffer->offset + delta);
return true;
}
bool
intel_batchbuffer_emit_reloc_fenced(struct intel_context *intel,
drm_intel_bo *buffer,
uint32_t read_domains,
uint32_t write_domain,
uint32_t delta)
{
int ret;
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(intel, buffer->offset + delta);
return true;
}
void
intel_batchbuffer_data(struct intel_context *intel,
const void *data, GLuint bytes, bool is_blit)
{
assert((bytes & 3) == 0);
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;
}
/**
* Restriction [DevSNB, DevIVB]:
*
* Prior to changing Depth/Stencil Buffer state (i.e. any combination of
* 3DSTATE_DEPTH_BUFFER, 3DSTATE_CLEAR_PARAMS, 3DSTATE_STENCIL_BUFFER,
* 3DSTATE_HIER_DEPTH_BUFFER) SW must first issue a pipelined depth stall
* (PIPE_CONTROL with Depth Stall bit set), followed by a pipelined depth
* cache flush (PIPE_CONTROL with Depth Flush Bit set), followed by
* another pipelined depth stall (PIPE_CONTROL with Depth Stall bit set),
* unless SW can otherwise guarantee that the pipeline from WM onwards is
* already flushed (e.g., via a preceding MI_FLUSH).
*/
void
intel_emit_depth_stall_flushes(struct intel_context *intel)
{
assert(intel->gen >= 6 && intel->gen <= 7);
BEGIN_BATCH(4);
OUT_BATCH(_3DSTATE_PIPE_CONTROL | (4 - 2));
OUT_BATCH(PIPE_CONTROL_DEPTH_STALL);
OUT_BATCH(0); /* address */
OUT_BATCH(0); /* write data */
ADVANCE_BATCH()
BEGIN_BATCH(4);
OUT_BATCH(_3DSTATE_PIPE_CONTROL | (4 - 2));
OUT_BATCH(PIPE_CONTROL_DEPTH_CACHE_FLUSH);
OUT_BATCH(0); /* address */
OUT_BATCH(0); /* write data */
ADVANCE_BATCH();
BEGIN_BATCH(4);
OUT_BATCH(_3DSTATE_PIPE_CONTROL | (4 - 2));
OUT_BATCH(PIPE_CONTROL_DEPTH_STALL);
OUT_BATCH(0); /* address */
OUT_BATCH(0); /* write data */
ADVANCE_BATCH();
}
/**
* From the BSpec, volume 2a.03: VS Stage Input / State:
* "[DevIVB] A PIPE_CONTROL with Post-Sync Operation set to 1h and a depth
* stall needs to be sent just prior to any 3DSTATE_VS, 3DSTATE_URB_VS,
* 3DSTATE_CONSTANT_VS, 3DSTATE_BINDING_TABLE_POINTER_VS,
* 3DSTATE_SAMPLER_STATE_POINTER_VS command. Only one PIPE_CONTROL needs
* to be sent before any combination of VS associated 3DSTATE."
*/
void
gen7_emit_vs_workaround_flush(struct intel_context *intel)
{
assert(intel->gen == 7);
BEGIN_BATCH(4);
OUT_BATCH(_3DSTATE_PIPE_CONTROL | (4 - 2));
OUT_BATCH(PIPE_CONTROL_DEPTH_STALL | PIPE_CONTROL_WRITE_IMMEDIATE);
OUT_RELOC(intel->batch.workaround_bo,
I915_GEM_DOMAIN_INSTRUCTION, I915_GEM_DOMAIN_INSTRUCTION, 0);
OUT_BATCH(0); /* write data */
ADVANCE_BATCH();
}
/**
* Emits a PIPE_CONTROL with a non-zero post-sync operation, for
* implementing two workarounds on gen6. From section 1.4.7.1
* "PIPE_CONTROL" of the Sandy Bridge PRM volume 2 part 1:
*
* [DevSNB-C+{W/A}] Before any depth stall flush (including those
* produced by non-pipelined state commands), software needs to first
* send a PIPE_CONTROL with no bits set except Post-Sync Operation !=
* 0.
*
* [Dev-SNB{W/A}]: Before a PIPE_CONTROL with Write Cache Flush Enable
* =1, a PIPE_CONTROL with any non-zero post-sync-op is required.
*
* And the workaround for these two requires this workaround first:
*
* [Dev-SNB{W/A}]: Pipe-control with CS-stall bit set must be sent
* BEFORE the pipe-control with a post-sync op and no write-cache
* flushes.
*
* And this last workaround is tricky because of the requirements on
* that bit. From section 1.4.7.2.3 "Stall" of the Sandy Bridge PRM
* volume 2 part 1:
*
* "1 of the following must also be set:
* - Render Target Cache Flush Enable ([12] of DW1)
* - Depth Cache Flush Enable ([0] of DW1)
* - Stall at Pixel Scoreboard ([1] of DW1)
* - Depth Stall ([13] of DW1)
* - Post-Sync Operation ([13] of DW1)
* - Notify Enable ([8] of DW1)"
*
* The cache flushes require the workaround flush that triggered this
* one, so we can't use it. Depth stall would trigger the same.
* Post-sync nonzero is what triggered this second workaround, so we
* can't use that one either. Notify enable is IRQs, which aren't
* really our business. That leaves only stall at scoreboard.
*/
void
intel_emit_post_sync_nonzero_flush(struct intel_context *intel)
{
if (!intel->batch.need_workaround_flush)
return;
BEGIN_BATCH(4);
OUT_BATCH(_3DSTATE_PIPE_CONTROL | (4 - 2));
OUT_BATCH(PIPE_CONTROL_CS_STALL |
PIPE_CONTROL_STALL_AT_SCOREBOARD);
OUT_BATCH(0); /* address */
OUT_BATCH(0); /* write data */
ADVANCE_BATCH();
BEGIN_BATCH(4);
OUT_BATCH(_3DSTATE_PIPE_CONTROL | (4 - 2));
OUT_BATCH(PIPE_CONTROL_WRITE_IMMEDIATE);
OUT_RELOC(intel->batch.workaround_bo,
I915_GEM_DOMAIN_INSTRUCTION, I915_GEM_DOMAIN_INSTRUCTION, 0);
OUT_BATCH(0); /* write data */
ADVANCE_BATCH();
intel->batch.need_workaround_flush = false;
}
/* Emit a pipelined flush to either flush render and texture cache for
* reading from a FBO-drawn texture, or flush so that frontbuffer
* render appears on the screen in DRI1.
*
* This is also used for the always_flush_cache driconf debug option.
*/
void
intel_batchbuffer_emit_mi_flush(struct intel_context *intel)
{
if (intel->gen >= 6) {
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 {
if (intel->gen == 6) {
/* Hardware workaround: SNB B-Spec says:
*
* [Dev-SNB{W/A}]: Before a PIPE_CONTROL with Write Cache
* Flush Enable =1, a PIPE_CONTROL with any non-zero
* post-sync-op is required.
*/
intel_emit_post_sync_nonzero_flush(intel);
}
BEGIN_BATCH(4);
OUT_BATCH(_3DSTATE_PIPE_CONTROL | (4 - 2));
OUT_BATCH(PIPE_CONTROL_INSTRUCTION_FLUSH |
PIPE_CONTROL_WRITE_FLUSH |
PIPE_CONTROL_DEPTH_CACHE_FLUSH |
PIPE_CONTROL_VF_CACHE_INVALIDATE |
PIPE_CONTROL_TC_FLUSH |
PIPE_CONTROL_NO_WRITE |
PIPE_CONTROL_CS_STALL);
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 | (4 - 2) |
PIPE_CONTROL_WRITE_FLUSH |
PIPE_CONTROL_NO_WRITE);
OUT_BATCH(0); /* write address */
OUT_BATCH(0); /* write data */
OUT_BATCH(0); /* write data */
ADVANCE_BATCH();
} else {
BEGIN_BATCH(1);
OUT_BATCH(MI_FLUSH);
ADVANCE_BATCH();
}
}

View file

@ -0,0 +1,173 @@
#ifndef INTEL_BATCHBUFFER_H
#define INTEL_BATCHBUFFER_H
#include "main/mtypes.h"
#include "intel_context.h"
#include "intel_bufmgr.h"
#include "intel_reg.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* Number of bytes to reserve for commands necessary to complete a batch.
*
* This includes:
* - MI_BATCHBUFFER_END (4 bytes)
* - Optional MI_NOOP for ensuring the batch length is qword aligned (4 bytes)
* - Any state emitted by vtbl->finish_batch():
* - Gen4-5 record ending occlusion query values (4 * 4 = 16 bytes)
*/
#define BATCH_RESERVED 24
struct intel_batchbuffer;
void intel_batchbuffer_init(struct intel_context *intel);
void intel_batchbuffer_free(struct intel_context *intel);
void intel_batchbuffer_save_state(struct intel_context *intel);
void intel_batchbuffer_reset_to_saved(struct intel_context *intel);
int _intel_batchbuffer_flush(struct intel_context *intel,
const char *file, int line);
#define intel_batchbuffer_flush(intel) \
_intel_batchbuffer_flush(intel, __FILE__, __LINE__)
/* 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_context *intel,
const void *data, GLuint bytes, bool is_blit);
bool intel_batchbuffer_emit_reloc(struct intel_context *intel,
drm_intel_bo *buffer,
uint32_t read_domains,
uint32_t write_domain,
uint32_t offset);
bool 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_context *intel);
void intel_emit_post_sync_nonzero_flush(struct intel_context *intel);
void intel_emit_depth_stall_flushes(struct intel_context *intel);
void gen7_emit_vs_workaround_flush(struct intel_context *intel);
static INLINE uint32_t float_as_int(float f)
{
union {
float f;
uint32_t d;
} fi;
fi.f = f;
return fi.d;
}
/* Inline functions - might actually be better off with these
* non-inlined. Certainly better off switching all command packets to
* be passed as structs rather than dwords, but that's a little bit of
* work...
*/
static INLINE unsigned
intel_batchbuffer_space(struct intel_context *intel)
{
return (intel->batch.state_batch_offset - intel->batch.reserved_space)
- intel->batch.used*4;
}
static INLINE void
intel_batchbuffer_emit_dword(struct intel_context *intel, GLuint dword)
{
#ifdef DEBUG
assert(intel_batchbuffer_space(intel) >= 4);
#endif
intel->batch.map[intel->batch.used++] = dword;
}
static INLINE void
intel_batchbuffer_emit_float(struct intel_context *intel, float f)
{
intel_batchbuffer_emit_dword(intel, float_as_int(f));
}
static INLINE void
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 < intel->maxBatchSize - BATCH_RESERVED);
#endif
if (intel_batchbuffer_space(intel) < sz)
intel_batchbuffer_flush(intel);
}
static INLINE void
intel_batchbuffer_begin(struct intel_context *intel, int n, bool is_blit)
{
intel_batchbuffer_require_space(intel, n * 4, is_blit);
intel->batch.emit = intel->batch.used;
#ifdef DEBUG
intel->batch.total = n;
#endif
}
static INLINE void
intel_batchbuffer_advance(struct intel_context *intel)
{
#ifdef DEBUG
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->total);
abort();
}
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, 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, 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, buf, \
read_domains, write_domain, delta); \
} while (0)
#define ADVANCE_BATCH() intel_batchbuffer_advance(intel);
#define CACHED_BATCH() intel_batchbuffer_cached_advance(intel);
#ifdef __cplusplus
}
#endif
#endif

View file

@ -1 +0,0 @@
../intel/intel_blit.c

View file

@ -0,0 +1,770 @@
/**************************************************************************
*
* Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sub license, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial portions
* of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
**************************************************************************/
#include "main/mtypes.h"
#include "main/context.h"
#include "main/enums.h"
#include "main/colormac.h"
#include "main/fbobject.h"
#include "intel_blit.h"
#include "intel_buffers.h"
#include "intel_context.h"
#include "intel_fbo.h"
#include "intel_reg.h"
#include "intel_regions.h"
#include "intel_batchbuffer.h"
#include "intel_mipmap_tree.h"
#define FILE_DEBUG_FLAG DEBUG_BLIT
static void
intel_miptree_set_alpha_to_one(struct intel_context *intel,
struct intel_mipmap_tree *mt,
int x, int y, int width, int height);
static GLuint translate_raster_op(GLenum logicop)
{
switch(logicop) {
case GL_CLEAR: return 0x00;
case GL_AND: return 0x88;
case GL_AND_REVERSE: return 0x44;
case GL_COPY: return 0xCC;
case GL_AND_INVERTED: return 0x22;
case GL_NOOP: return 0xAA;
case GL_XOR: return 0x66;
case GL_OR: return 0xEE;
case GL_NOR: return 0x11;
case GL_EQUIV: return 0x99;
case GL_INVERT: return 0x55;
case GL_OR_REVERSE: return 0xDD;
case GL_COPY_INVERTED: return 0x33;
case GL_OR_INVERTED: return 0xBB;
case GL_NAND: return 0x77;
case GL_SET: return 0xFF;
default: return 0;
}
}
static uint32_t
br13_for_cpp(int cpp)
{
switch (cpp) {
case 4:
return BR13_8888;
break;
case 2:
return BR13_565;
break;
case 1:
return BR13_8;
break;
default:
assert(0);
return 0;
}
}
/**
* Emits the packet for switching the blitter from X to Y tiled or back.
*
* This has to be called in a single BEGIN_BATCH_BLT_TILED() /
* ADVANCE_BATCH_TILED(). This is because BCS_SWCTRL is saved and restored as
* part of the power context, not a render context, and if the batchbuffer was
* to get flushed between setting and blitting, or blitting and restoring, our
* tiling state would leak into other unsuspecting applications (like the X
* server).
*/
static void
set_blitter_tiling(struct intel_context *intel,
bool dst_y_tiled, bool src_y_tiled)
{
assert(intel->gen >= 6);
/* Idle the blitter before we update how tiling is interpreted. */
OUT_BATCH(MI_FLUSH_DW);
OUT_BATCH(0);
OUT_BATCH(0);
OUT_BATCH(0);
OUT_BATCH(MI_LOAD_REGISTER_IMM | (3 - 2));
OUT_BATCH(BCS_SWCTRL);
OUT_BATCH((BCS_SWCTRL_DST_Y | BCS_SWCTRL_SRC_Y) << 16 |
(dst_y_tiled ? BCS_SWCTRL_DST_Y : 0) |
(src_y_tiled ? BCS_SWCTRL_SRC_Y : 0));
}
#define BEGIN_BATCH_BLT_TILED(n, dst_y_tiled, src_y_tiled) do { \
BEGIN_BATCH_BLT(n + ((dst_y_tiled || src_y_tiled) ? 14 : 0)); \
if (dst_y_tiled || src_y_tiled) \
set_blitter_tiling(intel, dst_y_tiled, src_y_tiled); \
} while (0)
#define ADVANCE_BATCH_TILED(dst_y_tiled, src_y_tiled) do { \
if (dst_y_tiled || src_y_tiled) \
set_blitter_tiling(intel, false, false); \
ADVANCE_BATCH(); \
} while (0)
/**
* Implements a rectangular block transfer (blit) of pixels between two
* miptrees.
*
* Our blitter can operate on 1, 2, or 4-byte-per-pixel data, with generous,
* but limited, pitches and sizes allowed.
*
* The src/dst coordinates are relative to the given level/slice of the
* miptree.
*
* If @src_flip or @dst_flip is set, then the rectangle within that miptree
* will be inverted (including scanline order) when copying. This is common
* in GL when copying between window system and user-created
* renderbuffers/textures.
*/
bool
intel_miptree_blit(struct intel_context *intel,
struct intel_mipmap_tree *src_mt,
int src_level, int src_slice,
uint32_t src_x, uint32_t src_y, bool src_flip,
struct intel_mipmap_tree *dst_mt,
int dst_level, int dst_slice,
uint32_t dst_x, uint32_t dst_y, bool dst_flip,
uint32_t width, uint32_t height,
GLenum logicop)
{
/* No sRGB decode or encode is done by the hardware blitter, which is
* consistent with what we want in the callers (glCopyTexSubImage(),
* glBlitFramebuffer(), texture validation, etc.).
*/
gl_format src_format = _mesa_get_srgb_format_linear(src_mt->format);
gl_format dst_format = _mesa_get_srgb_format_linear(dst_mt->format);
/* The blitter doesn't support doing any format conversions. We do also
* support blitting ARGB8888 to XRGB8888 (trivial, the values dropped into
* the X channel don't matter), and XRGB8888 to ARGB8888 by setting the A
* channel to 1.0 at the end.
*/
if (src_format != dst_format &&
((src_format != MESA_FORMAT_ARGB8888 &&
src_format != MESA_FORMAT_XRGB8888) ||
(dst_format != MESA_FORMAT_ARGB8888 &&
dst_format != MESA_FORMAT_XRGB8888))) {
perf_debug("%s: Can't use hardware blitter from %s to %s, "
"falling back.\n", __FUNCTION__,
_mesa_get_format_name(src_format),
_mesa_get_format_name(dst_format));
return false;
}
/* According to the Ivy Bridge PRM, Vol1 Part4, section 1.2.1.2 (Graphics
* Data Size Limitations):
*
* The BLT engine is capable of transferring very large quantities of
* graphics data. Any graphics data read from and written to the
* destination is permitted to represent a number of pixels that
* occupies up to 65,536 scan lines and up to 32,768 bytes per scan line
* at the destination. The maximum number of pixels that may be
* represented per scan lines worth of graphics data depends on the
* color depth.
*
* Furthermore, intelEmitCopyBlit (which is called below) uses a signed
* 16-bit integer to represent buffer pitch, so it can only handle buffer
* pitches < 32k.
*
* As a result of these two limitations, we can only use the blitter to do
* this copy when the region's pitch is less than 32k.
*/
if (src_mt->region->pitch > 32768 ||
dst_mt->region->pitch > 32768) {
perf_debug("Falling back due to >32k pitch\n");
return false;
}
/* The blitter has no idea about HiZ or fast color clears, so we need to
* resolve the miptrees before we do anything.
*/
intel_miptree_slice_resolve_depth(intel, src_mt, src_level, src_slice);
intel_miptree_slice_resolve_depth(intel, dst_mt, dst_level, dst_slice);
intel_miptree_resolve_color(intel, src_mt);
intel_miptree_resolve_color(intel, dst_mt);
if (src_flip)
src_y = src_mt->level[src_level].height - src_y - height;
if (dst_flip)
dst_y = dst_mt->level[dst_level].height - dst_y - height;
int src_pitch = src_mt->region->pitch;
if (src_flip != dst_flip)
src_pitch = -src_pitch;
uint32_t src_image_x, src_image_y;
intel_miptree_get_image_offset(src_mt, src_level, src_slice,
&src_image_x, &src_image_y);
src_x += src_image_x;
src_y += src_image_y;
uint32_t dst_image_x, dst_image_y;
intel_miptree_get_image_offset(dst_mt, dst_level, dst_slice,
&dst_image_x, &dst_image_y);
dst_x += dst_image_x;
dst_y += dst_image_y;
if (!intelEmitCopyBlit(intel,
src_mt->cpp,
src_pitch,
src_mt->region->bo, src_mt->offset,
src_mt->region->tiling,
dst_mt->region->pitch,
dst_mt->region->bo, dst_mt->offset,
dst_mt->region->tiling,
src_x, src_y,
dst_x, dst_y,
width, height,
logicop)) {
return false;
}
if (src_mt->format == MESA_FORMAT_XRGB8888 &&
dst_mt->format == MESA_FORMAT_ARGB8888) {
intel_miptree_set_alpha_to_one(intel, dst_mt,
dst_x, dst_y,
width, height);
}
return true;
}
/* Copy BitBlt
*/
bool
intelEmitCopyBlit(struct intel_context *intel,
GLuint cpp,
GLshort src_pitch,
drm_intel_bo *src_buffer,
GLuint src_offset,
uint32_t src_tiling,
GLshort dst_pitch,
drm_intel_bo *dst_buffer,
GLuint dst_offset,
uint32_t dst_tiling,
GLshort src_x, GLshort src_y,
GLshort dst_x, GLshort dst_y,
GLshort w, GLshort h,
GLenum logic_op)
{
GLuint CMD, BR13, pass = 0;
int dst_y2 = dst_y + h;
int dst_x2 = dst_x + w;
drm_intel_bo *aper_array[3];
bool dst_y_tiled = dst_tiling == I915_TILING_Y;
bool src_y_tiled = src_tiling == I915_TILING_Y;
BATCH_LOCALS;
if (dst_tiling != I915_TILING_NONE) {
if (dst_offset & 4095)
return false;
}
if (src_tiling != I915_TILING_NONE) {
if (src_offset & 4095)
return false;
}
if ((dst_y_tiled || src_y_tiled) && intel->gen < 6)
return false;
/* do space check before going any further */
do {
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);
pass++;
} else
break;
} while (pass < 2);
if (pass >= 2)
return false;
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,
dst_buffer, dst_pitch, dst_offset, dst_x, dst_y, w, h);
/* Blit pitch must be dword-aligned. Otherwise, the hardware appears to drop
* the low bits.
*/
if (src_pitch % 4 != 0 || dst_pitch % 4 != 0)
return false;
/* For big formats (such as floating point), do the copy using 16 or 32bpp
* and multiply the coordinates.
*/
if (cpp > 4) {
if (cpp % 4 == 2) {
dst_x *= cpp / 2;
dst_x2 *= cpp / 2;
src_x *= cpp / 2;
cpp = 2;
} else {
assert(cpp % 4 == 0);
dst_x *= cpp / 4;
dst_x2 *= cpp / 4;
src_x *= cpp / 4;
cpp = 4;
}
}
BR13 = br13_for_cpp(cpp) | translate_raster_op(logic_op) << 16;
switch (cpp) {
case 1:
case 2:
CMD = XY_SRC_COPY_BLT_CMD;
break;
case 4:
CMD = XY_SRC_COPY_BLT_CMD | XY_BLT_WRITE_ALPHA | XY_BLT_WRITE_RGB;
break;
default:
return false;
}
#ifndef I915
if (dst_tiling != I915_TILING_NONE) {
CMD |= XY_DST_TILED;
dst_pitch /= 4;
}
if (src_tiling != I915_TILING_NONE) {
CMD |= XY_SRC_TILED;
src_pitch /= 4;
}
#endif
if (dst_y2 <= dst_y || dst_x2 <= dst_x) {
return true;
}
assert(dst_x < dst_x2);
assert(dst_y < dst_y2);
BEGIN_BATCH_BLT_TILED(8, dst_y_tiled, src_y_tiled);
OUT_BATCH(CMD | (8 - 2));
OUT_BATCH(BR13 | (uint16_t)dst_pitch);
OUT_BATCH((dst_y << 16) | dst_x);
OUT_BATCH((dst_y2 << 16) | dst_x2);
OUT_RELOC_FENCED(dst_buffer,
I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER,
dst_offset);
OUT_BATCH((src_y << 16) | src_x);
OUT_BATCH((uint16_t)src_pitch);
OUT_RELOC_FENCED(src_buffer,
I915_GEM_DOMAIN_RENDER, 0,
src_offset);
ADVANCE_BATCH_TILED(dst_y_tiled, src_y_tiled);
intel_batchbuffer_emit_mi_flush(intel);
return true;
}
/**
* Use blitting to clear the renderbuffers named by 'flags'.
* Note: we can't use the ctx->DrawBuffer->_ColorDrawBufferIndexes field
* since that might include software renderbuffers or renderbuffers
* which we're clearing with triangles.
* \param mask bitmask of BUFFER_BIT_* values indicating buffers to clear
*/
GLbitfield
intelClearWithBlit(struct gl_context *ctx, GLbitfield mask)
{
struct intel_context *intel = intel_context(ctx);
struct gl_framebuffer *fb = ctx->DrawBuffer;
GLuint clear_depth_value, clear_depth_mask;
GLint cx, cy, cw, ch;
GLbitfield fail_mask = 0;
BATCH_LOCALS;
/* Note: we don't use this function on Gen7+ hardware, so we can safely
* ignore fast color clear issues.
*/
assert(intel->gen < 7);
/*
* Compute values for clearing the buffers.
*/
clear_depth_value = 0;
clear_depth_mask = 0;
if (mask & BUFFER_BIT_DEPTH) {
clear_depth_value = (GLuint) (fb->_DepthMax * ctx->Depth.Clear);
clear_depth_mask = XY_BLT_WRITE_RGB;
}
if (mask & BUFFER_BIT_STENCIL) {
clear_depth_value |= (ctx->Stencil.Clear & 0xff) << 24;
clear_depth_mask |= XY_BLT_WRITE_ALPHA;
}
cx = fb->_Xmin;
if (_mesa_is_winsys_fbo(fb))
cy = ctx->DrawBuffer->Height - fb->_Ymax;
else
cy = fb->_Ymin;
cw = fb->_Xmax - fb->_Xmin;
ch = fb->_Ymax - fb->_Ymin;
if (cw == 0 || ch == 0)
return 0;
/* Loop over all renderbuffers */
mask &= (1 << BUFFER_COUNT) - 1;
while (mask) {
GLuint buf = ffs(mask) - 1;
bool is_depth_stencil = buf == BUFFER_DEPTH || buf == BUFFER_STENCIL;
struct intel_renderbuffer *irb;
int x1, y1, x2, y2;
uint32_t clear_val;
uint32_t BR13, CMD;
struct intel_region *region;
int pitch, cpp;
drm_intel_bo *aper_array[2];
mask &= ~(1 << buf);
irb = intel_get_renderbuffer(fb, buf);
if (irb && irb->mt) {
region = irb->mt->region;
assert(region);
assert(region->bo);
} else {
fail_mask |= 1 << buf;
continue;
}
/* OK, clear this renderbuffer */
x1 = cx + irb->draw_x;
y1 = cy + irb->draw_y;
x2 = cx + cw + irb->draw_x;
y2 = cy + ch + irb->draw_y;
pitch = region->pitch;
cpp = region->cpp;
DBG("%s dst:buf(%p)/%d %d,%d sz:%dx%d\n",
__FUNCTION__,
region->bo, pitch,
x1, y1, x2 - x1, y2 - y1);
BR13 = 0xf0 << 16;
CMD = XY_COLOR_BLT_CMD;
/* Setup the blit command */
if (cpp == 4) {
if (is_depth_stencil) {
CMD |= clear_depth_mask;
} else {
/* clearing RGBA */
CMD |= XY_BLT_WRITE_ALPHA | XY_BLT_WRITE_RGB;
}
}
assert(region->tiling != I915_TILING_Y);
#ifndef I915
if (region->tiling != I915_TILING_NONE) {
CMD |= XY_DST_TILED;
pitch /= 4;
}
#endif
BR13 |= pitch;
if (is_depth_stencil) {
clear_val = clear_depth_value;
} else {
uint8_t clear[4];
GLfloat *color = ctx->Color.ClearColor.f;
_mesa_unclamped_float_rgba_to_ubyte(clear, color);
switch (intel_rb_format(irb)) {
case MESA_FORMAT_ARGB8888:
case MESA_FORMAT_XRGB8888:
clear_val = PACK_COLOR_8888(clear[3], clear[0],
clear[1], clear[2]);
break;
case MESA_FORMAT_RGB565:
clear_val = PACK_COLOR_565(clear[0], clear[1], clear[2]);
break;
case MESA_FORMAT_ARGB4444:
clear_val = PACK_COLOR_4444(clear[3], clear[0],
clear[1], clear[2]);
break;
case MESA_FORMAT_ARGB1555:
clear_val = PACK_COLOR_1555(clear[3], clear[0],
clear[1], clear[2]);
break;
case MESA_FORMAT_A8:
clear_val = PACK_COLOR_8888(clear[3], clear[3],
clear[3], clear[3]);
break;
default:
fail_mask |= 1 << buf;
continue;
}
}
BR13 |= br13_for_cpp(cpp);
assert(x1 < x2);
assert(y1 < y2);
/* do space check before going any further */
aper_array[0] = intel->batch.bo;
aper_array[1] = region->bo;
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 | (6 - 2));
OUT_BATCH(BR13);
OUT_BATCH((y1 << 16) | x1);
OUT_BATCH((y2 << 16) | x2);
OUT_RELOC_FENCED(region->bo,
I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER,
0);
OUT_BATCH(clear_val);
ADVANCE_BATCH();
if (intel->always_flush_cache)
intel_batchbuffer_emit_mi_flush(intel);
if (buf == BUFFER_DEPTH || buf == BUFFER_STENCIL)
mask &= ~(BUFFER_BIT_DEPTH | BUFFER_BIT_STENCIL);
}
return fail_mask;
}
bool
intelEmitImmediateColorExpandBlit(struct intel_context *intel,
GLuint cpp,
GLubyte *src_bits, GLuint src_size,
GLuint fg_color,
GLshort dst_pitch,
drm_intel_bo *dst_buffer,
GLuint dst_offset,
uint32_t dst_tiling,
GLshort x, GLshort y,
GLshort w, GLshort h,
GLenum logic_op)
{
int dwords = ALIGN(src_size, 8) / 4;
uint32_t opcode, br13, blit_cmd;
if (dst_tiling != I915_TILING_NONE) {
if (dst_offset & 4095)
return false;
if (dst_tiling == I915_TILING_Y)
return false;
}
assert( logic_op - GL_CLEAR >= 0 );
assert( logic_op - GL_CLEAR < 0x10 );
assert(dst_pitch > 0);
if (w < 0 || h < 0)
return true;
DBG("%s dst:buf(%p)/%d+%d %d,%d sz:%dx%d, %d bytes %d dwords\n",
__FUNCTION__,
dst_buffer, dst_pitch, dst_offset, x, y, w, h, src_size, dwords);
intel_batchbuffer_require_space(intel,
(8 * 4) +
(3 * 4) +
dwords * 4, true);
opcode = XY_SETUP_BLT_CMD;
if (cpp == 4)
opcode |= XY_BLT_WRITE_ALPHA | XY_BLT_WRITE_RGB;
#ifndef I915
if (dst_tiling != I915_TILING_NONE) {
opcode |= XY_DST_TILED;
dst_pitch /= 4;
}
#endif
br13 = dst_pitch | (translate_raster_op(logic_op) << 16) | (1 << 29);
br13 |= br13_for_cpp(cpp);
blit_cmd = XY_TEXT_IMMEDIATE_BLIT_CMD | XY_TEXT_BYTE_PACKED; /* packing? */
if (dst_tiling != I915_TILING_NONE)
blit_cmd |= XY_DST_TILED;
BEGIN_BATCH_BLT(8 + 3);
OUT_BATCH(opcode | (8 - 2));
OUT_BATCH(br13);
OUT_BATCH((0 << 16) | 0); /* clip x1, y1 */
OUT_BATCH((100 << 16) | 100); /* clip x2, y2 */
OUT_RELOC_FENCED(dst_buffer,
I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER,
dst_offset);
OUT_BATCH(0); /* bg */
OUT_BATCH(fg_color); /* fg */
OUT_BATCH(0); /* pattern base addr */
OUT_BATCH(blit_cmd | ((3 - 2) + dwords));
OUT_BATCH((y << 16) | x);
OUT_BATCH(((y + h) << 16) | (x + w));
ADVANCE_BATCH();
intel_batchbuffer_data(intel, src_bits, dwords * 4, true);
intel_batchbuffer_emit_mi_flush(intel);
return true;
}
/* We don't have a memmove-type blit like some other hardware, so we'll do a
* rectangular blit covering a large space, then emit 1-scanline blit at the
* end to cover the last if we need.
*/
void
intel_emit_linear_blit(struct intel_context *intel,
drm_intel_bo *dst_bo,
unsigned int dst_offset,
drm_intel_bo *src_bo,
unsigned int src_offset,
unsigned int size)
{
struct gl_context *ctx = &intel->ctx;
GLuint pitch, height;
bool ok;
/* 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
*/
pitch = ROUND_DOWN_TO(MIN2(size, (1 << 15) - 1), 4);
height = (pitch == 0) ? 1 : size / pitch;
ok = intelEmitCopyBlit(intel, 1,
pitch, src_bo, src_offset, I915_TILING_NONE,
pitch, dst_bo, dst_offset, I915_TILING_NONE,
0, 0, /* src x/y */
0, 0, /* dst x/y */
pitch, height, /* w, h */
GL_COPY);
if (!ok)
_mesa_problem(ctx, "Failed to linear blit %dx%d\n", pitch, height);
src_offset += pitch * height;
dst_offset += pitch * height;
size -= pitch * height;
assert (size < (1 << 15));
pitch = ALIGN(size, 4);
if (size != 0) {
ok = intelEmitCopyBlit(intel, 1,
pitch, src_bo, src_offset, I915_TILING_NONE,
pitch, dst_bo, dst_offset, I915_TILING_NONE,
0, 0, /* src x/y */
0, 0, /* dst x/y */
size, 1, /* w, h */
GL_COPY);
if (!ok)
_mesa_problem(ctx, "Failed to linear blit %dx%d\n", size, 1);
}
}
/**
* Used to initialize the alpha value of an ARGB8888 miptree after copying
* into it from an XRGB8888 source.
*
* This is very common with glCopyTexImage2D(). Note that the coordinates are
* relative to the start of the miptree, not relative to a slice within the
* miptree.
*/
static void
intel_miptree_set_alpha_to_one(struct intel_context *intel,
struct intel_mipmap_tree *mt,
int x, int y, int width, int height)
{
struct intel_region *region = mt->region;
uint32_t BR13, CMD;
int pitch, cpp;
drm_intel_bo *aper_array[2];
BATCH_LOCALS;
pitch = region->pitch;
cpp = region->cpp;
DBG("%s dst:buf(%p)/%d %d,%d sz:%dx%d\n",
__FUNCTION__, region->bo, pitch, x, y, width, height);
BR13 = br13_for_cpp(cpp) | 0xf0 << 16;
CMD = XY_COLOR_BLT_CMD;
CMD |= XY_BLT_WRITE_ALPHA;
#ifndef I915
if (region->tiling != I915_TILING_NONE) {
CMD |= XY_DST_TILED;
pitch /= 4;
}
#endif
BR13 |= pitch;
/* do space check before going any further */
aper_array[0] = intel->batch.bo;
aper_array[1] = region->bo;
if (drm_intel_bufmgr_check_aperture_space(aper_array,
ARRAY_SIZE(aper_array)) != 0) {
intel_batchbuffer_flush(intel);
}
bool dst_y_tiled = region->tiling == I915_TILING_Y;
BEGIN_BATCH_BLT_TILED(6, dst_y_tiled, false);
OUT_BATCH(CMD | (6 - 2));
OUT_BATCH(BR13);
OUT_BATCH((y << 16) | x);
OUT_BATCH(((y + height) << 16) | (x + width));
OUT_RELOC_FENCED(region->bo,
I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER,
0);
OUT_BATCH(0xffffffff); /* white, but only alpha gets written */
ADVANCE_BATCH_TILED(dst_y_tiled, false);
intel_batchbuffer_emit_mi_flush(intel);
}

View file

@ -0,0 +1,83 @@
/**************************************************************************
*
* Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sub license, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial portions
* of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
**************************************************************************/
#ifndef INTEL_BLIT_H
#define INTEL_BLIT_H
#include "intel_context.h"
extern void intelCopyBuffer(const __DRIdrawable * dpriv,
const drm_clip_rect_t * rect);
extern GLbitfield intelClearWithBlit(struct gl_context * ctx, GLbitfield mask);
bool
intelEmitCopyBlit(struct intel_context *intel,
GLuint cpp,
GLshort src_pitch,
drm_intel_bo *src_buffer,
GLuint src_offset,
uint32_t src_tiling,
GLshort dst_pitch,
drm_intel_bo *dst_buffer,
GLuint dst_offset,
uint32_t dst_tiling,
GLshort srcx, GLshort srcy,
GLshort dstx, GLshort dsty,
GLshort w, GLshort h,
GLenum logicop );
bool intel_miptree_blit(struct intel_context *intel,
struct intel_mipmap_tree *src_mt,
int src_level, int src_slice,
uint32_t src_x, uint32_t src_y, bool src_flip,
struct intel_mipmap_tree *dst_mt,
int dst_level, int dst_slice,
uint32_t dst_x, uint32_t dst_y, bool dst_flip,
uint32_t width, uint32_t height,
GLenum logicop);
bool
intelEmitImmediateColorExpandBlit(struct intel_context *intel,
GLuint cpp,
GLubyte *src_bits, GLuint src_size,
GLuint fg_color,
GLshort dst_pitch,
drm_intel_bo *dst_buffer,
GLuint dst_offset,
uint32_t dst_tiling,
GLshort x, GLshort y,
GLshort w, GLshort h,
GLenum logic_op);
void intel_emit_linear_blit(struct intel_context *intel,
drm_intel_bo *dst_bo,
unsigned int dst_offset,
drm_intel_bo *src_bo,
unsigned int src_offset,
unsigned int size);
#endif

View file

@ -1 +0,0 @@
../intel/intel_buffer_objects.c

View file

@ -0,0 +1,853 @@
/**************************************************************************
*
* Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sub license, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial portions
* of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
**************************************************************************/
#include "main/imports.h"
#include "main/mtypes.h"
#include "main/macros.h"
#include "main/bufferobj.h"
#include "intel_blit.h"
#include "intel_buffer_objects.h"
#include "intel_batchbuffer.h"
#include "intel_context.h"
#include "intel_fbo.h"
#include "intel_mipmap_tree.h"
#include "intel_regions.h"
#ifndef I915
#include "brw_context.h"
#endif
static GLboolean
intel_bufferobj_unmap(struct gl_context * ctx, struct gl_buffer_object *obj);
/** Allocates a new drm_intel_bo to store the data for the buffer object. */
static void
intel_bufferobj_alloc_buffer(struct intel_context *intel,
struct intel_buffer_object *intel_obj)
{
intel_obj->buffer = drm_intel_bo_alloc(intel->bufmgr, "bufferobj",
intel_obj->Base.Size, 64);
#ifndef I915
/* the buffer might be bound as a uniform buffer, need to update it
*/
{
struct brw_context *brw = brw_context(&intel->ctx);
brw->state.dirty.brw |= BRW_NEW_UNIFORM_BUFFER;
}
#endif
}
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
* lookup an opaque structure. It would be nice if the handles and
* internal structure where somehow shared.
*/
static struct gl_buffer_object *
intel_bufferobj_alloc(struct gl_context * ctx, GLuint name, GLenum target)
{
struct intel_buffer_object *obj = CALLOC_STRUCT(intel_buffer_object);
_mesa_initialize_buffer_object(ctx, &obj->Base, name, target);
obj->buffer = NULL;
return &obj->Base;
}
/**
* Deallocate/free a vertex/pixel buffer object.
* Called via glDeleteBuffersARB().
*/
static void
intel_bufferobj_free(struct gl_context * ctx, struct gl_buffer_object *obj)
{
struct intel_buffer_object *intel_obj = intel_buffer_object(obj);
assert(intel_obj);
/* Buffer objects are automatically unmapped when deleting according
* to the spec, but Mesa doesn't do UnmapBuffer for us at context destroy
* (though it does if you call glDeleteBuffers)
*/
if (obj->Pointer)
intel_bufferobj_unmap(ctx, obj);
free(intel_obj->sys_buffer);
drm_intel_bo_unreference(intel_obj->buffer);
free(intel_obj);
}
/**
* Allocate space for and store data in a buffer object. Any data that was
* previously stored in the buffer object is lost. If data is NULL,
* memory will be allocated, but no copy will occur.
* Called via ctx->Driver.BufferData().
* \return true for success, false if out of memory
*/
static GLboolean
intel_bufferobj_data(struct gl_context * ctx,
GLenum target,
GLsizeiptrARB size,
const GLvoid * data,
GLenum usage, struct gl_buffer_object *obj)
{
struct intel_context *intel = intel_context(ctx);
struct intel_buffer_object *intel_obj = intel_buffer_object(obj);
/* Part of the ABI, but this function doesn't use it.
*/
#ifndef I915
(void) target;
#endif
intel_obj->Base.Size = size;
intel_obj->Base.Usage = usage;
assert(!obj->Pointer); /* Mesa should have unmapped it */
if (intel_obj->buffer != NULL)
release_buffer(intel_obj);
free(intel_obj->sys_buffer);
intel_obj->sys_buffer = NULL;
if (size != 0) {
#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) {
intel_obj->sys_buffer = malloc(size);
if (intel_obj->sys_buffer != NULL) {
if (data != NULL)
memcpy(intel_obj->sys_buffer, data, size);
return true;
}
}
#endif
intel_bufferobj_alloc_buffer(intel, intel_obj);
if (!intel_obj->buffer)
return false;
if (data != NULL)
drm_intel_bo_subdata(intel_obj->buffer, 0, size, data);
}
return true;
}
/**
* Replace data in a subrange of buffer object. If the data range
* specified by size + offset extends beyond the end of the buffer or
* if data is NULL, no copy is performed.
* Called via glBufferSubDataARB().
*/
static void
intel_bufferobj_subdata(struct gl_context * ctx,
GLintptrARB offset,
GLsizeiptrARB size,
const GLvoid * data, struct gl_buffer_object *obj)
{
struct intel_context *intel = intel_context(ctx);
struct intel_buffer_object *intel_obj = intel_buffer_object(obj);
bool busy;
if (size == 0)
return;
assert(intel_obj);
/* If we have a single copy in system memory, update that */
if (intel_obj->sys_buffer) {
if (intel_obj->source)
release_buffer(intel_obj);
if (intel_obj->buffer == NULL) {
memcpy((char *)intel_obj->sys_buffer + offset, data, size);
return;
}
free(intel_obj->sys_buffer);
intel_obj->sys_buffer = NULL;
}
/* 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);
if (busy) {
if (size == intel_obj->Base.Size) {
/* Replace the current busy bo with fresh data. */
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 {
perf_debug("Using a blit copy to avoid stalling on %ldb "
"glBufferSubData() to a busy buffer object.\n",
(long)size);
drm_intel_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 {
drm_intel_bo_subdata(intel_obj->buffer, offset, size, data);
}
}
/**
* Called via glGetBufferSubDataARB().
*/
static void
intel_bufferobj_get_subdata(struct gl_context * ctx,
GLintptrARB offset,
GLsizeiptrARB size,
GLvoid * data, struct gl_buffer_object *obj)
{
struct intel_buffer_object *intel_obj = intel_buffer_object(obj);
struct intel_context *intel = intel_context(ctx);
assert(intel_obj);
if (intel_obj->sys_buffer)
memcpy(data, (char *)intel_obj->sys_buffer + offset, size);
else {
if (drm_intel_bo_references(intel->batch.bo, intel_obj->buffer)) {
intel_batchbuffer_flush(intel);
}
drm_intel_bo_get_subdata(intel_obj->buffer, offset, size, data);
}
}
/**
* Called via glMapBufferRange and glMapBuffer
*
* The goal of this extension is to allow apps to accumulate their rendering
* at the same time as they accumulate their buffer object. Without it,
* you'd end up blocking on execution of rendering every time you mapped
* the buffer to put new data in.
*
* We support it in 3 ways: If unsynchronized, then don't bother
* flushing the batchbuffer before mapping the buffer, which can save blocking
* in many cases. If we would still block, and they allow the whole buffer
* to be invalidated, then just allocate a new buffer to replace the old one.
* If not, and we'd block, and they allow the subrange of the buffer to be
* invalidated, then we can make a new little BO, let them write into that,
* and blit it into the real BO at unmap time.
*/
static void *
intel_bufferobj_map_range(struct gl_context * ctx,
GLintptr offset, GLsizeiptr length,
GLbitfield access, struct gl_buffer_object *obj)
{
struct intel_context *intel = intel_context(ctx);
struct intel_buffer_object *intel_obj = intel_buffer_object(obj);
assert(intel_obj);
/* _mesa_MapBufferRange (GL entrypoint) sets these, but the vbo module also
* internally uses our functions directly.
*/
obj->Offset = offset;
obj->Length = length;
obj->AccessFlags = access;
if (intel_obj->sys_buffer) {
const bool read_only =
(access & (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT)) == GL_MAP_READ_BIT;
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->buffer == NULL) {
obj->Pointer = NULL;
return NULL;
}
/* If the access is synchronized (like a normal buffer mapping), then get
* things flushed out so the later mapping syncs appropriately through GEM.
* If the user doesn't care about existing buffer contents and mapping would
* cause us to block, then throw out the old buffer.
*
* If they set INVALIDATE_BUFFER, we can pitch the current contents to
* achieve the required synchronization.
*/
if (!(access & GL_MAP_UNSYNCHRONIZED_BIT)) {
if (drm_intel_bo_references(intel->batch.bo, intel_obj->buffer)) {
if (access & GL_MAP_INVALIDATE_BUFFER_BIT) {
drm_intel_bo_unreference(intel_obj->buffer);
intel_bufferobj_alloc_buffer(intel, intel_obj);
} else {
perf_debug("Stalling on the GPU for mapping a busy buffer "
"object\n");
intel_flush(ctx);
}
} else if (drm_intel_bo_busy(intel_obj->buffer) &&
(access & GL_MAP_INVALIDATE_BUFFER_BIT)) {
drm_intel_bo_unreference(intel_obj->buffer);
intel_bufferobj_alloc_buffer(intel, intel_obj);
}
}
/* If the user is mapping a range of an active buffer object but
* doesn't require the current contents of that range, make a new
* BO, and we'll copy what they put in there out at unmap or
* FlushRange time.
*/
if ((access & GL_MAP_INVALIDATE_RANGE_BIT) &&
drm_intel_bo_busy(intel_obj->buffer)) {
if (access & GL_MAP_FLUSH_EXPLICIT_BIT) {
intel_obj->range_map_buffer = malloc(length);
obj->Pointer = intel_obj->range_map_buffer;
} else {
intel_obj->range_map_bo = drm_intel_bo_alloc(intel->bufmgr,
"range map",
length, 64);
if (!(access & GL_MAP_READ_BIT)) {
drm_intel_gem_bo_map_gtt(intel_obj->range_map_bo);
} else {
drm_intel_bo_map(intel_obj->range_map_bo,
(access & GL_MAP_WRITE_BIT) != 0);
}
obj->Pointer = intel_obj->range_map_bo->virtual;
}
return obj->Pointer;
}
if (access & GL_MAP_UNSYNCHRONIZED_BIT)
drm_intel_gem_bo_map_unsynchronized(intel_obj->buffer);
else if (!(access & GL_MAP_READ_BIT)) {
drm_intel_gem_bo_map_gtt(intel_obj->buffer);
} else {
drm_intel_bo_map(intel_obj->buffer, (access & GL_MAP_WRITE_BIT) != 0);
}
obj->Pointer = intel_obj->buffer->virtual + offset;
return obj->Pointer;
}
/* Ideally we'd use a BO to avoid taking up cache space for the temporary
* data, but FlushMappedBufferRange may be followed by further writes to
* the pointer, so we would have to re-map after emitting our blit, which
* would defeat the point.
*/
static void
intel_bufferobj_flush_mapped_range(struct gl_context *ctx,
GLintptr offset, GLsizeiptr length,
struct gl_buffer_object *obj)
{
struct intel_context *intel = intel_context(ctx);
struct intel_buffer_object *intel_obj = intel_buffer_object(obj);
drm_intel_bo *temp_bo;
/* Unless we're in the range map using a temporary system buffer,
* there's no work to do.
*/
if (intel_obj->range_map_buffer == NULL)
return;
if (length == 0)
return;
temp_bo = drm_intel_bo_alloc(intel->bufmgr, "range map flush", length, 64);
drm_intel_bo_subdata(temp_bo, 0, length, intel_obj->range_map_buffer);
intel_emit_linear_blit(intel,
intel_obj->buffer, obj->Offset + offset,
temp_bo, 0,
length);
drm_intel_bo_unreference(temp_bo);
}
/**
* Called via glUnmapBuffer().
*/
static GLboolean
intel_bufferobj_unmap(struct gl_context * ctx, struct gl_buffer_object *obj)
{
struct intel_context *intel = intel_context(ctx);
struct intel_buffer_object *intel_obj = intel_buffer_object(obj);
assert(intel_obj);
assert(obj->Pointer);
if (intel_obj->sys_buffer != NULL) {
/* always keep the mapping around. */
} else if (intel_obj->range_map_buffer != NULL) {
/* 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);
free(intel_obj->range_map_buffer);
intel_obj->range_map_buffer = NULL;
} else if (intel_obj->range_map_bo != NULL) {
drm_intel_bo_unmap(intel_obj->range_map_bo);
intel_emit_linear_blit(intel,
intel_obj->buffer, obj->Offset,
intel_obj->range_map_bo, 0,
obj->Length);
/* 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);
drm_intel_bo_unreference(intel_obj->range_map_bo);
intel_obj->range_map_bo = NULL;
} else if (intel_obj->buffer != NULL) {
drm_intel_bo_unmap(intel_obj->buffer);
}
obj->Pointer = NULL;
obj->Offset = 0;
obj->Length = 0;
return true;
}
drm_intel_bo *
intel_bufferobj_buffer(struct intel_context *intel,
struct intel_buffer_object *intel_obj,
GLuint flag)
{
if (intel_obj->source)
release_buffer(intel_obj);
if (intel_obj->buffer == NULL) {
intel_bufferobj_alloc_buffer(intel, intel_obj);
drm_intel_bo_subdata(intel_obj->buffer,
0, intel_obj->Base.Size,
intel_obj->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;
}
static void
intel_bufferobj_copy_subdata(struct gl_context *ctx,
struct gl_buffer_object *src,
struct gl_buffer_object *dst,
GLintptr read_offset, GLintptr write_offset,
GLsizeiptr size)
{
struct intel_context *intel = intel_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;
/* If we're in system memory, just map and memcpy. */
if (intel_src->sys_buffer || intel_dst->sys_buffer) {
/* The same buffer may be used, but note that regions copied may
* not overlap.
*/
if (src == dst) {
char *ptr = intel_bufferobj_map_range(ctx, 0, dst->Size,
GL_MAP_READ_BIT |
GL_MAP_WRITE_BIT,
dst);
memmove(ptr + write_offset, ptr + read_offset, size);
intel_bufferobj_unmap(ctx, dst);
} else {
const char *src_ptr;
char *dst_ptr;
src_ptr = intel_bufferobj_map_range(ctx, 0, src->Size,
GL_MAP_READ_BIT, src);
dst_ptr = intel_bufferobj_map_range(ctx, 0, dst->Size,
GL_MAP_WRITE_BIT, dst);
memcpy(dst_ptr + write_offset, src_ptr + read_offset, size);
intel_bufferobj_unmap(ctx, src);
intel_bufferobj_unmap(ctx, dst);
}
return;
}
/* Otherwise, we have real BOs, so blit them. */
dst_bo = intel_bufferobj_buffer(intel, intel_dst, INTEL_WRITE_PART);
src_bo = intel_bufferobj_source(intel, intel_src, 64, &src_offset);
intel_emit_linear_blit(intel,
dst_bo, write_offset,
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);
}
static GLenum
intel_buffer_purgeable(drm_intel_bo *buffer)
{
int retained = 0;
if (buffer != NULL)
retained = drm_intel_bo_madvise (buffer, I915_MADV_DONTNEED);
return retained ? GL_VOLATILE_APPLE : GL_RELEASED_APPLE;
}
static GLenum
intel_buffer_object_purgeable(struct gl_context * ctx,
struct gl_buffer_object *obj,
GLenum option)
{
struct intel_buffer_object *intel_obj = intel_buffer_object (obj);
if (intel_obj->buffer != NULL)
return intel_buffer_purgeable(intel_obj->buffer);
if (option == GL_RELEASED_APPLE) {
free(intel_obj->sys_buffer);
intel_obj->sys_buffer = NULL;
return GL_RELEASED_APPLE;
} else {
/* XXX Create the buffer and madvise(MADV_DONTNEED)? */
struct intel_context *intel = intel_context(ctx);
drm_intel_bo *bo = intel_bufferobj_buffer(intel, intel_obj, INTEL_READ);
return intel_buffer_purgeable(bo);
}
}
static GLenum
intel_texture_object_purgeable(struct gl_context * ctx,
struct gl_texture_object *obj,
GLenum option)
{
struct intel_texture_object *intel;
(void) ctx;
(void) option;
intel = intel_texture_object(obj);
if (intel->mt == NULL || intel->mt->region == NULL)
return GL_RELEASED_APPLE;
return intel_buffer_purgeable(intel->mt->region->bo);
}
static GLenum
intel_render_object_purgeable(struct gl_context * ctx,
struct gl_renderbuffer *obj,
GLenum option)
{
struct intel_renderbuffer *intel;
(void) ctx;
(void) option;
intel = intel_renderbuffer(obj);
if (intel->mt == NULL)
return GL_RELEASED_APPLE;
return intel_buffer_purgeable(intel->mt->region->bo);
}
static GLenum
intel_buffer_unpurgeable(drm_intel_bo *buffer)
{
int retained;
retained = 0;
if (buffer != NULL)
retained = drm_intel_bo_madvise (buffer, I915_MADV_WILLNEED);
return retained ? GL_RETAINED_APPLE : GL_UNDEFINED_APPLE;
}
static GLenum
intel_buffer_object_unpurgeable(struct gl_context * ctx,
struct gl_buffer_object *obj,
GLenum option)
{
(void) ctx;
(void) option;
return intel_buffer_unpurgeable(intel_buffer_object (obj)->buffer);
}
static GLenum
intel_texture_object_unpurgeable(struct gl_context * ctx,
struct gl_texture_object *obj,
GLenum option)
{
struct intel_texture_object *intel;
(void) ctx;
(void) option;
intel = intel_texture_object(obj);
if (intel->mt == NULL || intel->mt->region == NULL)
return GL_UNDEFINED_APPLE;
return intel_buffer_unpurgeable(intel->mt->region->bo);
}
static GLenum
intel_render_object_unpurgeable(struct gl_context * ctx,
struct gl_renderbuffer *obj,
GLenum option)
{
struct intel_renderbuffer *intel;
(void) ctx;
(void) option;
intel = intel_renderbuffer(obj);
if (intel->mt == NULL)
return GL_UNDEFINED_APPLE;
return intel_buffer_unpurgeable(intel->mt->region->bo);
}
void
intelInitBufferObjectFuncs(struct dd_function_table *functions)
{
functions->NewBufferObject = intel_bufferobj_alloc;
functions->DeleteBuffer = intel_bufferobj_free;
functions->BufferData = intel_bufferobj_data;
functions->BufferSubData = intel_bufferobj_subdata;
functions->GetBufferSubData = intel_bufferobj_get_subdata;
functions->MapBufferRange = intel_bufferobj_map_range;
functions->FlushMappedBufferRange = intel_bufferobj_flush_mapped_range;
functions->UnmapBuffer = intel_bufferobj_unmap;
functions->CopyBufferSubData = intel_bufferobj_copy_subdata;
functions->BufferObjectPurgeable = intel_buffer_object_purgeable;
functions->TextureObjectPurgeable = intel_texture_object_purgeable;
functions->RenderObjectPurgeable = intel_render_object_purgeable;
functions->BufferObjectUnpurgeable = intel_buffer_object_unpurgeable;
functions->TextureObjectUnpurgeable = intel_texture_object_unpurgeable;
functions->RenderObjectUnpurgeable = intel_render_object_unpurgeable;
}

View file

@ -0,0 +1,92 @@
/**************************************************************************
*
* Copyright 2005 Tungsten Graphics, Inc., Cedar Park, Texas.
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sub license, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial portions
* of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
**************************************************************************/
#ifndef INTEL_BUFFEROBJ_H
#define INTEL_BUFFEROBJ_H
#include "main/mtypes.h"
struct intel_context;
struct gl_buffer_object;
/**
* Intel vertex/pixel buffer object, derived from Mesa's gl_buffer_object.
*/
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;
drm_intel_bo *range_map_bo;
void *range_map_buffer;
unsigned int range_map_offset;
GLsizei range_map_size;
bool source;
};
/* Get the bm buffer associated with a GL bufferobject:
*/
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:
*/
void intelInitBufferObjectFuncs(struct dd_function_table *functions);
static inline struct intel_buffer_object *
intel_buffer_object(struct gl_buffer_object *obj)
{
return (struct intel_buffer_object *) obj;
}
#endif

View file

@ -1 +0,0 @@
../intel/intel_buffers.c

View file

@ -0,0 +1,118 @@
/**************************************************************************
*
* Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sub license, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial portions
* of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
**************************************************************************/
#include "intel_context.h"
#include "intel_buffers.h"
#include "intel_fbo.h"
#include "intel_mipmap_tree.h"
#include "main/fbobject.h"
#include "main/framebuffer.h"
#include "main/renderbuffer.h"
/**
* Return pointer to current color reading region, or NULL.
*/
struct intel_region *
intel_readbuf_region(struct intel_context *intel)
{
struct intel_renderbuffer *irb
= intel_renderbuffer(intel->ctx.ReadBuffer->_ColorReadBuffer);
if (irb && irb->mt)
return irb->mt->region;
else
return NULL;
}
/**
* Check if we're about to draw into the front color buffer.
* If so, set the intel->front_buffer_dirty field to true.
*/
void
intel_check_front_buffer_rendering(struct intel_context *intel)
{
const struct gl_framebuffer *fb = intel->ctx.DrawBuffer;
if (_mesa_is_winsys_fbo(fb)) {
/* drawing to window system buffer */
if (fb->_NumColorDrawBuffers > 0) {
if (fb->_ColorDrawBufferIndexes[0] == BUFFER_FRONT_LEFT) {
intel->front_buffer_dirty = true;
}
}
}
}
static void
intelDrawBuffer(struct gl_context * ctx, GLenum mode)
{
if (ctx->DrawBuffer && _mesa_is_winsys_fbo(ctx->DrawBuffer)) {
struct intel_context *const intel = intel_context(ctx);
const bool was_front_buffer_rendering =
intel->is_front_buffer_rendering;
intel->is_front_buffer_rendering = (mode == GL_FRONT_LEFT)
|| (mode == GL_FRONT) || (mode == GL_FRONT_AND_BACK);
/* If we weren't front-buffer rendering before but we are now,
* invalidate our DRI drawable so we'll ask for new buffers
* (including the fake front) before we start rendering again.
*/
if (!was_front_buffer_rendering && intel->is_front_buffer_rendering)
dri2InvalidateDrawable(intel->driContext->driDrawablePriv);
}
intel_draw_buffer(ctx);
}
static void
intelReadBuffer(struct gl_context * ctx, GLenum mode)
{
if (ctx->DrawBuffer && _mesa_is_winsys_fbo(ctx->DrawBuffer)) {
struct intel_context *const intel = intel_context(ctx);
const bool was_front_buffer_reading =
intel->is_front_buffer_reading;
intel->is_front_buffer_reading = (mode == GL_FRONT_LEFT)
|| (mode == GL_FRONT);
/* If we weren't front-buffer reading before but we are now,
* invalidate our DRI drawable so we'll ask for new buffers
* (including the fake front) before we start reading again.
*/
if (!was_front_buffer_reading && intel->is_front_buffer_reading)
dri2InvalidateDrawable(intel->driContext->driReadablePriv);
}
}
void
intelInitBufferFuncs(struct dd_function_table *functions)
{
functions->DrawBuffer = intelDrawBuffer;
functions->ReadBuffer = intelReadBuffer;
}

View file

@ -0,0 +1,56 @@
/**************************************************************************
*
* Copyright 2006 Tungsten Graphics, Inc., Cedar Park, Texas.
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sub license, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial portions
* of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
**************************************************************************/
#ifndef INTEL_BUFFERS_H
#define INTEL_BUFFERS_H
#include "dri_util.h"
#include "drm.h"
#include "intel_context.h"
struct intel_context;
struct intel_framebuffer;
extern struct intel_region *intel_readbuf_region(struct intel_context *intel);
extern void intel_check_front_buffer_rendering(struct intel_context *intel);
static inline void
intel_draw_buffer(struct gl_context * ctx)
{
struct intel_context *intel = intel_context(ctx);
intel->vtbl.update_draw_buffer(intel);
}
extern void intelInitBufferFuncs(struct dd_function_table *functions);
#ifdef I915
void intelCalcViewport(struct gl_context * ctx);
#endif
#endif /* INTEL_BUFFERS_H */

View file

@ -0,0 +1,314 @@
/*
* Copyright © 2007 Intel Corporation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
* IN THE SOFTWARE.
*
* Authors:
* Eric Anholt <eric@anholt.net>
*
*/
#define PCI_CHIP_I810 0x7121
#define PCI_CHIP_I810_DC100 0x7123
#define PCI_CHIP_I810_E 0x7125
#define PCI_CHIP_I815 0x1132
#define PCI_CHIP_I830_M 0x3577
#define PCI_CHIP_845_G 0x2562
#define PCI_CHIP_I855_GM 0x3582
#define PCI_CHIP_I865_G 0x2572
#define PCI_CHIP_I915_G 0x2582
#define PCI_CHIP_E7221_G 0x258A
#define PCI_CHIP_I915_GM 0x2592
#define PCI_CHIP_I945_G 0x2772
#define PCI_CHIP_I945_GM 0x27A2
#define PCI_CHIP_I945_GME 0x27AE
#define PCI_CHIP_Q35_G 0x29B2
#define PCI_CHIP_G33_G 0x29C2
#define PCI_CHIP_Q33_G 0x29D2
#define PCI_CHIP_IGD_GM 0xA011
#define PCI_CHIP_IGD_G 0xA001
#define IS_IGDGM(devid) (devid == PCI_CHIP_IGD_GM)
#define IS_IGDG(devid) (devid == PCI_CHIP_IGD_G)
#define IS_IGD(devid) (IS_IGDG(devid) || IS_IGDGM(devid))
#define PCI_CHIP_I965_G 0x29A2
#define PCI_CHIP_I965_Q 0x2992
#define PCI_CHIP_I965_G_1 0x2982
#define PCI_CHIP_I946_GZ 0x2972
#define PCI_CHIP_I965_GM 0x2A02
#define PCI_CHIP_I965_GME 0x2A12
#define PCI_CHIP_GM45_GM 0x2A42
#define PCI_CHIP_IGD_E_G 0x2E02
#define PCI_CHIP_Q45_G 0x2E12
#define PCI_CHIP_G45_G 0x2E22
#define PCI_CHIP_G41_G 0x2E32
#define PCI_CHIP_B43_G 0x2E42
#define PCI_CHIP_B43_G1 0x2E92
#define PCI_CHIP_ILD_G 0x0042
#define PCI_CHIP_ILM_G 0x0046
#define PCI_CHIP_SANDYBRIDGE_GT1 0x0102 /* Desktop */
#define PCI_CHIP_SANDYBRIDGE_GT2 0x0112
#define PCI_CHIP_SANDYBRIDGE_GT2_PLUS 0x0122
#define PCI_CHIP_SANDYBRIDGE_M_GT1 0x0106 /* Mobile */
#define PCI_CHIP_SANDYBRIDGE_M_GT2 0x0116
#define PCI_CHIP_SANDYBRIDGE_M_GT2_PLUS 0x0126
#define PCI_CHIP_SANDYBRIDGE_S 0x010A /* Server */
#define PCI_CHIP_IVYBRIDGE_GT1 0x0152 /* Desktop */
#define PCI_CHIP_IVYBRIDGE_GT2 0x0162
#define PCI_CHIP_IVYBRIDGE_M_GT1 0x0156 /* Mobile */
#define PCI_CHIP_IVYBRIDGE_M_GT2 0x0166
#define PCI_CHIP_IVYBRIDGE_S_GT1 0x015a /* Server */
#define PCI_CHIP_IVYBRIDGE_S_GT2 0x016a
#define PCI_CHIP_BAYTRAIL_M_1 0x0F31
#define PCI_CHIP_BAYTRAIL_M_2 0x0F32
#define PCI_CHIP_BAYTRAIL_M_3 0x0F33
#define PCI_CHIP_BAYTRAIL_M_4 0x0157
#define PCI_CHIP_BAYTRAIL_D 0x0155
#define PCI_CHIP_HASWELL_GT1 0x0402 /* Desktop */
#define PCI_CHIP_HASWELL_GT2 0x0412
#define PCI_CHIP_HASWELL_GT3 0x0422
#define PCI_CHIP_HASWELL_M_GT1 0x0406 /* Mobile */
#define PCI_CHIP_HASWELL_M_GT2 0x0416
#define PCI_CHIP_HASWELL_M_GT3 0x0426
#define PCI_CHIP_HASWELL_S_GT1 0x040A /* Server */
#define PCI_CHIP_HASWELL_S_GT2 0x041A
#define PCI_CHIP_HASWELL_S_GT3 0x042A
#define PCI_CHIP_HASWELL_B_GT1 0x040B /* Reserved */
#define PCI_CHIP_HASWELL_B_GT2 0x041B
#define PCI_CHIP_HASWELL_B_GT3 0x042B
#define PCI_CHIP_HASWELL_E_GT1 0x040E /* Reserved */
#define PCI_CHIP_HASWELL_E_GT2 0x041E
#define PCI_CHIP_HASWELL_E_GT3 0x042E
#define PCI_CHIP_HASWELL_SDV_GT1 0x0C02 /* Desktop */
#define PCI_CHIP_HASWELL_SDV_GT2 0x0C12
#define PCI_CHIP_HASWELL_SDV_GT3 0x0C22
#define PCI_CHIP_HASWELL_SDV_M_GT1 0x0C06 /* Mobile */
#define PCI_CHIP_HASWELL_SDV_M_GT2 0x0C16
#define PCI_CHIP_HASWELL_SDV_M_GT3 0x0C26
#define PCI_CHIP_HASWELL_SDV_S_GT1 0x0C0A /* Server */
#define PCI_CHIP_HASWELL_SDV_S_GT2 0x0C1A
#define PCI_CHIP_HASWELL_SDV_S_GT3 0x0C2A
#define PCI_CHIP_HASWELL_SDV_B_GT1 0x0C0B /* Reserved */
#define PCI_CHIP_HASWELL_SDV_B_GT2 0x0C1B
#define PCI_CHIP_HASWELL_SDV_B_GT3 0x0C2B
#define PCI_CHIP_HASWELL_SDV_E_GT1 0x0C0E /* Reserved */
#define PCI_CHIP_HASWELL_SDV_E_GT2 0x0C1E
#define PCI_CHIP_HASWELL_SDV_E_GT3 0x0C2E
#define PCI_CHIP_HASWELL_ULT_GT1 0x0A02 /* Desktop */
#define PCI_CHIP_HASWELL_ULT_GT2 0x0A12
#define PCI_CHIP_HASWELL_ULT_GT3 0x0A22
#define PCI_CHIP_HASWELL_ULT_M_GT1 0x0A06 /* Mobile */
#define PCI_CHIP_HASWELL_ULT_M_GT2 0x0A16
#define PCI_CHIP_HASWELL_ULT_M_GT3 0x0A26
#define PCI_CHIP_HASWELL_ULT_S_GT1 0x0A0A /* Server */
#define PCI_CHIP_HASWELL_ULT_S_GT2 0x0A1A
#define PCI_CHIP_HASWELL_ULT_S_GT3 0x0A2A
#define PCI_CHIP_HASWELL_ULT_B_GT1 0x0A0B /* Reserved */
#define PCI_CHIP_HASWELL_ULT_B_GT2 0x0A1B
#define PCI_CHIP_HASWELL_ULT_B_GT3 0x0A2B
#define PCI_CHIP_HASWELL_ULT_E_GT1 0x0A0E /* Reserved */
#define PCI_CHIP_HASWELL_ULT_E_GT2 0x0A1E
#define PCI_CHIP_HASWELL_ULT_E_GT3 0x0A2E
#define PCI_CHIP_HASWELL_CRW_GT1 0x0D02 /* Desktop */
#define PCI_CHIP_HASWELL_CRW_GT2 0x0D12
#define PCI_CHIP_HASWELL_CRW_GT3 0x0D22
#define PCI_CHIP_HASWELL_CRW_M_GT1 0x0D06 /* Mobile */
#define PCI_CHIP_HASWELL_CRW_M_GT2 0x0D16
#define PCI_CHIP_HASWELL_CRW_M_GT3 0x0D26
#define PCI_CHIP_HASWELL_CRW_S_GT1 0x0D0A /* Server */
#define PCI_CHIP_HASWELL_CRW_S_GT2 0x0D1A
#define PCI_CHIP_HASWELL_CRW_S_GT3 0x0D2A
#define PCI_CHIP_HASWELL_CRW_B_GT1 0x0D0B /* Reserved */
#define PCI_CHIP_HASWELL_CRW_B_GT2 0x0D1B
#define PCI_CHIP_HASWELL_CRW_B_GT3 0x0D2B
#define PCI_CHIP_HASWELL_CRW_E_GT1 0x0D0E /* Reserved */
#define PCI_CHIP_HASWELL_CRW_E_GT2 0x0D1E
#define PCI_CHIP_HASWELL_CRW_E_GT3 0x0D2E
#define IS_MOBILE(devid) (devid == PCI_CHIP_I855_GM || \
devid == PCI_CHIP_I915_GM || \
devid == PCI_CHIP_I945_GM || \
devid == PCI_CHIP_I945_GME || \
devid == PCI_CHIP_I965_GM || \
devid == PCI_CHIP_I965_GME || \
devid == PCI_CHIP_GM45_GM || \
IS_IGD(devid) || \
devid == PCI_CHIP_ILM_G)
#define IS_G45(devid) (devid == PCI_CHIP_IGD_E_G || \
devid == PCI_CHIP_Q45_G || \
devid == PCI_CHIP_G45_G || \
devid == PCI_CHIP_G41_G || \
devid == PCI_CHIP_B43_G || \
devid == PCI_CHIP_B43_G1)
#define IS_GM45(devid) (devid == PCI_CHIP_GM45_GM)
#define IS_G4X(devid) (IS_G45(devid) || IS_GM45(devid))
#define IS_ILD(devid) (devid == PCI_CHIP_ILD_G)
#define IS_ILM(devid) (devid == PCI_CHIP_ILM_G)
#define IS_GEN5(devid) (IS_ILD(devid) || IS_ILM(devid))
#define IS_915(devid) (devid == PCI_CHIP_I915_G || \
devid == PCI_CHIP_E7221_G || \
devid == PCI_CHIP_I915_GM)
#define IS_945(devid) (devid == PCI_CHIP_I945_G || \
devid == PCI_CHIP_I945_GM || \
devid == PCI_CHIP_I945_GME || \
devid == PCI_CHIP_G33_G || \
devid == PCI_CHIP_Q33_G || \
devid == PCI_CHIP_Q35_G || IS_IGD(devid))
#define IS_GEN4(devid) (devid == PCI_CHIP_I965_G || \
devid == PCI_CHIP_I965_Q || \
devid == PCI_CHIP_I965_G_1 || \
devid == PCI_CHIP_I965_GM || \
devid == PCI_CHIP_I965_GME || \
devid == PCI_CHIP_I946_GZ || \
IS_G4X(devid))
/* Compat macro for intel_decode.c */
#define IS_IRONLAKE(devid) IS_GEN5(devid)
#define IS_SNB_GT1(devid) (devid == PCI_CHIP_SANDYBRIDGE_GT1 || \
devid == PCI_CHIP_SANDYBRIDGE_M_GT1 || \
devid == PCI_CHIP_SANDYBRIDGE_S)
#define IS_SNB_GT2(devid) (devid == PCI_CHIP_SANDYBRIDGE_GT2 || \
devid == PCI_CHIP_SANDYBRIDGE_GT2_PLUS || \
devid == PCI_CHIP_SANDYBRIDGE_M_GT2 || \
devid == PCI_CHIP_SANDYBRIDGE_M_GT2_PLUS)
#define IS_GEN6(devid) (IS_SNB_GT1(devid) || IS_SNB_GT2(devid))
#define IS_IVB_GT1(devid) (devid == PCI_CHIP_IVYBRIDGE_GT1 || \
devid == PCI_CHIP_IVYBRIDGE_M_GT1 || \
devid == PCI_CHIP_IVYBRIDGE_S_GT1)
#define IS_IVB_GT2(devid) (devid == PCI_CHIP_IVYBRIDGE_GT2 || \
devid == PCI_CHIP_IVYBRIDGE_M_GT2 || \
devid == PCI_CHIP_IVYBRIDGE_S_GT2)
#define IS_IVYBRIDGE(devid) (IS_IVB_GT1(devid) || IS_IVB_GT2(devid))
#define IS_BAYTRAIL(devid) (devid == PCI_CHIP_BAYTRAIL_M_1 || \
devid == PCI_CHIP_BAYTRAIL_M_2 || \
devid == PCI_CHIP_BAYTRAIL_M_3 || \
devid == PCI_CHIP_BAYTRAIL_M_4 || \
devid == PCI_CHIP_BAYTRAIL_D)
#define IS_GEN7(devid) (IS_IVYBRIDGE(devid) || \
IS_BAYTRAIL(devid) || \
IS_HASWELL(devid))
#define IS_HSW_GT1(devid) (devid == PCI_CHIP_HASWELL_GT1 || \
devid == PCI_CHIP_HASWELL_M_GT1 || \
devid == PCI_CHIP_HASWELL_S_GT1 || \
devid == PCI_CHIP_HASWELL_B_GT1 || \
devid == PCI_CHIP_HASWELL_E_GT1 || \
devid == PCI_CHIP_HASWELL_SDV_GT1 || \
devid == PCI_CHIP_HASWELL_SDV_M_GT1 || \
devid == PCI_CHIP_HASWELL_SDV_S_GT1 || \
devid == PCI_CHIP_HASWELL_SDV_B_GT1 || \
devid == PCI_CHIP_HASWELL_SDV_E_GT1 || \
devid == PCI_CHIP_HASWELL_ULT_GT1 || \
devid == PCI_CHIP_HASWELL_ULT_M_GT1 || \
devid == PCI_CHIP_HASWELL_ULT_S_GT1 || \
devid == PCI_CHIP_HASWELL_ULT_B_GT1 || \
devid == PCI_CHIP_HASWELL_ULT_E_GT1 || \
devid == PCI_CHIP_HASWELL_CRW_GT1 || \
devid == PCI_CHIP_HASWELL_CRW_M_GT1 || \
devid == PCI_CHIP_HASWELL_CRW_S_GT1 || \
devid == PCI_CHIP_HASWELL_CRW_B_GT1 || \
devid == PCI_CHIP_HASWELL_CRW_E_GT1)
#define IS_HSW_GT2(devid) (devid == PCI_CHIP_HASWELL_GT2 || \
devid == PCI_CHIP_HASWELL_M_GT2 || \
devid == PCI_CHIP_HASWELL_S_GT2 || \
devid == PCI_CHIP_HASWELL_B_GT2 || \
devid == PCI_CHIP_HASWELL_E_GT2 || \
devid == PCI_CHIP_HASWELL_SDV_GT2 || \
devid == PCI_CHIP_HASWELL_SDV_M_GT2 || \
devid == PCI_CHIP_HASWELL_SDV_S_GT2 || \
devid == PCI_CHIP_HASWELL_SDV_B_GT2 || \
devid == PCI_CHIP_HASWELL_SDV_E_GT2 || \
devid == PCI_CHIP_HASWELL_ULT_GT2 || \
devid == PCI_CHIP_HASWELL_ULT_M_GT2 || \
devid == PCI_CHIP_HASWELL_ULT_S_GT2 || \
devid == PCI_CHIP_HASWELL_ULT_B_GT2 || \
devid == PCI_CHIP_HASWELL_ULT_E_GT2 || \
devid == PCI_CHIP_HASWELL_CRW_GT2 || \
devid == PCI_CHIP_HASWELL_CRW_M_GT2 || \
devid == PCI_CHIP_HASWELL_CRW_S_GT2 || \
devid == PCI_CHIP_HASWELL_CRW_B_GT2 || \
devid == PCI_CHIP_HASWELL_CRW_E_GT2)
#define IS_HSW_GT3(devid) (devid == PCI_CHIP_HASWELL_GT3 || \
devid == PCI_CHIP_HASWELL_M_GT3 || \
devid == PCI_CHIP_HASWELL_S_GT3 || \
devid == PCI_CHIP_HASWELL_B_GT3 || \
devid == PCI_CHIP_HASWELL_E_GT3 || \
devid == PCI_CHIP_HASWELL_SDV_GT3 || \
devid == PCI_CHIP_HASWELL_SDV_M_GT3 || \
devid == PCI_CHIP_HASWELL_SDV_S_GT3 || \
devid == PCI_CHIP_HASWELL_SDV_B_GT3 || \
devid == PCI_CHIP_HASWELL_SDV_E_GT3 || \
devid == PCI_CHIP_HASWELL_ULT_GT3 || \
devid == PCI_CHIP_HASWELL_ULT_M_GT3 || \
devid == PCI_CHIP_HASWELL_ULT_S_GT3 || \
devid == PCI_CHIP_HASWELL_ULT_B_GT3 || \
devid == PCI_CHIP_HASWELL_ULT_E_GT3 || \
devid == PCI_CHIP_HASWELL_CRW_GT3 || \
devid == PCI_CHIP_HASWELL_CRW_M_GT3 || \
devid == PCI_CHIP_HASWELL_CRW_S_GT3 || \
devid == PCI_CHIP_HASWELL_CRW_B_GT3 || \
devid == PCI_CHIP_HASWELL_CRW_E_GT3)
#define IS_HASWELL(devid) (IS_HSW_GT1(devid) || \
IS_HSW_GT2(devid) || \
IS_HSW_GT3(devid))
#define IS_965(devid) (IS_GEN4(devid) || \
IS_G4X(devid) || \
IS_GEN5(devid) || \
IS_GEN6(devid) || \
IS_GEN7(devid))
#define IS_9XX(devid) (IS_915(devid) || \
IS_945(devid) || \
IS_965(devid))
#define IS_GEN3(devid) (IS_915(devid) || \
IS_945(devid))
#define IS_GEN2(devid) (devid == PCI_CHIP_I830_M || \
devid == PCI_CHIP_845_G || \
devid == PCI_CHIP_I855_GM || \
devid == PCI_CHIP_I865_G)

View file

@ -0,0 +1,38 @@
/**************************************************************************
*
* Copyright 2006 Tungsten Graphics, Inc., Cedar Park, Texas.
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sub license, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial portions
* of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
**************************************************************************/
#ifndef INTEL_CLEAR_H
#define INTEL_CLEAR_H
struct dd_function_table;
extern void
intelInitClearFuncs(struct dd_function_table *functions);
#endif /* INTEL_CLEAR_H */

View file

@ -1 +0,0 @@
../intel/intel_context.c

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,643 @@
/**************************************************************************
*
* Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sub license, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial portions
* of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
**************************************************************************/
#ifndef INTELCONTEXT_INC
#define INTELCONTEXT_INC
#include <stdbool.h>
#include <string.h>
#include "main/mtypes.h"
#include "main/mm.h"
#ifdef __cplusplus
extern "C" {
/* Evil hack for using libdrm in a c++ compiler. */
#define virtual virt
#endif
#include "drm.h"
#include "intel_bufmgr.h"
#include "intel_screen.h"
#include "intel_tex_obj.h"
#include "i915_drm.h"
#ifdef __cplusplus
#undef virtual
#endif
#include "tnl/t_vertex.h"
#define TAG(x) intel##x
#include "tnl_dd/t_dd_vertex.h"
#undef TAG
#define DV_PF_555 (1<<8)
#define DV_PF_565 (2<<8)
#define DV_PF_8888 (3<<8)
#define DV_PF_4444 (8<<8)
#define DV_PF_1555 (9<<8)
struct intel_region;
struct intel_context;
typedef void (*intel_tri_func) (struct intel_context *, intelVertex *,
intelVertex *, intelVertex *);
typedef void (*intel_line_func) (struct intel_context *, intelVertex *,
intelVertex *);
typedef void (*intel_point_func) (struct intel_context *, intelVertex *);
/**
* Bits for intel->Fallback field
*/
/*@{*/
#define INTEL_FALLBACK_DRAW_BUFFER 0x1
#define INTEL_FALLBACK_READ_BUFFER 0x2
#define INTEL_FALLBACK_DEPTH_BUFFER 0x4
#define INTEL_FALLBACK_STENCIL_BUFFER 0x8
#define INTEL_FALLBACK_USER 0x10
#define INTEL_FALLBACK_RENDERMODE 0x20
#define INTEL_FALLBACK_TEXTURE 0x40
#define INTEL_FALLBACK_DRIVER 0x1000 /**< first for drivers */
/*@}*/
extern void intelFallback(struct intel_context *intel, GLbitfield bit,
bool mode);
#define FALLBACK( intel, bit, mode ) intelFallback( intel, bit, mode )
#define INTEL_WRITE_PART 0x1
#define INTEL_WRITE_FULL 0x2
#define INTEL_READ 0x4
#define INTEL_MAX_FIXUP 64
#ifndef likely
#ifdef __GNUC__
#define likely(expr) (__builtin_expect(expr, 1))
#define unlikely(expr) (__builtin_expect(expr, 0))
#else
#define likely(expr) (expr)
#define unlikely(expr) (expr)
#endif
#endif
struct intel_sync_object {
struct gl_sync_object Base;
/** Batch associated with this sync object */
drm_intel_bo *bo;
};
struct brw_context;
struct intel_batchbuffer {
/** Current batchbuffer being queued up. */
drm_intel_bo *bo;
/** Last BO submitted to the hardware. Used for glFinish(). */
drm_intel_bo *last_bo;
/** BO for post-sync nonzero writes for gen6 workaround. */
drm_intel_bo *workaround_bo;
bool need_workaround_flush;
struct cached_batch_item *cached_items;
uint16_t emit, total;
uint16_t used, reserved_space;
uint32_t *map;
uint32_t *cpu_map;
#define BATCH_SZ (8192*sizeof(uint32_t))
uint32_t state_batch_offset;
bool is_blit;
bool needs_sol_reset;
struct {
uint16_t used;
int reloc_count;
} saved;
};
/**
* intel_context is derived from Mesa's context class: struct gl_context.
*/
struct intel_context
{
struct gl_context ctx; /**< base class, must be first field */
struct
{
void (*destroy) (struct intel_context * intel);
void (*emit_state) (struct intel_context * intel);
void (*finish_batch) (struct intel_context * intel);
void (*new_batch) (struct intel_context * intel);
void (*emit_invarient_state) (struct intel_context * intel);
void (*update_texture_state) (struct intel_context * intel);
void (*render_start) (struct intel_context * intel);
void (*render_prevalidate) (struct intel_context * intel);
void (*set_draw_region) (struct intel_context * intel,
struct intel_region * draw_regions[],
struct intel_region * depth_region,
GLuint num_regions);
void (*update_draw_buffer)(struct intel_context *intel);
void (*reduced_primitive_state) (struct intel_context * intel,
GLenum rprim);
bool (*check_vertex_size) (struct intel_context * intel,
GLuint expected);
void (*invalidate_state) (struct intel_context *intel,
GLuint new_state);
void (*assert_not_dirty) (struct intel_context *intel);
void (*debug_batch)(struct intel_context *intel);
void (*annotate_aub)(struct intel_context *intel);
bool (*render_target_supported)(struct intel_context *intel,
struct gl_renderbuffer *rb);
/** Can HiZ be enabled on a depthbuffer of the given format? */
bool (*is_hiz_depth_format)(struct intel_context *intel,
gl_format format);
/**
* Surface state operations (i965+ only)
* \{
*/
void (*update_texture_surface)(struct gl_context *ctx,
unsigned unit,
uint32_t *binding_table,
unsigned surf_index);
void (*update_renderbuffer_surface)(struct brw_context *brw,
struct gl_renderbuffer *rb,
bool layered,
unsigned unit);
void (*update_null_renderbuffer_surface)(struct brw_context *brw,
unsigned unit);
void (*create_constant_surface)(struct brw_context *brw,
drm_intel_bo *bo,
uint32_t offset,
uint32_t size,
uint32_t *out_offset,
bool dword_pitch);
/** \} */
/**
* Send the appropriate state packets to configure depth, stencil, and
* HiZ buffers (i965+ only)
*/
void (*emit_depth_stencil_hiz)(struct brw_context *brw,
struct intel_mipmap_tree *depth_mt,
uint32_t depth_offset,
uint32_t depthbuffer_format,
uint32_t depth_surface_type,
struct intel_mipmap_tree *stencil_mt,
bool hiz, bool separate_stencil,
uint32_t width, uint32_t height,
uint32_t tile_x, uint32_t tile_y);
} vtbl;
GLbitfield Fallback; /**< mask of INTEL_FALLBACK_x bits */
GLuint NewGLState;
dri_bufmgr *bufmgr;
unsigned int maxBatchSize;
/**
* Generation number of the hardware: 2 is 8xx, 3 is 9xx pre-965, 4 is 965.
*/
int gen;
int gt;
bool needs_ff_sync;
bool is_haswell;
bool is_baytrail;
bool is_g4x;
bool is_945;
bool has_separate_stencil;
bool must_use_separate_stencil;
bool has_hiz;
bool has_llc;
bool has_swizzling;
int urb_size;
drm_intel_context *hw_ctx;
struct intel_batchbuffer batch;
drm_intel_bo *first_post_swapbuffers_batch;
bool need_throttle;
bool no_batch_wrap;
bool tnl_pipeline_running; /**< Set while i915's _tnl_run_pipeline. */
/**
* Set if we're either a debug context or the INTEL_DEBUG=perf environment
* variable is set, this is the flag indicating to do expensive work that
* might lead to a perf_debug() call.
*/
bool perf_debug;
struct
{
GLuint id;
uint32_t start_ptr; /**< for i8xx */
uint32_t primitive; /**< Current hardware primitive type */
void (*flush) (struct intel_context *);
drm_intel_bo *vb_bo;
uint8_t *vb;
unsigned int start_offset; /**< Byte offset of primitive sequence */
unsigned int current_offset; /**< Byte offset of next vertex */
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;
uint32_t max_gtt_map_object_size;
GLuint stats_wm;
/* Offsets of fields within the current vertex:
*/
GLuint coloroffset;
GLuint specoffset;
GLuint wpos_offset;
struct tnl_attr_map vertex_attrs[VERT_ATTRIB_MAX];
GLuint vertex_attr_count;
GLfloat polygon_offset_scale; /* dependent on depth_scale, bpp */
bool hw_stencil;
bool hw_stipple;
bool no_rast;
bool always_flush_batch;
bool always_flush_cache;
bool disable_throttling;
/* State for intelvb.c and inteltris.c.
*/
GLuint RenderIndex;
GLmatrix ViewportMatrix;
GLenum render_primitive;
GLenum reduced_primitive; /*< Only gen < 6 */
GLuint vertex_size;
GLubyte *verts; /* points to tnl->clipspace.vertex_buf */
/* Fallback rasterization functions
*/
intel_point_func draw_point;
intel_line_func draw_line;
intel_tri_func draw_tri;
/**
* Set if rendering has occured to the drawable's front buffer.
*
* This is used in the DRI2 case to detect that glFlush should also copy
* the contents of the fake front buffer to the real front buffer.
*/
bool front_buffer_dirty;
/**
* Track whether front-buffer rendering is currently enabled
*
* A separate flag is used to track this in order to support MRT more
* easily.
*/
bool is_front_buffer_rendering;
/**
* Track whether front-buffer is the current read target.
*
* This is closely associated with is_front_buffer_rendering, but may
* be set separately. The DRI2 fake front buffer must be referenced
* either way.
*/
bool is_front_buffer_reading;
bool use_early_z;
int driFd;
__DRIcontext *driContext;
struct intel_screen *intelScreen;
void (*saved_viewport)(struct gl_context * ctx,
GLint x, GLint y, GLsizei width, GLsizei height);
/**
* Configuration cache
*/
driOptionCache optionCache;
};
extern char *__progname;
#define SUBPIXEL_X 0.125
#define SUBPIXEL_Y 0.125
/**
* Align a value down to an alignment value
*
* If \c value is not already aligned to the requested alignment value, it
* will be rounded down.
*
* \param value Value to be rounded
* \param alignment Alignment value to be used. This must be a power of two.
*
* \sa ALIGN()
*/
#define ROUND_DOWN_TO(value, alignment) ((value) & ~(alignment - 1))
static INLINE uint32_t
U_FIXED(float value, uint32_t frac_bits)
{
value *= (1 << frac_bits);
return value < 0 ? 0 : value;
}
static INLINE uint32_t
S_FIXED(float value, uint32_t frac_bits)
{
return value * (1 << frac_bits);
}
#define INTEL_FIREVERTICES(intel) \
do { \
if ((intel)->prim.flush) \
(intel)->prim.flush(intel); \
} while (0)
/* ================================================================
* From linux kernel i386 header files, copes with odd sizes better
* than COPY_DWORDS would:
* XXX Put this in src/mesa/main/imports.h ???
*/
#if defined(i386) || defined(__i386__)
static INLINE void * __memcpy(void * to, const void * from, size_t n)
{
int d0, d1, d2;
__asm__ __volatile__(
"rep ; movsl\n\t"
"testb $2,%b4\n\t"
"je 1f\n\t"
"movsw\n"
"1:\ttestb $1,%b4\n\t"
"je 2f\n\t"
"movsb\n"
"2:"
: "=&c" (d0), "=&D" (d1), "=&S" (d2)
:"0" (n/4), "q" (n),"1" ((long) to),"2" ((long) from)
: "memory");
return (to);
}
#else
#define __memcpy(a,b,c) memcpy(a,b,c)
#endif
/* ================================================================
* Debugging:
*/
extern int INTEL_DEBUG;
#define DEBUG_TEXTURE 0x1
#define DEBUG_STATE 0x2
#define DEBUG_IOCTL 0x4
#define DEBUG_BLIT 0x8
#define DEBUG_MIPTREE 0x10
#define DEBUG_PERF 0x20
#define DEBUG_BATCH 0x80
#define DEBUG_PIXEL 0x100
#define DEBUG_BUFMGR 0x200
#define DEBUG_REGION 0x400
#define DEBUG_FBO 0x800
#define DEBUG_GS 0x1000
#define DEBUG_SYNC 0x2000
#define DEBUG_PRIMS 0x4000
#define DEBUG_VERTS 0x8000
#define DEBUG_DRI 0x10000
#define DEBUG_SF 0x20000
#define DEBUG_STATS 0x100000
#define DEBUG_WM 0x400000
#define DEBUG_URB 0x800000
#define DEBUG_VS 0x1000000
#define DEBUG_CLIP 0x2000000
#define DEBUG_AUB 0x4000000
#define DEBUG_SHADER_TIME 0x8000000
#define DEBUG_BLORP 0x10000000
#define DEBUG_NO16 0x20000000
#ifdef HAVE_ANDROID_PLATFORM
#define LOG_TAG "INTEL-MESA"
#include <cutils/log.h>
#ifndef ALOGW
#define ALOGW LOGW
#endif
#define dbg_printf(...) ALOGW(__VA_ARGS__)
#else
#define dbg_printf(...) printf(__VA_ARGS__)
#endif /* HAVE_ANDROID_PLATFORM */
#define DBG(...) do { \
if (unlikely(INTEL_DEBUG & FILE_DEBUG_FLAG)) \
dbg_printf(__VA_ARGS__); \
} while(0)
#define perf_debug(...) do { \
static GLuint msg_id = 0; \
if (unlikely(INTEL_DEBUG & DEBUG_PERF)) \
dbg_printf(__VA_ARGS__); \
if (intel->perf_debug) \
_mesa_gl_debug(&intel->ctx, &msg_id, \
MESA_DEBUG_TYPE_PERFORMANCE, \
MESA_DEBUG_SEVERITY_MEDIUM, \
__VA_ARGS__); \
} while(0)
#define WARN_ONCE(cond, fmt...) do { \
if (unlikely(cond)) { \
static bool _warned = false; \
static GLuint msg_id = 0; \
if (!_warned) { \
fprintf(stderr, "WARNING: "); \
fprintf(stderr, fmt); \
_warned = true; \
\
_mesa_gl_debug(ctx, &msg_id, \
MESA_DEBUG_TYPE_OTHER, \
MESA_DEBUG_SEVERITY_HIGH, fmt); \
} \
} \
} while (0)
#define PCI_CHIP_845_G 0x2562
#define PCI_CHIP_I830_M 0x3577
#define PCI_CHIP_I855_GM 0x3582
#define PCI_CHIP_I865_G 0x2572
#define PCI_CHIP_I915_G 0x2582
#define PCI_CHIP_I915_GM 0x2592
#define PCI_CHIP_I945_G 0x2772
#define PCI_CHIP_I945_GM 0x27A2
#define PCI_CHIP_I945_GME 0x27AE
#define PCI_CHIP_G33_G 0x29C2
#define PCI_CHIP_Q35_G 0x29B2
#define PCI_CHIP_Q33_G 0x29D2
/* ================================================================
* intel_context.c:
*/
extern bool intelInitContext(struct intel_context *intel,
int api,
unsigned major_version,
unsigned minor_version,
const struct gl_config * mesaVis,
__DRIcontext * driContextPriv,
void *sharedContextPrivate,
struct dd_function_table *functions,
unsigned *dri_ctx_error);
extern void intelFinish(struct gl_context * ctx);
extern void intel_flush_rendering_to_batch(struct gl_context *ctx);
extern void _intel_flush(struct gl_context * ctx, const char *file, int line);
#define intel_flush(ctx) _intel_flush(ctx, __FILE__, __LINE__)
extern void intelInitDriverFunctions(struct dd_function_table *functions);
void intel_init_syncobj_functions(struct dd_function_table *functions);
/* ================================================================
* intel_state.c:
*/
#define COMPAREFUNC_ALWAYS 0
#define COMPAREFUNC_NEVER 0x1
#define COMPAREFUNC_LESS 0x2
#define COMPAREFUNC_EQUAL 0x3
#define COMPAREFUNC_LEQUAL 0x4
#define COMPAREFUNC_GREATER 0x5
#define COMPAREFUNC_NOTEQUAL 0x6
#define COMPAREFUNC_GEQUAL 0x7
#define STENCILOP_KEEP 0
#define STENCILOP_ZERO 0x1
#define STENCILOP_REPLACE 0x2
#define STENCILOP_INCRSAT 0x3
#define STENCILOP_DECRSAT 0x4
#define STENCILOP_INCR 0x5
#define STENCILOP_DECR 0x6
#define STENCILOP_INVERT 0x7
#define LOGICOP_CLEAR 0
#define LOGICOP_NOR 0x1
#define LOGICOP_AND_INV 0x2
#define LOGICOP_COPY_INV 0x3
#define LOGICOP_AND_RVRSE 0x4
#define LOGICOP_INV 0x5
#define LOGICOP_XOR 0x6
#define LOGICOP_NAND 0x7
#define LOGICOP_AND 0x8
#define LOGICOP_EQUIV 0x9
#define LOGICOP_NOOP 0xa
#define LOGICOP_OR_INV 0xb
#define LOGICOP_COPY 0xc
#define LOGICOP_OR_RVRSE 0xd
#define LOGICOP_OR 0xe
#define LOGICOP_SET 0xf
#define BLENDFACT_ZERO 0x01
#define BLENDFACT_ONE 0x02
#define BLENDFACT_SRC_COLR 0x03
#define BLENDFACT_INV_SRC_COLR 0x04
#define BLENDFACT_SRC_ALPHA 0x05
#define BLENDFACT_INV_SRC_ALPHA 0x06
#define BLENDFACT_DST_ALPHA 0x07
#define BLENDFACT_INV_DST_ALPHA 0x08
#define BLENDFACT_DST_COLR 0x09
#define BLENDFACT_INV_DST_COLR 0x0a
#define BLENDFACT_SRC_ALPHA_SATURATE 0x0b
#define BLENDFACT_CONST_COLOR 0x0c
#define BLENDFACT_INV_CONST_COLOR 0x0d
#define BLENDFACT_CONST_ALPHA 0x0e
#define BLENDFACT_INV_CONST_ALPHA 0x0f
#define BLENDFACT_MASK 0x0f
enum {
DRI_CONF_BO_REUSE_DISABLED,
DRI_CONF_BO_REUSE_ALL
};
extern int intel_translate_shadow_compare_func(GLenum func);
extern int intel_translate_compare_func(GLenum func);
extern int intel_translate_stencil_op(GLenum op);
extern int intel_translate_blend_factor(GLenum factor);
extern int intel_translate_logic_op(GLenum opcode);
void intel_update_renderbuffers(__DRIcontext *context,
__DRIdrawable *drawable);
void intel_prepare_render(struct intel_context *intel);
void
intel_resolve_for_dri2_flush(struct intel_context *intel,
__DRIdrawable *drawable);
void i915_set_buf_info_for_region(uint32_t *state, struct intel_region *region,
uint32_t buffer_id);
void intel_init_texture_formats(struct gl_context *ctx);
/*======================================================================
* Inline conversion functions.
* These are better-typed than the macros used previously:
*/
static INLINE struct intel_context *
intel_context(struct gl_context * ctx)
{
return (struct intel_context *) ctx;
}
static INLINE bool
is_power_of_two(uint32_t value)
{
return (value & (value - 1)) == 0;
}
#ifdef __cplusplus
}
#endif
#endif

View file

@ -1 +0,0 @@
../intel/intel_extensions.c

View file

@ -0,0 +1,188 @@
/**************************************************************************
*
* Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sub license, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial portions
* of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
**************************************************************************/
#include "main/version.h"
#include "intel_chipset.h"
#include "intel_context.h"
#include "intel_extensions.h"
#include "intel_reg.h"
#include "utils.h"
/**
* Initializes potential list of extensions if ctx == NULL, or actually enables
* extensions for a context.
*/
void
intelInitExtensions(struct gl_context *ctx)
{
struct intel_context *intel = intel_context(ctx);
ctx->Extensions.ARB_draw_elements_base_vertex = true;
ctx->Extensions.ARB_explicit_attrib_location = true;
ctx->Extensions.ARB_framebuffer_object = true;
ctx->Extensions.ARB_half_float_pixel = true;
ctx->Extensions.ARB_internalformat_query = true;
ctx->Extensions.ARB_map_buffer_range = true;
ctx->Extensions.ARB_point_sprite = true;
ctx->Extensions.ARB_shader_objects = true;
ctx->Extensions.ARB_shading_language_100 = true;
ctx->Extensions.ARB_sync = true;
ctx->Extensions.ARB_texture_border_clamp = true;
ctx->Extensions.ARB_texture_cube_map = true;
ctx->Extensions.ARB_texture_env_combine = true;
ctx->Extensions.ARB_texture_env_crossbar = true;
ctx->Extensions.ARB_texture_env_dot3 = true;
ctx->Extensions.ARB_texture_storage = true;
ctx->Extensions.ARB_vertex_program = true;
ctx->Extensions.ARB_vertex_shader = true;
ctx->Extensions.EXT_blend_color = true;
ctx->Extensions.EXT_blend_equation_separate = true;
ctx->Extensions.EXT_blend_func_separate = true;
ctx->Extensions.EXT_blend_minmax = true;
ctx->Extensions.EXT_framebuffer_blit = true;
ctx->Extensions.EXT_framebuffer_object = true;
ctx->Extensions.EXT_fog_coord = true;
ctx->Extensions.EXT_gpu_program_parameters = true;
ctx->Extensions.EXT_packed_depth_stencil = true;
ctx->Extensions.EXT_pixel_buffer_object = true;
ctx->Extensions.EXT_point_parameters = true;
ctx->Extensions.EXT_provoking_vertex = true;
ctx->Extensions.EXT_secondary_color = true;
ctx->Extensions.EXT_separate_shader_objects = true;
ctx->Extensions.EXT_texture_env_dot3 = true;
ctx->Extensions.EXT_texture_filter_anisotropic = true;
ctx->Extensions.APPLE_object_purgeable = true;
ctx->Extensions.MESA_pack_invert = true;
ctx->Extensions.MESA_ycbcr_texture = true;
ctx->Extensions.NV_blend_square = true;
ctx->Extensions.NV_texture_rectangle = true;
ctx->Extensions.TDFX_texture_compression_FXT1 = true;
ctx->Extensions.OES_EGL_image = true;
ctx->Extensions.OES_draw_texture = true;
if (intel->gen >= 6)
ctx->Const.GLSLVersion = 140;
else
ctx->Const.GLSLVersion = 120;
_mesa_override_glsl_version(ctx);
if (intel->gen >= 6) {
ctx->Extensions.EXT_framebuffer_multisample = true;
ctx->Extensions.EXT_transform_feedback = true;
ctx->Extensions.ARB_blend_func_extended = !driQueryOptionb(&intel->optionCache, "disable_blend_func_extended");
ctx->Extensions.ARB_draw_buffers_blend = true;
ctx->Extensions.ARB_ES3_compatibility = true;
ctx->Extensions.ARB_uniform_buffer_object = true;
ctx->Extensions.ARB_texture_buffer_object = true;
ctx->Extensions.ARB_texture_buffer_object_rgb32 = true;
ctx->Extensions.ARB_texture_cube_map_array = true;
ctx->Extensions.OES_depth_texture_cube_map = true;
ctx->Extensions.ARB_shading_language_packing = true;
ctx->Extensions.ARB_texture_multisample = true;
ctx->Extensions.ARB_texture_storage_multisample = true;
}
if (intel->gen >= 5) {
ctx->Extensions.ARB_texture_query_lod = true;
ctx->Extensions.EXT_timer_query = true;
}
if (intel->gen >= 6) {
uint64_t dummy;
/* Test if the kernel has the ioctl. */
if (drm_intel_reg_read(intel->bufmgr, TIMESTAMP, &dummy) == 0)
ctx->Extensions.ARB_timer_query = true;
}
if (intel->gen >= 4) {
if (ctx->API == API_OPENGL_CORE)
ctx->Extensions.ARB_base_instance = true;
if (ctx->API != API_OPENGL_CORE)
ctx->Extensions.ARB_color_buffer_float = true;
ctx->Extensions.ARB_depth_buffer_float = true;
ctx->Extensions.ARB_depth_clamp = true;
ctx->Extensions.ARB_draw_instanced = true;
ctx->Extensions.ARB_instanced_arrays = true;
ctx->Extensions.ARB_fragment_coord_conventions = true;
ctx->Extensions.ARB_fragment_program_shadow = true;
ctx->Extensions.ARB_fragment_shader = true;
ctx->Extensions.ARB_half_float_vertex = true;
ctx->Extensions.ARB_occlusion_query = true;
ctx->Extensions.ARB_occlusion_query2 = true;
ctx->Extensions.ARB_point_sprite = true;
ctx->Extensions.ARB_seamless_cube_map = true;
ctx->Extensions.ARB_shader_bit_encoding = true;
ctx->Extensions.ARB_shader_texture_lod = true;
ctx->Extensions.ARB_texture_float = true;
ctx->Extensions.EXT_texture_shared_exponent = true;
ctx->Extensions.EXT_packed_float = true;
ctx->Extensions.ARB_texture_compression_rgtc = true;
ctx->Extensions.ARB_texture_rg = true;
ctx->Extensions.ARB_texture_rgb10_a2ui = true;
ctx->Extensions.ARB_vertex_type_2_10_10_10_rev = true;
ctx->Extensions.EXT_draw_buffers2 = true;
ctx->Extensions.EXT_framebuffer_sRGB = true;
ctx->Extensions.EXT_texture_array = true;
ctx->Extensions.EXT_texture_integer = true;
ctx->Extensions.EXT_texture_snorm = true;
ctx->Extensions.EXT_texture_swizzle = true;
ctx->Extensions.EXT_vertex_array_bgra = true;
ctx->Extensions.ATI_envmap_bumpmap = true;
ctx->Extensions.MESA_texture_array = true;
ctx->Extensions.NV_conditional_render = true;
ctx->Extensions.OES_compressed_ETC1_RGB8_texture = true;
ctx->Extensions.OES_standard_derivatives = true;
}
if (intel->gen >= 3) {
ctx->Extensions.ARB_ES2_compatibility = true;
ctx->Extensions.ARB_depth_texture = true;
ctx->Extensions.ARB_fragment_program = true;
ctx->Extensions.ARB_shadow = true;
ctx->Extensions.ARB_texture_non_power_of_two = true;
ctx->Extensions.EXT_texture_sRGB = true;
ctx->Extensions.EXT_texture_sRGB_decode = true;
ctx->Extensions.EXT_shadow_funcs = true;
ctx->Extensions.EXT_stencil_two_side = true;
ctx->Extensions.ATI_separate_stencil = true;
ctx->Extensions.ATI_texture_env_combine3 = true;
ctx->Extensions.NV_texture_env_combine4 = true;
ctx->Extensions.ARB_fragment_shader = true;
ctx->Extensions.ARB_occlusion_query = true;
}
if (intel->ctx.Mesa_DXTn
|| driQueryOptionb(&intel->optionCache, "force_s3tc_enable"))
ctx->Extensions.EXT_texture_compression_s3tc = true;
ctx->Extensions.ANGLE_texture_compression_dxt = true;
if (intel->gen >= 4) {
ctx->Extensions.NV_primitive_restart = true;
}
}

View file

@ -0,0 +1,42 @@
/**************************************************************************
*
* Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sub license, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial portions
* of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
**************************************************************************/
#ifndef INTEL_EXTENSIONS_H
#define INTEL_EXTENSIONS_H
extern void
intelInitExtensions(struct gl_context *ctx);
extern void
intelInitExtensionsES1(struct gl_context *ctx);
extern void
intelInitExtensionsES2(struct gl_context *ctx);
#endif

View file

@ -1 +0,0 @@
../intel/intel_fbo.c

View file

@ -0,0 +1,949 @@
/**************************************************************************
*
* Copyright 2006 Tungsten Graphics, Inc., Cedar Park, Texas.
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sub license, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial portions
* of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
**************************************************************************/
#include "main/enums.h"
#include "main/imports.h"
#include "main/macros.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/image.h"
#include "swrast/swrast.h"
#include "drivers/common/meta.h"
#include "intel_context.h"
#include "intel_batchbuffer.h"
#include "intel_buffers.h"
#include "intel_blit.h"
#include "intel_fbo.h"
#include "intel_mipmap_tree.h"
#include "intel_regions.h"
#include "intel_tex.h"
#ifndef I915
#include "brw_context.h"
#endif
#define FILE_DEBUG_FLAG DEBUG_FBO
static struct gl_renderbuffer *
intel_new_renderbuffer(struct gl_context * ctx, GLuint name);
struct intel_region*
intel_get_rb_region(struct gl_framebuffer *fb, GLuint attIndex)
{
struct intel_renderbuffer *irb = intel_get_renderbuffer(fb, attIndex);
if (irb && irb->mt) {
if (attIndex == BUFFER_STENCIL && irb->mt->stencil_mt)
return irb->mt->stencil_mt->region;
else
return irb->mt->region;
} else
return NULL;
}
/**
* Create a new framebuffer object.
*/
static struct gl_framebuffer *
intel_new_framebuffer(struct gl_context * ctx, GLuint name)
{
/* Only drawable state in intel_framebuffer at this time, just use Mesa's
* class
*/
return _mesa_new_framebuffer(ctx, name);
}
/** Called by gl_renderbuffer::Delete() */
static void
intel_delete_renderbuffer(struct gl_context *ctx, struct gl_renderbuffer *rb)
{
struct intel_renderbuffer *irb = intel_renderbuffer(rb);
ASSERT(irb);
intel_miptree_release(&irb->mt);
_mesa_delete_renderbuffer(ctx, rb);
}
/**
* \see dd_function_table::MapRenderbuffer
*/
static void
intel_map_renderbuffer(struct gl_context *ctx,
struct gl_renderbuffer *rb,
GLuint x, GLuint y, GLuint w, GLuint h,
GLbitfield mode,
GLubyte **out_map,
GLint *out_stride)
{
struct intel_context *intel = intel_context(ctx);
struct swrast_renderbuffer *srb = (struct swrast_renderbuffer *)rb;
struct intel_renderbuffer *irb = intel_renderbuffer(rb);
void *map;
int stride;
if (srb->Buffer) {
/* this is a malloc'd renderbuffer (accum buffer), not an irb */
GLint bpp = _mesa_get_format_bytes(rb->Format);
GLint rowStride = srb->RowStride;
*out_map = (GLubyte *) srb->Buffer + y * rowStride + x * bpp;
*out_stride = rowStride;
return;
}
intel_prepare_render(intel);
/* For a window-system renderbuffer, we need to flip the mapping we receive
* upside-down. So we need to ask for a rectangle on flipped vertically, and
* we then return a pointer to the bottom of it with a negative stride.
*/
if (rb->Name == 0) {
y = rb->Height - y - h;
}
intel_miptree_map(intel, irb->mt, irb->mt_level, irb->mt_layer,
x, y, w, h, mode, &map, &stride);
if (rb->Name == 0) {
map += (h - 1) * stride;
stride = -stride;
}
DBG("%s: rb %d (%s) mt mapped: (%d, %d) (%dx%d) -> %p/%d\n",
__FUNCTION__, rb->Name, _mesa_get_format_name(rb->Format),
x, y, w, h, map, stride);
*out_map = map;
*out_stride = stride;
}
/**
* \see dd_function_table::UnmapRenderbuffer
*/
static void
intel_unmap_renderbuffer(struct gl_context *ctx,
struct gl_renderbuffer *rb)
{
struct intel_context *intel = intel_context(ctx);
struct swrast_renderbuffer *srb = (struct swrast_renderbuffer *)rb;
struct intel_renderbuffer *irb = intel_renderbuffer(rb);
DBG("%s: rb %d (%s)\n", __FUNCTION__,
rb->Name, _mesa_get_format_name(rb->Format));
if (srb->Buffer) {
/* this is a malloc'd renderbuffer (accum buffer) */
/* nothing to do */
return;
}
intel_miptree_unmap(intel, irb->mt, irb->mt_level, irb->mt_layer);
}
/**
* Round up the requested multisample count to the next supported sample size.
*/
unsigned
intel_quantize_num_samples(struct intel_screen *intel, unsigned num_samples)
{
switch (intel->gen) {
case 6:
/* Gen6 supports only 4x multisampling. */
if (num_samples > 0)
return 4;
else
return 0;
case 7:
/* Gen7 supports 4x and 8x multisampling. */
if (num_samples > 4)
return 8;
else if (num_samples > 0)
return 4;
else
return 0;
return 0;
default:
/* MSAA unsupported. */
return 0;
}
}
/**
* Called via glRenderbufferStorageEXT() to set the format and allocate
* storage for a user-created renderbuffer.
*/
static GLboolean
intel_alloc_renderbuffer_storage(struct gl_context * ctx, struct gl_renderbuffer *rb,
GLenum internalFormat,
GLuint width, GLuint height)
{
struct intel_context *intel = intel_context(ctx);
struct intel_screen *screen = intel->intelScreen;
struct intel_renderbuffer *irb = intel_renderbuffer(rb);
rb->NumSamples = intel_quantize_num_samples(screen, rb->NumSamples);
switch (internalFormat) {
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, GL_TEXTURE_2D,
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:
/* These aren't actual texture formats, so force them here. */
if (intel->has_separate_stencil) {
rb->Format = MESA_FORMAT_S8;
} else {
assert(!intel->must_use_separate_stencil);
rb->Format = MESA_FORMAT_S8_Z24;
}
break;
}
rb->Width = width;
rb->Height = height;
rb->_BaseFormat = _mesa_base_fbo_format(ctx, internalFormat);
intel_miptree_release(&irb->mt);
DBG("%s: %s: %s (%dx%d)\n", __FUNCTION__,
_mesa_lookup_enum_by_nr(internalFormat),
_mesa_get_format_name(rb->Format), width, height);
if (width == 0 || height == 0)
return true;
irb->mt = intel_miptree_create_for_renderbuffer(intel, rb->Format,
width, height,
rb->NumSamples);
if (!irb->mt)
return false;
return true;
}
static void
intel_image_target_renderbuffer_storage(struct gl_context *ctx,
struct gl_renderbuffer *rb,
void *image_handle)
{
struct intel_context *intel = intel_context(ctx);
struct intel_renderbuffer *irb;
__DRIscreen *screen;
__DRIimage *image;
screen = intel->intelScreen->driScrnPriv;
image = screen->dri2.image->lookupEGLImage(screen, image_handle,
screen->loaderPrivate);
if (image == NULL)
return;
/* __DRIimage is opaque to the core so it has to be checked here */
switch (image->format) {
case MESA_FORMAT_RGBA8888_REV:
_mesa_error(&intel->ctx, GL_INVALID_OPERATION,
"glEGLImageTargetRenderbufferStorage(unsupported image format");
return;
break;
default:
break;
}
irb = intel_renderbuffer(rb);
intel_miptree_release(&irb->mt);
irb->mt = intel_miptree_create_for_bo(intel,
image->region->bo,
image->format,
image->offset,
image->region->width,
image->region->height,
image->region->pitch,
image->region->tiling);
if (!irb->mt)
return;
rb->InternalFormat = image->internal_format;
rb->Width = image->region->width;
rb->Height = image->region->height;
rb->Format = image->format;
rb->_BaseFormat = _mesa_base_fbo_format(&intel->ctx,
image->internal_format);
rb->NeedsFinishRenderTexture = true;
}
/**
* Called by _mesa_resize_framebuffer() for each hardware renderbuffer when a
* window system framebuffer is resized.
*
* Any actual buffer reallocations for hardware renderbuffers (which would
* have triggered _mesa_resize_framebuffer()) were done by
* intel_process_dri2_buffer().
*/
static GLboolean
intel_alloc_window_storage(struct gl_context * ctx, struct gl_renderbuffer *rb,
GLenum internalFormat, GLuint width, GLuint height)
{
ASSERT(rb->Name == 0);
rb->Width = width;
rb->Height = height;
rb->InternalFormat = internalFormat;
return true;
}
/** Dummy function for gl_renderbuffer::AllocStorage() */
static GLboolean
intel_nop_alloc_storage(struct gl_context * ctx, struct gl_renderbuffer *rb,
GLenum internalFormat, GLuint width, GLuint height)
{
_mesa_problem(ctx, "intel_op_alloc_storage should never be called.");
return false;
}
/**
* Create a new intel_renderbuffer which corresponds to an on-screen window,
* not a user-created renderbuffer.
*
* \param num_samples must be quantized.
*/
struct intel_renderbuffer *
intel_create_renderbuffer(gl_format format, unsigned num_samples)
{
struct intel_renderbuffer *irb;
struct gl_renderbuffer *rb;
GET_CURRENT_CONTEXT(ctx);
irb = CALLOC_STRUCT(intel_renderbuffer);
if (!irb) {
_mesa_error(ctx, GL_OUT_OF_MEMORY, "creating renderbuffer");
return NULL;
}
rb = &irb->Base.Base;
_mesa_init_renderbuffer(rb, 0);
rb->ClassID = INTEL_RB_CLASS;
rb->_BaseFormat = _mesa_get_format_base_format(format);
rb->Format = format;
rb->InternalFormat = rb->_BaseFormat;
rb->NumSamples = num_samples;
/* intel-specific methods */
rb->Delete = intel_delete_renderbuffer;
rb->AllocStorage = intel_alloc_window_storage;
return irb;
}
/**
* Private window-system buffers (as opposed to ones shared with the display
* server created with intel_create_renderbuffer()) are most similar in their
* handling to user-created renderbuffers, but they have a resize handler that
* may be called at intel_update_renderbuffers() time.
*
* \param num_samples must be quantized.
*/
struct intel_renderbuffer *
intel_create_private_renderbuffer(gl_format format, unsigned num_samples)
{
struct intel_renderbuffer *irb;
irb = intel_create_renderbuffer(format, num_samples);
irb->Base.Base.AllocStorage = intel_alloc_renderbuffer_storage;
return irb;
}
/**
* Create a new renderbuffer object.
* Typically called via glBindRenderbufferEXT().
*/
static struct gl_renderbuffer *
intel_new_renderbuffer(struct gl_context * ctx, GLuint name)
{
/*struct intel_context *intel = intel_context(ctx); */
struct intel_renderbuffer *irb;
struct gl_renderbuffer *rb;
irb = CALLOC_STRUCT(intel_renderbuffer);
if (!irb) {
_mesa_error(ctx, GL_OUT_OF_MEMORY, "creating renderbuffer");
return NULL;
}
rb = &irb->Base.Base;
_mesa_init_renderbuffer(rb, name);
rb->ClassID = INTEL_RB_CLASS;
/* intel-specific methods */
rb->Delete = intel_delete_renderbuffer;
rb->AllocStorage = intel_alloc_renderbuffer_storage;
/* span routines set in alloc_storage function */
return rb;
}
/**
* Called via glBindFramebufferEXT().
*/
static void
intel_bind_framebuffer(struct gl_context * ctx, GLenum target,
struct gl_framebuffer *fb, struct gl_framebuffer *fbread)
{
if (target == GL_FRAMEBUFFER_EXT || target == GL_DRAW_FRAMEBUFFER_EXT) {
intel_draw_buffer(ctx);
}
else {
/* don't need to do anything if target == GL_READ_FRAMEBUFFER_EXT */
}
}
/**
* Called via glFramebufferRenderbufferEXT().
*/
static void
intel_framebuffer_renderbuffer(struct gl_context * ctx,
struct gl_framebuffer *fb,
GLenum attachment, struct gl_renderbuffer *rb)
{
DBG("Intel FramebufferRenderbuffer %u %u\n", fb->Name, rb ? rb->Name : 0);
_mesa_framebuffer_renderbuffer(ctx, fb, attachment, rb);
intel_draw_buffer(ctx);
}
static bool
intel_renderbuffer_update_wrapper(struct intel_context *intel,
struct intel_renderbuffer *irb,
struct gl_texture_image *image,
uint32_t layer)
{
struct gl_renderbuffer *rb = &irb->Base.Base;
struct intel_texture_image *intel_image = intel_texture_image(image);
struct intel_mipmap_tree *mt = intel_image->mt;
int level = image->Level;
rb->Depth = image->Depth;
rb->AllocStorage = intel_nop_alloc_storage;
intel_miptree_check_level_layer(mt, level, layer);
irb->mt_level = level;
switch (mt->msaa_layout) {
case INTEL_MSAA_LAYOUT_UMS:
case INTEL_MSAA_LAYOUT_CMS:
irb->mt_layer = layer * mt->num_samples;
break;
default:
irb->mt_layer = layer;
}
intel_miptree_reference(&irb->mt, mt);
intel_renderbuffer_set_draw_offset(irb);
if (mt->hiz_mt == NULL &&
intel->vtbl.is_hiz_depth_format(intel, rb->Format)) {
intel_miptree_alloc_hiz(intel, mt);
if (!mt->hiz_mt)
return false;
}
return true;
}
void
intel_renderbuffer_set_draw_offset(struct intel_renderbuffer *irb)
{
unsigned int dst_x, dst_y;
/* compute offset of the particular 2D image within the texture region */
intel_miptree_get_image_offset(irb->mt,
irb->mt_level,
irb->mt_layer,
&dst_x, &dst_y);
irb->draw_x = dst_x;
irb->draw_y = dst_y;
}
/**
* Called by glFramebufferTexture[123]DEXT() (and other places) to
* prepare for rendering into texture memory. This might be called
* many times to choose different texture levels, cube faces, etc
* before intel_finish_render_texture() is ever called.
*/
static void
intel_render_texture(struct gl_context * ctx,
struct gl_framebuffer *fb,
struct gl_renderbuffer_attachment *att)
{
struct intel_context *intel = intel_context(ctx);
struct gl_renderbuffer *rb = att->Renderbuffer;
struct intel_renderbuffer *irb = intel_renderbuffer(rb);
struct gl_texture_image *image = rb->TexImage;
struct intel_texture_image *intel_image = intel_texture_image(image);
struct intel_mipmap_tree *mt = intel_image->mt;
int layer;
(void) fb;
if (att->CubeMapFace > 0) {
assert(att->Zoffset == 0);
layer = att->CubeMapFace;
} else {
layer = att->Zoffset;
}
if (!intel_image->mt) {
/* Fallback on drawing to a texture that doesn't have a miptree
* (has a border, width/height 0, etc.)
*/
_swrast_render_texture(ctx, fb, att);
return;
}
intel_miptree_check_level_layer(mt, att->TextureLevel, layer);
if (!intel_renderbuffer_update_wrapper(intel, irb, image, layer)) {
_swrast_render_texture(ctx, fb, att);
return;
}
DBG("Begin render %s texture tex=%u w=%d h=%d d=%d refcount=%d\n",
_mesa_get_format_name(image->TexFormat),
att->Texture->Name, image->Width, image->Height, image->Depth,
rb->RefCount);
/* update drawing region, etc */
intel_draw_buffer(ctx);
}
/**
* Called by Mesa when rendering to a texture is done.
*/
static void
intel_finish_render_texture(struct gl_context * ctx, struct gl_renderbuffer *rb)
{
struct intel_context *intel = intel_context(ctx);
DBG("Finish render %s texture\n", _mesa_get_format_name(rb->Format));
/* 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);
}
#define fbo_incomplete(fb, ...) do { \
static GLuint msg_id = 0; \
if (unlikely(ctx->Const.ContextFlags & GL_CONTEXT_FLAG_DEBUG_BIT)) { \
_mesa_gl_debug(ctx, &msg_id, \
MESA_DEBUG_TYPE_OTHER, \
MESA_DEBUG_SEVERITY_MEDIUM, \
__VA_ARGS__); \
} \
DBG(__VA_ARGS__); \
fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED; \
} while (0)
/**
* Do additional "completeness" testing of a framebuffer object.
*/
static void
intel_validate_framebuffer(struct gl_context *ctx, struct gl_framebuffer *fb)
{
struct intel_context *intel = intel_context(ctx);
struct intel_renderbuffer *depthRb =
intel_get_renderbuffer(fb, BUFFER_DEPTH);
struct intel_renderbuffer *stencilRb =
intel_get_renderbuffer(fb, BUFFER_STENCIL);
struct intel_mipmap_tree *depth_mt = NULL, *stencil_mt = NULL;
int i;
DBG("%s() on fb %p (%s)\n", __FUNCTION__,
fb, (fb == ctx->DrawBuffer ? "drawbuffer" :
(fb == ctx->ReadBuffer ? "readbuffer" : "other buffer")));
if (depthRb)
depth_mt = depthRb->mt;
if (stencilRb) {
stencil_mt = stencilRb->mt;
if (stencil_mt->stencil_mt)
stencil_mt = stencil_mt->stencil_mt;
}
if (depth_mt && stencil_mt) {
if (depth_mt == stencil_mt) {
/* For true packed depth/stencil (not faked on prefers-separate-stencil
* hardware) we need to be sure they're the same level/layer, since
* we'll be emitting a single packet describing the packed setup.
*/
if (depthRb->mt_level != stencilRb->mt_level ||
depthRb->mt_layer != stencilRb->mt_layer) {
fbo_incomplete(fb,
"FBO incomplete: depth image level/layer %d/%d != "
"stencil image %d/%d\n",
depthRb->mt_level,
depthRb->mt_layer,
stencilRb->mt_level,
stencilRb->mt_layer);
}
} else {
if (!intel->has_separate_stencil) {
fbo_incomplete(fb, "FBO incomplete: separate stencil "
"unsupported\n");
}
if (stencil_mt->format != MESA_FORMAT_S8) {
fbo_incomplete(fb, "FBO incomplete: separate stencil is %s "
"instead of S8\n",
_mesa_get_format_name(stencil_mt->format));
}
if (intel->gen < 7 && !intel_renderbuffer_has_hiz(depthRb)) {
/* Before Gen7, separate depth and stencil buffers can be used
* only if HiZ is enabled. From the Sandybridge PRM, Volume 2,
* Part 1, Bit 3DSTATE_DEPTH_BUFFER.SeparateStencilBufferEnable:
* [DevSNB]: This field must be set to the same value (enabled
* or disabled) as Hierarchical Depth Buffer Enable.
*/
fbo_incomplete(fb, "FBO incomplete: separate stencil "
"without HiZ\n");
}
}
}
for (i = 0; i < Elements(fb->Attachment); i++) {
struct gl_renderbuffer *rb;
struct intel_renderbuffer *irb;
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) {
fbo_incomplete(fb, "FBO incomplete: attachment without "
"renderbuffer\n");
continue;
}
if (fb->Attachment[i].Type == GL_TEXTURE) {
if (rb->TexImage->Border) {
fbo_incomplete(fb, "FBO incomplete: texture with border\n");
continue;
}
}
irb = intel_renderbuffer(rb);
if (irb == NULL) {
fbo_incomplete(fb, "FBO incomplete: software rendering "
"renderbuffer\n");
continue;
}
if (!intel->vtbl.render_target_supported(intel, rb)) {
fbo_incomplete(fb, "FBO incomplete: Unsupported HW "
"texture/renderbuffer format attached: %s\n",
_mesa_get_format_name(intel_rb_format(irb)));
}
}
}
/**
* 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_with_blitter(struct gl_context *ctx,
GLint srcX0, GLint srcY0,
GLint srcX1, GLint srcY1,
GLint dstX0, GLint dstY0,
GLint dstX1, GLint dstY1,
GLbitfield mask, GLenum filter)
{
struct intel_context *intel = intel_context(ctx);
if (mask & GL_COLOR_BUFFER_BIT) {
GLint i;
const struct gl_framebuffer *drawFb = ctx->DrawBuffer;
const struct gl_framebuffer *readFb = ctx->ReadBuffer;
struct gl_renderbuffer *src_rb = readFb->_ColorReadBuffer;
struct intel_renderbuffer *src_irb = intel_renderbuffer(src_rb);
if (!src_irb) {
perf_debug("glBlitFramebuffer(): missing src renderbuffer. "
"Falling back to software rendering.\n");
return mask;
}
/* 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 probably use the blit engine.
*/
if (!(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)) {
perf_debug("glBlitFramebuffer(): non-1:1 blit. "
"Falling back to software rendering.\n");
return mask;
}
/* Blit to all active draw buffers. We don't do any pre-checking,
* because we assume that copying to MRTs is rare, and failure midway
* through copying is even more rare. Even if it was to occur, it's
* safe to let meta start the copy over from scratch, because
* glBlitFramebuffer completely overwrites the destination pixels, and
* results are undefined if any destination pixels have a dependency on
* source pixels.
*/
for (i = 0; i < ctx->DrawBuffer->_NumColorDrawBuffers; i++) {
struct gl_renderbuffer *dst_rb = ctx->DrawBuffer->_ColorDrawBuffers[i];
struct intel_renderbuffer *dst_irb = intel_renderbuffer(dst_rb);
if (!dst_irb) {
perf_debug("glBlitFramebuffer(): missing dst renderbuffer. "
"Falling back to software rendering.\n");
return mask;
}
gl_format src_format = _mesa_get_srgb_format_linear(src_rb->Format);
gl_format dst_format = _mesa_get_srgb_format_linear(dst_rb->Format);
if (src_format != dst_format) {
perf_debug("glBlitFramebuffer(): unsupported blit from %s to %s. "
"Falling back to software rendering.\n",
_mesa_get_format_name(src_format),
_mesa_get_format_name(dst_format));
return mask;
}
if (!intel_miptree_blit(intel,
src_irb->mt,
src_irb->mt_level, src_irb->mt_layer,
srcX0, srcY0, src_rb->Name == 0,
dst_irb->mt,
dst_irb->mt_level, dst_irb->mt_layer,
dstX0, dstY0, dst_rb->Name == 0,
dstX1 - dstX0, dstY1 - dstY0, GL_COPY)) {
perf_debug("glBlitFramebuffer(): unknown blit failure. "
"Falling back to software rendering.\n");
return mask;
}
}
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)
{
#ifndef I915
mask = brw_blorp_framebuffer(intel_context(ctx),
srcX0, srcY0, srcX1, srcY1,
dstX0, dstY0, dstX1, dstY1,
mask, filter);
if (mask == 0x0)
return;
#endif
/* Try using the BLT engine. */
mask = intel_blit_framebuffer_with_blitter(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);
}
/**
* This is a no-op except on multisample buffers shared with DRI2.
*/
void
intel_renderbuffer_set_needs_downsample(struct intel_renderbuffer *irb)
{
if (irb->mt && irb->mt->singlesample_mt)
irb->mt->need_downsample = true;
}
/**
* Does the renderbuffer have hiz enabled?
*/
bool
intel_renderbuffer_has_hiz(struct intel_renderbuffer *irb)
{
return intel_miptree_slice_has_hiz(irb->mt, irb->mt_level, irb->mt_layer);
}
void
intel_renderbuffer_set_needs_hiz_resolve(struct intel_renderbuffer *irb)
{
if (irb->mt) {
intel_miptree_slice_set_needs_hiz_resolve(irb->mt,
irb->mt_level,
irb->mt_layer);
}
}
void
intel_renderbuffer_set_needs_depth_resolve(struct intel_renderbuffer *irb)
{
if (irb->mt) {
intel_miptree_slice_set_needs_depth_resolve(irb->mt,
irb->mt_level,
irb->mt_layer);
}
}
bool
intel_renderbuffer_resolve_hiz(struct intel_context *intel,
struct intel_renderbuffer *irb)
{
if (irb->mt)
return intel_miptree_slice_resolve_hiz(intel,
irb->mt,
irb->mt_level,
irb->mt_layer);
return false;
}
bool
intel_renderbuffer_resolve_depth(struct intel_context *intel,
struct intel_renderbuffer *irb)
{
if (irb->mt)
return intel_miptree_slice_resolve_depth(intel,
irb->mt,
irb->mt_level,
irb->mt_layer);
return false;
}
void
intel_renderbuffer_move_to_temp(struct intel_context *intel,
struct intel_renderbuffer *irb,
bool invalidate)
{
struct gl_renderbuffer *rb =&irb->Base.Base;
struct intel_texture_image *intel_image = intel_texture_image(rb->TexImage);
struct intel_mipmap_tree *new_mt;
int width, height, depth;
intel_miptree_get_dimensions_for_image(rb->TexImage, &width, &height, &depth);
new_mt = intel_miptree_create(intel, rb->TexImage->TexObject->Target,
intel_image->base.Base.TexFormat,
intel_image->base.Base.Level,
intel_image->base.Base.Level,
width, height, depth,
true,
irb->mt->num_samples,
INTEL_MIPTREE_TILING_ANY);
if (intel->vtbl.is_hiz_depth_format(intel, new_mt->format)) {
intel_miptree_alloc_hiz(intel, new_mt);
}
intel_miptree_copy_teximage(intel, intel_image, new_mt, invalidate);
intel_miptree_reference(&irb->mt, intel_image->mt);
intel_renderbuffer_set_draw_offset(irb);
intel_miptree_release(&new_mt);
}
/**
* Do one-time context initializations related to GL_EXT_framebuffer_object.
* Hook in device driver functions.
*/
void
intel_fbo_init(struct intel_context *intel)
{
intel->ctx.Driver.NewFramebuffer = intel_new_framebuffer;
intel->ctx.Driver.NewRenderbuffer = intel_new_renderbuffer;
intel->ctx.Driver.MapRenderbuffer = intel_map_renderbuffer;
intel->ctx.Driver.UnmapRenderbuffer = intel_unmap_renderbuffer;
intel->ctx.Driver.BindFramebuffer = intel_bind_framebuffer;
intel->ctx.Driver.FramebufferRenderbuffer = intel_framebuffer_renderbuffer;
intel->ctx.Driver.RenderTexture = intel_render_texture;
intel->ctx.Driver.FinishRenderTexture = intel_finish_render_texture;
intel->ctx.Driver.ValidateFramebuffer = intel_validate_framebuffer;
intel->ctx.Driver.BlitFramebuffer = intel_blit_framebuffer;
intel->ctx.Driver.EGLImageTargetRenderbufferStorage =
intel_image_target_renderbuffer_storage;
}

View file

@ -0,0 +1,212 @@
/**************************************************************************
*
* Copyright 2006 Tungsten Graphics, Inc., Cedar Park, Texas.
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sub license, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial portions
* of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
**************************************************************************/
#ifndef INTEL_FBO_H
#define INTEL_FBO_H
#include <stdbool.h>
#include <assert.h>
#include "main/formats.h"
#include "main/macros.h"
#include "intel_context.h"
#include "intel_mipmap_tree.h"
#include "intel_screen.h"
#ifdef __cplusplus
extern "C" {
#endif
struct intel_context;
struct intel_mipmap_tree;
struct intel_texture_image;
/**
* Intel renderbuffer, derived from gl_renderbuffer.
*/
struct intel_renderbuffer
{
struct swrast_renderbuffer Base;
struct intel_mipmap_tree *mt; /**< The renderbuffer storage. */
drm_intel_bo *map_bo;
/**
* \name Miptree view
* \{
*
* Multiple renderbuffers may simultaneously wrap a single texture and each
* provide a different view into that texture. The fields below indicate
* which miptree slice is wrapped by this renderbuffer. The fields' values
* are consistent with the 'level' and 'layer' parameters of
* glFramebufferTextureLayer().
*
* For renderbuffers not created with glFramebufferTexture*(), mt_level and
* mt_layer are 0.
*/
unsigned int mt_level;
unsigned int mt_layer;
/** \} */
GLuint draw_x, draw_y; /**< Offset of drawing within the region */
};
/**
* gl_renderbuffer is a base class which we subclass. The Class field
* is used for simple run-time type checking.
*/
#define INTEL_RB_CLASS 0x12345678
/**
* Return a gl_renderbuffer ptr casted to intel_renderbuffer.
* NULL will be returned if the rb isn't really an intel_renderbuffer.
* This is determined by checking the ClassID.
*/
static INLINE struct intel_renderbuffer *
intel_renderbuffer(struct gl_renderbuffer *rb)
{
struct intel_renderbuffer *irb = (struct intel_renderbuffer *) rb;
if (irb && irb->Base.Base.ClassID == INTEL_RB_CLASS) {
/*_mesa_warning(NULL, "Returning non-intel Rb\n");*/
return irb;
}
else
return NULL;
}
/**
* \brief Return the framebuffer attachment specified by attIndex.
*
* If the framebuffer lacks the specified attachment, then return null.
*
* If the attached renderbuffer is a wrapper, then return wrapped
* renderbuffer.
*/
static INLINE struct intel_renderbuffer *
intel_get_renderbuffer(struct gl_framebuffer *fb, gl_buffer_index attIndex)
{
struct gl_renderbuffer *rb;
assert((unsigned)attIndex < ARRAY_SIZE(fb->Attachment));
rb = fb->Attachment[attIndex].Renderbuffer;
if (!rb)
return NULL;
return intel_renderbuffer(rb);
}
static INLINE gl_format
intel_rb_format(const struct intel_renderbuffer *rb)
{
return rb->Base.Base.Format;
}
extern struct intel_renderbuffer *
intel_create_renderbuffer(gl_format format, unsigned num_samples);
struct intel_renderbuffer *
intel_create_private_renderbuffer(gl_format format, unsigned num_samples);
struct gl_renderbuffer*
intel_create_wrapped_renderbuffer(struct gl_context * ctx,
int width, int height,
gl_format format);
extern void
intel_fbo_init(struct intel_context *intel);
extern void
intel_flip_renderbuffers(struct gl_framebuffer *fb);
void
intel_renderbuffer_set_draw_offset(struct intel_renderbuffer *irb);
static inline uint32_t
intel_renderbuffer_get_tile_offsets(struct intel_renderbuffer *irb,
uint32_t *tile_x,
uint32_t *tile_y)
{
return intel_miptree_get_tile_offsets(irb->mt, irb->mt_level, irb->mt_layer,
tile_x, tile_y);
}
struct intel_region*
intel_get_rb_region(struct gl_framebuffer *fb, GLuint attIndex);
void
intel_renderbuffer_set_needs_downsample(struct intel_renderbuffer *irb);
bool
intel_renderbuffer_has_hiz(struct intel_renderbuffer *irb);
void
intel_renderbuffer_set_needs_hiz_resolve(struct intel_renderbuffer *irb);
void
intel_renderbuffer_set_needs_depth_resolve(struct intel_renderbuffer *irb);
/**
* \brief Perform a HiZ resolve on the renderbuffer.
*
* It is safe to call this function on a renderbuffer without HiZ. In that
* case, the function is a no-op.
*
* \return false if no resolve was needed
*/
bool
intel_renderbuffer_resolve_hiz(struct intel_context *intel,
struct intel_renderbuffer *irb);
/**
* \brief Perform a depth resolve on the renderbuffer.
*
* It is safe to call this function on a renderbuffer without HiZ. In that
* case, the function is a no-op.
*
* \return false if no resolve was needed
*/
bool
intel_renderbuffer_resolve_depth(struct intel_context *intel,
struct intel_renderbuffer *irb);
void intel_renderbuffer_move_to_temp(struct intel_context *intel,
struct intel_renderbuffer *irb,
bool invalidate);
unsigned
intel_quantize_num_samples(struct intel_screen *intel, unsigned num_samples);
#ifdef __cplusplus
}
#endif
#endif /* INTEL_FBO_H */

View file

@ -1 +0,0 @@
../intel/intel_mipmap_tree.c

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,788 @@
/**************************************************************************
*
* Copyright 2006 Tungsten Graphics, Inc., Cedar Park, Texas.
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sub license, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial portions
* of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
**************************************************************************/
#ifndef INTEL_MIPMAP_TREE_H
#define INTEL_MIPMAP_TREE_H
#include <assert.h>
#include "intel_regions.h"
#include "intel_resolve_map.h"
#ifdef __cplusplus
extern "C" {
#endif
/* A layer on top of the intel_regions code which adds:
*
* - Code to size and layout a region to hold a set of mipmaps.
* - Query to determine if a new image fits in an existing tree.
* - More refcounting
* - maybe able to remove refcounting from intel_region?
* - ?
*
* The fixed mipmap layout of intel hardware where one offset
* specifies the position of all images in a mipmap hierachy
* complicates the implementation of GL texture image commands,
* compared to hardware where each image is specified with an
* independent offset.
*
* In an ideal world, each texture object would be associated with a
* single bufmgr buffer or 2d intel_region, and all the images within
* the texture object would slot into the tree as they arrive. The
* reality can be a little messier, as images can arrive from the user
* with sizes that don't fit in the existing tree, or in an order
* where the tree layout cannot be guessed immediately.
*
* This structure encodes an idealized mipmap tree. The GL image
* commands build these where possible, otherwise store the images in
* temporary system buffers.
*/
struct intel_resolve_map;
struct intel_texture_image;
/**
* When calling intel_miptree_map() on an ETC-transcoded-to-RGB miptree or a
* depthstencil-split-to-separate-stencil miptree, we'll normally make a
* tmeporary and recreate the kind of data requested by Mesa core, since we're
* satisfying some glGetTexImage() request or something.
*
* However, occasionally you want to actually map the miptree's current data
* without transcoding back. This flag to intel_miptree_map() gets you that.
*/
#define BRW_MAP_DIRECT_BIT 0x80000000
struct intel_miptree_map {
/** Bitfield of GL_MAP_READ_BIT, GL_MAP_WRITE_BIT, GL_MAP_INVALIDATE_BIT */
GLbitfield mode;
/** Region of interest for the map. */
int x, y, w, h;
/** Possibly malloced temporary buffer for the mapping. */
void *buffer;
/** Possible pointer to a temporary linear miptree for the mapping. */
struct intel_mipmap_tree *mt;
/** Pointer to the start of (map_x, map_y) returned by the mapping. */
void *ptr;
/** Stride of the mapping. */
int stride;
/**
* intel_mipmap_tree::singlesample_mt is temporary storage that persists
* only for the duration of the map.
*/
bool singlesample_mt_is_tmp;
};
/**
* Describes the location of each texture image within a texture region.
*/
struct intel_mipmap_level
{
/** Offset to this miptree level, used in computing x_offset. */
GLuint level_x;
/** Offset to this miptree level, used in computing y_offset. */
GLuint level_y;
GLuint width;
GLuint height;
/**
* \brief Number of 2D slices in this miplevel.
*
* The exact semantics of depth varies according to the texture target:
* - For GL_TEXTURE_CUBE_MAP, depth is 6.
* - For GL_TEXTURE_2D_ARRAY, depth is the number of array slices. It is
* identical for all miplevels in the texture.
* - For GL_TEXTURE_3D, it is the texture's depth at this miplevel. Its
* value, like width and height, varies with miplevel.
* - For other texture types, depth is 1.
*/
GLuint depth;
/**
* \brief List of 2D images in this mipmap level.
*
* This may be a list of cube faces, array slices in 2D array texture, or
* layers in a 3D texture. The list's length is \c depth.
*/
struct intel_mipmap_slice {
/**
* \name Offset to slice
* \{
*
* Hardware formats are so diverse that that there is no unified way to
* compute the slice offsets, so we store them in this table.
*
* The (x, y) offset to slice \c s at level \c l relative the miptrees
* base address is
* \code
* x = mt->level[l].slice[s].x_offset
* y = mt->level[l].slice[s].y_offset
*/
GLuint x_offset;
GLuint y_offset;
/** \} */
/**
* Mapping information. Persistent for the duration of
* intel_miptree_map/unmap on this slice.
*/
struct intel_miptree_map *map;
/**
* \brief Is HiZ enabled for this slice?
*
* If \c mt->level[l].slice[s].has_hiz is set, then (1) \c mt->hiz_mt
* has been allocated and (2) the HiZ memory corresponding to this slice
* resides at \c mt->hiz_mt->level[l].slice[s].
*/
bool has_hiz;
} *slice;
};
/**
* Enum for keeping track of the different MSAA layouts supported by Gen7.
*/
enum intel_msaa_layout
{
/**
* Ordinary surface with no MSAA.
*/
INTEL_MSAA_LAYOUT_NONE,
/**
* Interleaved Multisample Surface. The additional samples are
* accommodated by scaling up the width and the height of the surface so
* that all the samples corresponding to a pixel are located at nearby
* memory locations.
*/
INTEL_MSAA_LAYOUT_IMS,
/**
* Uncompressed Multisample Surface. The surface is stored as a 2D array,
* with array slice n containing all pixel data for sample n.
*/
INTEL_MSAA_LAYOUT_UMS,
/**
* Compressed Multisample Surface. The surface is stored as in
* INTEL_MSAA_LAYOUT_UMS, but there is an additional buffer called the MCS
* (Multisample Control Surface) buffer. Each pixel in the MCS buffer
* indicates the mapping from sample number to array slice. This allows
* the common case (where all samples constituting a pixel have the same
* color value) to be stored efficiently by just using a single array
* slice.
*/
INTEL_MSAA_LAYOUT_CMS,
};
#ifndef I915
/**
* Enum for keeping track of the state of an MCS buffer associated with a
* miptree. This determines when fast clear related operations are needed.
*
* Fast clear works by deferring the memory writes that would be used to clear
* the buffer, so that instead of performing them at the time of the clear
* operation, the hardware automatically performs them at the time that the
* buffer is later accessed for rendering. The MCS buffer keeps track of
* which regions of the buffer still have pending clear writes.
*
* This enum keeps track of the driver's knowledge of the state of the MCS
* buffer.
*
* MCS buffers only exist on Gen7+.
*/
enum intel_mcs_state
{
/**
* There is no MCS buffer for this miptree, and one should never be
* allocated.
*/
INTEL_MCS_STATE_NONE,
/**
* An MCS buffer exists for this miptree, and it is used for MSAA purposes.
*/
INTEL_MCS_STATE_MSAA,
/**
* No deferred clears are pending for this miptree, and the contents of the
* color buffer are entirely correct. An MCS buffer may or may not exist
* for this miptree. If it does exist, it is entirely in the "no deferred
* clears pending" state. If it does not exist, it will be created the
* first time a fast color clear is executed.
*
* In this state, the color buffer can be used for purposes other than
* rendering without needing a render target resolve.
*/
INTEL_MCS_STATE_RESOLVED,
/**
* An MCS buffer exists for this miptree, and deferred clears are pending
* for some regions of the color buffer, as indicated by the MCS buffer.
* The contents of the color buffer are only correct for the regions where
* the MCS buffer doesn't indicate a deferred clear.
*
* In this state, a render target resolve must be performed before the
* color buffer can be used for purposes other than rendering.
*/
INTEL_MCS_STATE_UNRESOLVED,
/**
* An MCS buffer exists for this miptree, and deferred clears are pending
* for the entire color buffer, and the contents of the MCS buffer reflect
* this. The contents of the color buffer are undefined.
*
* In this state, a render target resolve must be performed before the
* color buffer can be used for purposes other than rendering.
*
* If the client attempts to clear a buffer which is already in this state,
* the clear can be safely skipped, since the buffer is already clear.
*/
INTEL_MCS_STATE_CLEAR,
};
#endif
struct intel_mipmap_tree
{
/* Effectively the key:
*/
GLenum target;
/**
* Generally, this is just the same as the gl_texture_image->TexFormat or
* gl_renderbuffer->Format.
*
* However, for textures and renderbuffers with packed depth/stencil formats
* on hardware where we want or need to use separate stencil, there will be
* two miptrees for storing the data. If the depthstencil texture or rb is
* MESA_FORMAT_Z32_FLOAT_X24S8, then mt->format will be
* MESA_FORMAT_Z32_FLOAT, otherwise for MESA_FORMAT_S8_Z24 objects it will be
* MESA_FORMAT_X8_Z24.
*
* For ETC1/ETC2 textures, this is one of the uncompressed mesa texture
* formats if the hardware lacks support for ETC1/ETC2. See @ref wraps_etc.
*/
gl_format format;
/** This variable stores the value of ETC compressed texture format */
gl_format etc_format;
/**
* The X offset of each image in the miptree must be aligned to this. See
* the "Alignment Unit Size" section of the BSpec.
*/
unsigned int align_w;
unsigned int align_h; /**< \see align_w */
GLuint first_level;
GLuint last_level;
/**
* Level zero image dimensions. These dimensions correspond to the
* physical layout of data in memory. Accordingly, they account for the
* extra width, height, and or depth that must be allocated in order to
* accommodate multisample formats, and they account for the extra factor
* of 6 in depth that must be allocated in order to accommodate cubemap
* textures.
*/
GLuint physical_width0, physical_height0, physical_depth0;
GLuint cpp;
GLuint num_samples;
bool compressed;
/**
* Level zero image dimensions. These dimensions correspond to the
* logical width, height, and depth of the region as seen by client code.
* Accordingly, they do not account for the extra width, height, and/or
* depth that must be allocated in order to accommodate multisample
* formats, nor do they account for the extra factor of 6 in depth that
* must be allocated in order to accommodate cubemap textures.
*/
uint32_t logical_width0, logical_height0, logical_depth0;
/**
* For 1D array, 2D array, cube, and 2D multisampled surfaces on Gen7: true
* if the surface only contains LOD 0, and hence no space is for LOD's
* other than 0 in between array slices.
*
* Corresponds to the surface_array_spacing bit in gen7_surface_state.
*/
bool array_spacing_lod0;
/**
* MSAA layout used by this buffer.
*/
enum intel_msaa_layout msaa_layout;
/* Derived from the above:
*/
GLuint total_width;
GLuint total_height;
/* The 3DSTATE_CLEAR_PARAMS value associated with the last depth clear to
* this depth mipmap tree, if any.
*/
uint32_t depth_clear_value;
/* Includes image offset tables:
*/
struct intel_mipmap_level level[MAX_TEXTURE_LEVELS];
/* The data is held here:
*/
struct intel_region *region;
/* Offset into region bo where miptree starts:
*/
uint32_t offset;
/**
* \brief Singlesample miptree.
*
* This is used under two cases.
*
* --- Case 1: As persistent singlesample storage for multisample window
* system front and back buffers ---
*
* Suppose that the window system FBO was created with a multisample
* config. Let `back_irb` be the `intel_renderbuffer` for the FBO's back
* buffer. Then `back_irb` contains two miptrees: a parent multisample
* miptree (back_irb->mt) and a child singlesample miptree
* (back_irb->mt->singlesample_mt). The DRM buffer shared with DRI2
* belongs to `back_irb->mt->singlesample_mt` and contains singlesample
* data. The singlesample miptree is created at the same time as and
* persists for the lifetime of its parent multisample miptree.
*
* When access to the singlesample data is needed, such as at
* eglSwapBuffers and glReadPixels, an automatic downsample occurs from
* `back_rb->mt` to `back_rb->mt->singlesample_mt` when necessary.
*
* This description of the back buffer applies analogously to the front
* buffer.
*
*
* --- Case 2: As temporary singlesample storage for mapping multisample
* miptrees ---
*
* Suppose the intel_miptree_map is called on a multisample miptree, `mt`,
* for which case 1 does not apply (that is, `mt` does not belong to
* a front or back buffer). Then `mt->singlesample_mt` is null at the
* start of the call. intel_miptree_map will create a temporary
* singlesample miptree, store it at `mt->singlesample_mt`, downsample from
* `mt` to `mt->singlesample_mt` if necessary, then map
* `mt->singlesample_mt`. The temporary miptree is later deleted during
* intel_miptree_unmap.
*/
struct intel_mipmap_tree *singlesample_mt;
/**
* \brief A downsample is needed from this miptree to singlesample_mt.
*/
bool need_downsample;
/**
* \brief HiZ miptree
*
* The hiz miptree contains the miptree's hiz buffer. To allocate the hiz
* miptree, use intel_miptree_alloc_hiz().
*
* To determine if hiz is enabled, do not check this pointer. Instead, use
* intel_miptree_slice_has_hiz().
*/
struct intel_mipmap_tree *hiz_mt;
/**
* \brief Map of miptree slices to needed resolves.
*
* This is used only when the miptree has a child HiZ miptree.
*
* Let \c mt be a depth miptree with HiZ enabled. Then the resolve map is
* \c mt->hiz_map. The resolve map of the child HiZ miptree, \c
* mt->hiz_mt->hiz_map, is unused.
*/
struct intel_resolve_map hiz_map;
/**
* \brief Stencil miptree for depthstencil textures.
*
* This miptree is used for depthstencil textures and renderbuffers that
* require separate stencil. It always has the true copy of the stencil
* bits, regardless of mt->format.
*
* \see intel_miptree_map_depthstencil()
* \see intel_miptree_unmap_depthstencil()
*/
struct intel_mipmap_tree *stencil_mt;
#ifndef I915
/**
* \brief MCS miptree.
*
* This miptree contains the "multisample control surface", which stores
* the necessary information to implement compressed MSAA
* (INTEL_MSAA_FORMAT_CMS) and "fast color clear" behaviour on Gen7+.
*
* NULL if no MCS miptree is in use for this surface.
*/
struct intel_mipmap_tree *mcs_mt;
/**
* MCS state for this buffer.
*/
enum intel_mcs_state mcs_state;
#endif
/**
* The SURFACE_STATE bits associated with the last fast color clear to this
* color mipmap tree, if any.
*
* This value will only ever contain ones in bits 28-31, so it is safe to
* OR into dword 7 of SURFACE_STATE.
*/
uint32_t fast_clear_color_value;
/* These are also refcounted:
*/
GLuint refcount;
};
enum intel_miptree_tiling_mode {
INTEL_MIPTREE_TILING_ANY,
INTEL_MIPTREE_TILING_Y,
INTEL_MIPTREE_TILING_NONE,
};
bool
intel_is_non_msrt_mcs_buffer_supported(struct intel_context *intel,
struct intel_mipmap_tree *mt);
void
intel_get_non_msrt_mcs_alignment(struct intel_context *intel,
struct intel_mipmap_tree *mt,
unsigned *width_px, unsigned *height);
bool
intel_miptree_alloc_non_msrt_mcs(struct intel_context *intel,
struct intel_mipmap_tree *mt);
struct intel_mipmap_tree *intel_miptree_create(struct intel_context *intel,
GLenum target,
gl_format format,
GLuint first_level,
GLuint last_level,
GLuint width0,
GLuint height0,
GLuint depth0,
bool expect_accelerated_upload,
GLuint num_samples,
enum intel_miptree_tiling_mode);
struct intel_mipmap_tree *
intel_miptree_create_layout(struct intel_context *intel,
GLenum target,
gl_format format,
GLuint first_level,
GLuint last_level,
GLuint width0,
GLuint height0,
GLuint depth0,
bool for_bo,
GLuint num_samples);
struct intel_mipmap_tree *
intel_miptree_create_for_bo(struct intel_context *intel,
drm_intel_bo *bo,
gl_format format,
uint32_t offset,
uint32_t width,
uint32_t height,
int pitch,
uint32_t tiling);
struct intel_mipmap_tree*
intel_miptree_create_for_dri2_buffer(struct intel_context *intel,
unsigned dri_attachment,
gl_format format,
uint32_t num_samples,
struct intel_region *region);
/**
* Create a miptree appropriate as the storage for a non-texture renderbuffer.
* The miptree has the following properties:
* - The target is GL_TEXTURE_2D.
* - There are no levels other than the base level 0.
* - Depth is 1.
*/
struct intel_mipmap_tree*
intel_miptree_create_for_renderbuffer(struct intel_context *intel,
gl_format format,
uint32_t width,
uint32_t height,
uint32_t num_samples);
/** \brief Assert that the level and layer are valid for the miptree. */
static inline void
intel_miptree_check_level_layer(struct intel_mipmap_tree *mt,
uint32_t level,
uint32_t layer)
{
assert(level >= mt->first_level);
assert(level <= mt->last_level);
assert(layer < mt->level[level].depth);
}
int intel_miptree_pitch_align (struct intel_context *intel,
struct intel_mipmap_tree *mt,
uint32_t tiling,
int pitch);
void intel_miptree_reference(struct intel_mipmap_tree **dst,
struct intel_mipmap_tree *src);
void intel_miptree_release(struct intel_mipmap_tree **mt);
/* Check if an image fits an existing mipmap tree layout
*/
bool intel_miptree_match_image(struct intel_mipmap_tree *mt,
struct gl_texture_image *image);
void
intel_miptree_get_image_offset(struct intel_mipmap_tree *mt,
GLuint level, GLuint slice,
GLuint *x, GLuint *y);
void
intel_miptree_get_dimensions_for_image(struct gl_texture_image *image,
int *width, int *height, int *depth);
uint32_t
intel_miptree_get_tile_offsets(struct intel_mipmap_tree *mt,
GLuint level, GLuint slice,
uint32_t *tile_x,
uint32_t *tile_y);
void intel_miptree_set_level_info(struct intel_mipmap_tree *mt,
GLuint level,
GLuint x, GLuint y,
GLuint w, GLuint h, GLuint d);
void intel_miptree_set_image_offset(struct intel_mipmap_tree *mt,
GLuint level,
GLuint img, GLuint x, GLuint y);
void
intel_miptree_copy_teximage(struct intel_context *intel,
struct intel_texture_image *intelImage,
struct intel_mipmap_tree *dst_mt, bool invalidate);
/**
* Copy the stencil data from \c mt->stencil_mt->region to \c mt->region for
* the given miptree slice.
*
* \see intel_mipmap_tree::stencil_mt
*/
void
intel_miptree_s8z24_scatter(struct intel_context *intel,
struct intel_mipmap_tree *mt,
uint32_t level,
uint32_t slice);
/**
* Copy the stencil data in \c mt->stencil_mt->region to \c mt->region for the
* given miptree slice.
*
* \see intel_mipmap_tree::stencil_mt
*/
void
intel_miptree_s8z24_gather(struct intel_context *intel,
struct intel_mipmap_tree *mt,
uint32_t level,
uint32_t layer);
bool
intel_miptree_alloc_mcs(struct intel_context *intel,
struct intel_mipmap_tree *mt,
GLuint num_samples);
/**
* \name Miptree HiZ functions
* \{
*
* It is safe to call the "slice_set_need_resolve" and "slice_resolve"
* functions on a miptree without HiZ. In that case, each function is a no-op.
*/
/**
* \brief Allocate the miptree's embedded HiZ miptree.
* \see intel_mipmap_tree:hiz_mt
* \return false if allocation failed
*/
bool
intel_miptree_alloc_hiz(struct intel_context *intel,
struct intel_mipmap_tree *mt);
bool
intel_miptree_slice_has_hiz(struct intel_mipmap_tree *mt,
uint32_t level,
uint32_t layer);
void
intel_miptree_slice_set_needs_hiz_resolve(struct intel_mipmap_tree *mt,
uint32_t level,
uint32_t depth);
void
intel_miptree_slice_set_needs_depth_resolve(struct intel_mipmap_tree *mt,
uint32_t level,
uint32_t depth);
/**
* \return false if no resolve was needed
*/
bool
intel_miptree_slice_resolve_hiz(struct intel_context *intel,
struct intel_mipmap_tree *mt,
unsigned int level,
unsigned int depth);
/**
* \return false if no resolve was needed
*/
bool
intel_miptree_slice_resolve_depth(struct intel_context *intel,
struct intel_mipmap_tree *mt,
unsigned int level,
unsigned int depth);
/**
* \return false if no resolve was needed
*/
bool
intel_miptree_all_slices_resolve_hiz(struct intel_context *intel,
struct intel_mipmap_tree *mt);
/**
* \return false if no resolve was needed
*/
bool
intel_miptree_all_slices_resolve_depth(struct intel_context *intel,
struct intel_mipmap_tree *mt);
/**\}*/
/**
* Update the fast clear state for a miptree to indicate that it has been used
* for rendering.
*/
static inline void
intel_miptree_used_for_rendering(struct intel_mipmap_tree *mt)
{
#ifdef I915
/* Nothing needs to be done for I915, since it doesn't support fast
* clear.
*/
#else
/* If the buffer was previously in fast clear state, change it to
* unresolved state, since it won't be guaranteed to be clear after
* rendering occurs.
*/
if (mt->mcs_state == INTEL_MCS_STATE_CLEAR)
mt->mcs_state = INTEL_MCS_STATE_UNRESOLVED;
#endif
}
void
intel_miptree_resolve_color(struct intel_context *intel,
struct intel_mipmap_tree *mt);
void
intel_miptree_make_shareable(struct intel_context *intel,
struct intel_mipmap_tree *mt);
void
intel_miptree_downsample(struct intel_context *intel,
struct intel_mipmap_tree *mt);
void
intel_miptree_upsample(struct intel_context *intel,
struct intel_mipmap_tree *mt);
/* i915_mipmap_tree.c:
*/
void i915_miptree_layout(struct intel_mipmap_tree *mt);
void i945_miptree_layout(struct intel_mipmap_tree *mt);
void brw_miptree_layout(struct intel_context *intel,
struct intel_mipmap_tree *mt);
void *intel_miptree_map_raw(struct intel_context *intel,
struct intel_mipmap_tree *mt);
void intel_miptree_unmap_raw(struct intel_context *intel,
struct intel_mipmap_tree *mt);
void
intel_miptree_map(struct intel_context *intel,
struct intel_mipmap_tree *mt,
unsigned int level,
unsigned int slice,
unsigned int x,
unsigned int y,
unsigned int w,
unsigned int h,
GLbitfield mode,
void **out_ptr,
int *out_stride);
void
intel_miptree_unmap(struct intel_context *intel,
struct intel_mipmap_tree *mt,
unsigned int level,
unsigned int slice);
#ifdef I915
static inline void
intel_hiz_exec(struct intel_context *intel, struct intel_mipmap_tree *mt,
unsigned int level, unsigned int layer, enum gen6_hiz_op op)
{
/* Stub on i915. It would be nice if we didn't execute resolve code at all
* there.
*/
}
#else
void
intel_hiz_exec(struct intel_context *intel, struct intel_mipmap_tree *mt,
unsigned int level, unsigned int layer, enum gen6_hiz_op op);
#endif
#ifdef __cplusplus
}
#endif
#endif

View file

@ -1 +0,0 @@
../intel/intel_pixel.c

View file

@ -0,0 +1,135 @@
/**************************************************************************
*
* Copyright 2006 Tungsten Graphics, Inc., Cedar Park, Texas.
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sub license, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial portionsalloc
* of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
**************************************************************************/
#include "main/accum.h"
#include "main/enums.h"
#include "main/state.h"
#include "main/bufferobj.h"
#include "main/context.h"
#include "swrast/swrast.h"
#include "intel_context.h"
#include "intel_pixel.h"
#include "intel_regions.h"
#define FILE_DEBUG_FLAG DEBUG_PIXEL
static GLenum
effective_func(GLenum func, bool src_alpha_is_one)
{
if (src_alpha_is_one) {
if (func == GL_SRC_ALPHA)
return GL_ONE;
if (func == GL_ONE_MINUS_SRC_ALPHA)
return GL_ZERO;
}
return func;
}
/**
* Check if any fragment operations are in effect which might effect
* glDraw/CopyPixels.
*/
bool
intel_check_blit_fragment_ops(struct gl_context * ctx, bool src_alpha_is_one)
{
if (ctx->NewState)
_mesa_update_state(ctx);
if (ctx->FragmentProgram._Enabled) {
DBG("fallback due to fragment program\n");
return false;
}
if (ctx->Color.BlendEnabled &&
(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 false;
}
if (ctx->Texture._EnabledUnits) {
DBG("fallback due to texturing\n");
return false;
}
if (!(ctx->Color.ColorMask[0][0] &&
ctx->Color.ColorMask[0][1] &&
ctx->Color.ColorMask[0][2] &&
ctx->Color.ColorMask[0][3])) {
DBG("fallback due to color masking\n");
return false;
}
if (ctx->Color.AlphaEnabled) {
DBG("fallback due to alpha\n");
return false;
}
if (ctx->Depth.Test) {
DBG("fallback due to depth test\n");
return false;
}
if (ctx->Fog.Enabled) {
DBG("fallback due to fog\n");
return false;
}
if (ctx->_ImageTransferState) {
DBG("fallback due to image transfer\n");
return false;
}
if (ctx->Stencil._Enabled) {
DBG("fallback due to image stencil\n");
return false;
}
if (ctx->RenderMode != GL_RENDER) {
DBG("fallback due to render mode\n");
return false;
}
return true;
}
void
intelInitPixelFuncs(struct dd_function_table *functions)
{
functions->Accum = _mesa_accum;
functions->Bitmap = intelBitmap;
functions->CopyPixels = intelCopyPixels;
functions->DrawPixels = intelDrawPixels;
functions->ReadPixels = intelReadPixels;
}

View file

@ -0,0 +1,63 @@
/**************************************************************************
*
* Copyright 2006 Tungsten Graphics, Inc., Cedar Park, Texas.
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sub license, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial portions
* of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
**************************************************************************/
#ifndef INTEL_PIXEL_H
#define INTEL_PIXEL_H
#include "main/mtypes.h"
void intelInitPixelFuncs(struct dd_function_table *functions);
bool intel_check_blit_fragment_ops(struct gl_context * ctx,
bool src_alpha_is_one);
void intelReadPixels(struct gl_context * ctx,
GLint x, GLint y,
GLsizei width, GLsizei height,
GLenum format, GLenum type,
const struct gl_pixelstore_attrib *pack,
GLvoid * pixels);
void intelDrawPixels(struct gl_context * ctx,
GLint x, GLint y,
GLsizei width, GLsizei height,
GLenum format,
GLenum type,
const struct gl_pixelstore_attrib *unpack,
const GLvoid * pixels);
void intelCopyPixels(struct gl_context * ctx,
GLint srcx, GLint srcy,
GLsizei width, GLsizei height,
GLint destx, GLint desty, GLenum type);
void intelBitmap(struct gl_context * ctx,
GLint x, GLint y,
GLsizei width, GLsizei height,
const struct gl_pixelstore_attrib *unpack,
const GLubyte * pixels);
#endif

View file

@ -1 +0,0 @@
../intel/intel_pixel_bitmap.c

View file

@ -0,0 +1,363 @@
/**************************************************************************
*
* Copyright 2006 Tungsten Graphics, Inc., Cedar Park, Texas.
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sub license, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial portionsalloc
* of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
**************************************************************************/
#include "main/glheader.h"
#include "main/enums.h"
#include "main/image.h"
#include "main/colormac.h"
#include "main/condrender.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"
#include "main/context.h"
#include "main/fbobject.h"
#include "swrast/swrast.h"
#include "drivers/common/meta.h"
#include "intel_screen.h"
#include "intel_context.h"
#include "intel_batchbuffer.h"
#include "intel_blit.h"
#include "intel_fbo.h"
#include "intel_regions.h"
#include "intel_buffers.h"
#include "intel_pixel.h"
#include "intel_reg.h"
#define FILE_DEBUG_FLAG DEBUG_PIXEL
/* Unlike the other intel_pixel_* functions, the expectation here is
* that the incoming data is not in a PBO. With the XY_TEXT blit
* method, there's no benefit haveing it in a PBO, but we could
* implement a path based on XY_MONO_SRC_COPY_BLIT which might benefit
* PBO bitmaps. I think they are probably pretty rare though - I
* wonder if Xgl uses them?
*/
static const GLubyte *map_pbo( struct gl_context *ctx,
GLsizei width, GLsizei height,
const struct gl_pixelstore_attrib *unpack,
const GLubyte *bitmap )
{
GLubyte *buf;
if (!_mesa_validate_pbo_access(2, unpack, width, height, 1,
GL_COLOR_INDEX, GL_BITMAP,
INT_MAX, (const GLvoid *) bitmap)) {
_mesa_error(ctx, GL_INVALID_OPERATION,"glBitmap(invalid PBO access)");
return NULL;
}
buf = (GLubyte *) ctx->Driver.MapBufferRange(ctx, 0, unpack->BufferObj->Size,
GL_MAP_READ_BIT,
unpack->BufferObj);
if (!buf) {
_mesa_error(ctx, GL_INVALID_OPERATION, "glBitmap(PBO is mapped)");
return NULL;
}
return ADD_POINTERS(buf, bitmap);
}
static bool test_bit( const GLubyte *src, GLuint bit )
{
return (src[bit/8] & (1<<(bit % 8))) ? 1 : 0;
}
static void set_bit( GLubyte *dest, GLuint bit )
{
dest[bit/8] |= 1 << (bit % 8);
}
/* Extract a rectangle's worth of data from the bitmap. Called
* per chunk of HW-sized bitmap.
*/
static GLuint get_bitmap_rect(GLsizei width, GLsizei height,
const struct gl_pixelstore_attrib *unpack,
const GLubyte *bitmap,
GLuint x, GLuint y,
GLuint w, GLuint h,
GLubyte *dest,
GLuint row_align,
bool invert)
{
GLuint src_offset = (x + unpack->SkipPixels) & 0x7;
GLuint mask = unpack->LsbFirst ? 0 : 7;
GLuint bit = 0;
GLint row, col;
GLint first, last;
GLint incr;
GLuint count = 0;
DBG("%s %d,%d %dx%d bitmap %dx%d skip %d src_offset %d mask %d\n",
__FUNCTION__, x,y,w,h,width,height,unpack->SkipPixels, src_offset, mask);
if (invert) {
first = h-1;
last = 0;
incr = -1;
}
else {
first = 0;
last = h-1;
incr = 1;
}
/* Require that dest be pre-zero'd.
*/
for (row = first; row != (last+incr); row += incr) {
const GLubyte *rowsrc = _mesa_image_address2d(unpack, bitmap,
width, height,
GL_COLOR_INDEX, GL_BITMAP,
y + row, x);
for (col = 0; col < w; col++, bit++) {
if (test_bit(rowsrc, (col + src_offset) ^ mask)) {
set_bit(dest, bit ^ 7);
count++;
}
}
if (row_align)
bit = ALIGN(bit, row_align);
}
return count;
}
/**
* Returns the low Y value of the vertical range given, flipped according to
* whether the framebuffer is or not.
*/
static INLINE int
y_flip(struct gl_framebuffer *fb, int y, int height)
{
if (_mesa_is_user_fbo(fb))
return y;
else
return fb->Height - y - height;
}
/*
* Render a bitmap.
*/
static bool
do_blit_bitmap( struct gl_context *ctx,
GLint dstx, GLint dsty,
GLsizei width, GLsizei height,
const struct gl_pixelstore_attrib *unpack,
const GLubyte *bitmap )
{
struct intel_context *intel = intel_context(ctx);
struct gl_framebuffer *fb = ctx->DrawBuffer;
struct intel_renderbuffer *irb;
GLfloat tmpColor[4];
GLubyte ubcolor[4];
GLuint color;
GLsizei bitmap_width = width;
GLsizei bitmap_height = height;
GLint px, py;
GLuint stipple[32];
GLint orig_dstx = dstx;
GLint orig_dsty = dsty;
/* Update draw buffer bounds */
_mesa_update_state(ctx);
if (ctx->Depth.Test) {
/* The blit path produces incorrect results when depth testing is on.
* It seems the blit Z coord is always 1.0 (the far plane) so fragments
* will likely be obscured by other, closer geometry.
*/
return false;
}
intel_prepare_render(intel);
if (fb->_NumColorDrawBuffers != 1) {
perf_debug("accelerated glBitmap() only supports rendering to a "
"single color buffer\n");
return false;
}
irb = intel_renderbuffer(fb->_ColorDrawBuffers[0]);
if (_mesa_is_bufferobj(unpack->BufferObj)) {
bitmap = map_pbo(ctx, width, height, unpack, bitmap);
if (bitmap == NULL)
return true; /* even though this is an error, we're done */
}
COPY_4V(tmpColor, ctx->Current.RasterColor);
if (_mesa_need_secondary_color(ctx)) {
ADD_3V(tmpColor, tmpColor, ctx->Current.RasterSecondaryColor);
}
UNCLAMPED_FLOAT_TO_UBYTE(ubcolor[0], tmpColor[0]);
UNCLAMPED_FLOAT_TO_UBYTE(ubcolor[1], tmpColor[1]);
UNCLAMPED_FLOAT_TO_UBYTE(ubcolor[2], tmpColor[2]);
UNCLAMPED_FLOAT_TO_UBYTE(ubcolor[3], tmpColor[3]);
switch (irb->mt->format) {
case MESA_FORMAT_ARGB8888:
case MESA_FORMAT_XRGB8888:
color = PACK_COLOR_8888(ubcolor[3], ubcolor[0], ubcolor[1], ubcolor[2]);
break;
case MESA_FORMAT_RGB565:
color = PACK_COLOR_565(ubcolor[0], ubcolor[1], ubcolor[2]);
break;
default:
perf_debug("Unsupported format %s in accelerated glBitmap()\n",
_mesa_get_format_name(irb->mt->format));
return false;
}
if (!intel_check_blit_fragment_ops(ctx, tmpColor[3] == 1.0F))
return false;
/* Clip to buffer bounds and scissor. */
if (!_mesa_clip_to_region(fb->_Xmin, fb->_Ymin,
fb->_Xmax, fb->_Ymax,
&dstx, &dsty, &width, &height))
goto out;
dsty = y_flip(fb, dsty, height);
#define DY 32
#define DX 32
/* The blitter has no idea about fast color clears, so we need to resolve
* the miptree before we do anything.
*/
intel_miptree_resolve_color(intel, irb->mt);
/* Chop it all into chunks that can be digested by hardware: */
for (py = 0; py < height; py += DY) {
for (px = 0; px < width; px += DX) {
int h = MIN2(DY, height - py);
int w = MIN2(DX, width - px);
GLuint sz = ALIGN(ALIGN(w,8) * h, 64)/8;
GLenum logic_op = ctx->Color.ColorLogicOpEnabled ?
ctx->Color.LogicOp : GL_COPY;
assert(sz <= sizeof(stipple));
memset(stipple, 0, sz);
/* May need to adjust this when padding has been introduced in
* sz above:
*
* Have to translate destination coordinates back into source
* coordinates.
*/
int count = get_bitmap_rect(bitmap_width, bitmap_height, unpack,
bitmap,
-orig_dstx + (dstx + px),
-orig_dsty + y_flip(fb, dsty + py, h),
w, h,
(GLubyte *)stipple,
8,
_mesa_is_winsys_fbo(fb));
if (count == 0)
continue;
if (!intelEmitImmediateColorExpandBlit(intel,
irb->mt->cpp,
(GLubyte *)stipple,
sz,
color,
irb->mt->region->pitch,
irb->mt->region->bo,
0,
irb->mt->region->tiling,
dstx + px,
dsty + py,
w, h,
logic_op)) {
return false;
}
if (ctx->Query.CurrentOcclusionObject)
ctx->Query.CurrentOcclusionObject->Result += count;
}
}
out:
if (unlikely(INTEL_DEBUG & DEBUG_SYNC))
intel_batchbuffer_flush(intel);
if (_mesa_is_bufferobj(unpack->BufferObj)) {
/* done with PBO so unmap it now */
ctx->Driver.UnmapBuffer(ctx, unpack->BufferObj);
}
intel_check_front_buffer_rendering(intel);
return true;
}
/* There are a large number of possible ways to implement bitmap on
* this hardware, most of them have some sort of drawback. Here are a
* few that spring to mind:
*
* Blit:
* - XY_MONO_SRC_BLT_CMD
* - use XY_SETUP_CLIP_BLT for cliprect clipping.
* - XY_TEXT_BLT
* - XY_TEXT_IMMEDIATE_BLT
* - blit per cliprect, subject to maximum immediate data size.
* - XY_COLOR_BLT
* - per pixel or run of pixels
* - XY_PIXEL_BLT
* - good for sparse bitmaps
*
* 3D engine:
* - Point per pixel
* - Translate bitmap to an alpha texture and render as a quad
* - Chop bitmap up into 32x32 squares and render w/polygon stipple.
*/
void
intelBitmap(struct gl_context * ctx,
GLint x, GLint y,
GLsizei width, GLsizei height,
const struct gl_pixelstore_attrib *unpack,
const GLubyte * pixels)
{
if (!_mesa_check_conditional_render(ctx))
return;
if (do_blit_bitmap(ctx, x, y, width, height,
unpack, pixels))
return;
_mesa_meta_Bitmap(ctx, x, y, width, height, unpack, pixels);
}

View file

@ -1 +0,0 @@
../intel/intel_pixel_copy.c

View file

@ -0,0 +1,210 @@
/**************************************************************************
*
* Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sub license, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial portions
* of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
**************************************************************************/
#include "main/glheader.h"
#include "main/image.h"
#include "main/state.h"
#include "main/mtypes.h"
#include "main/condrender.h"
#include "main/fbobject.h"
#include "drivers/common/meta.h"
#include "intel_context.h"
#include "intel_buffers.h"
#include "intel_mipmap_tree.h"
#include "intel_regions.h"
#include "intel_pixel.h"
#include "intel_fbo.h"
#include "intel_blit.h"
#define FILE_DEBUG_FLAG DEBUG_PIXEL
/**
* CopyPixels with the blitter. Don't support zooming, pixel transfer, etc.
*/
static bool
do_blit_copypixels(struct gl_context * ctx,
GLint srcx, GLint srcy,
GLsizei width, GLsizei height,
GLint dstx, GLint dsty, GLenum type)
{
struct intel_context *intel = intel_context(ctx);
struct gl_framebuffer *fb = ctx->DrawBuffer;
struct gl_framebuffer *read_fb = ctx->ReadBuffer;
GLint orig_dstx;
GLint orig_dsty;
GLint orig_srcx;
GLint orig_srcy;
struct intel_renderbuffer *draw_irb = NULL;
struct intel_renderbuffer *read_irb = NULL;
/* Update draw buffer bounds */
_mesa_update_state(ctx);
switch (type) {
case GL_COLOR:
if (fb->_NumColorDrawBuffers != 1) {
perf_debug("glCopyPixels() fallback: MRT\n");
return false;
}
draw_irb = intel_renderbuffer(fb->_ColorDrawBuffers[0]);
read_irb = intel_renderbuffer(read_fb->_ColorReadBuffer);
break;
case GL_DEPTH_STENCIL_EXT:
draw_irb = intel_renderbuffer(fb->Attachment[BUFFER_DEPTH].Renderbuffer);
read_irb =
intel_renderbuffer(read_fb->Attachment[BUFFER_DEPTH].Renderbuffer);
break;
case GL_DEPTH:
perf_debug("glCopyPixels() fallback: GL_DEPTH\n");
return false;
case GL_STENCIL:
perf_debug("glCopyPixels() fallback: GL_STENCIL\n");
return false;
default:
perf_debug("glCopyPixels(): Unknown type\n");
return false;
}
if (!draw_irb) {
perf_debug("glCopyPixels() fallback: missing draw buffer\n");
return false;
}
if (!read_irb) {
perf_debug("glCopyPixels() fallback: missing read buffer\n");
return false;
}
if (ctx->_ImageTransferState) {
perf_debug("glCopyPixels(): Unsupported image transfer state\n");
return false;
}
if (ctx->Depth.Test) {
perf_debug("glCopyPixels(): Unsupported depth test state\n");
return false;
}
if (ctx->Stencil._Enabled) {
perf_debug("glCopyPixels(): Unsupported stencil test state\n");
return false;
}
if (ctx->Fog.Enabled ||
ctx->Texture._EnabledUnits ||
ctx->FragmentProgram._Enabled) {
perf_debug("glCopyPixels(): Unsupported fragment shader state\n");
return false;
}
if (ctx->Color.AlphaEnabled ||
ctx->Color.BlendEnabled) {
perf_debug("glCopyPixels(): Unsupported blend state\n");
return false;
}
if (!ctx->Color.ColorMask[0][0] ||
!ctx->Color.ColorMask[0][1] ||
!ctx->Color.ColorMask[0][2] ||
!ctx->Color.ColorMask[0][3]) {
perf_debug("glCopyPixels(): Unsupported color mask state\n");
return false;
}
if (ctx->Pixel.ZoomX != 1.0F || ctx->Pixel.ZoomY != 1.0F) {
perf_debug("glCopyPixles(): Unsupported pixel zoom\n");
return false;
}
intel_prepare_render(intel);
intel_flush(&intel->ctx);
/* Clip to destination buffer. */
orig_dstx = dstx;
orig_dsty = dsty;
if (!_mesa_clip_to_region(fb->_Xmin, fb->_Ymin,
fb->_Xmax, fb->_Ymax,
&dstx, &dsty, &width, &height))
goto out;
/* Adjust src coords for our post-clipped destination origin */
srcx += dstx - orig_dstx;
srcy += dsty - orig_dsty;
/* Clip to source buffer. */
orig_srcx = srcx;
orig_srcy = srcy;
if (!_mesa_clip_to_region(0, 0,
read_fb->Width, read_fb->Height,
&srcx, &srcy, &width, &height))
goto out;
/* Adjust dst coords for our post-clipped source origin */
dstx += srcx - orig_srcx;
dsty += srcy - orig_srcy;
if (!intel_miptree_blit(intel,
read_irb->mt, read_irb->mt_level, read_irb->mt_layer,
srcx, srcy, _mesa_is_winsys_fbo(read_fb),
draw_irb->mt, draw_irb->mt_level, draw_irb->mt_layer,
dstx, dsty, _mesa_is_winsys_fbo(fb),
width, height,
(ctx->Color.ColorLogicOpEnabled ?
ctx->Color.LogicOp : GL_COPY))) {
DBG("%s: blit failure\n", __FUNCTION__);
return false;
}
if (ctx->Query.CurrentOcclusionObject)
ctx->Query.CurrentOcclusionObject->Result += width * height;
out:
intel_check_front_buffer_rendering(intel);
DBG("%s: success\n", __FUNCTION__);
return true;
}
void
intelCopyPixels(struct gl_context * ctx,
GLint srcx, GLint srcy,
GLsizei width, GLsizei height,
GLint destx, GLint desty, GLenum type)
{
DBG("%s\n", __FUNCTION__);
if (!_mesa_check_conditional_render(ctx))
return;
if (do_blit_copypixels(ctx, srcx, srcy, width, height, destx, desty, type))
return;
/* this will use swrast if needed */
_mesa_meta_CopyPixels(ctx, srcx, srcy, width, height, destx, desty, type);
}

View file

@ -1 +0,0 @@
../intel/intel_pixel_draw.c

View file

@ -0,0 +1,58 @@
/**************************************************************************
*
* Copyright 2006 Tungsten Graphics, Inc., Cedar Park, Texas.
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sub license, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial portionsalloc
* of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
**************************************************************************/
#include "main/glheader.h"
#include "main/enums.h"
#include "main/image.h"
#include "main/mtypes.h"
#include "main/teximage.h"
#include "main/texobj.h"
#include "main/texstate.h"
#include "swrast/swrast.h"
#include "drivers/common/meta.h"
#include "intel_context.h"
#include "intel_pixel.h"
void
intelDrawPixels(struct gl_context * ctx,
GLint x, GLint y,
GLsizei width, GLsizei height,
GLenum format,
GLenum type,
const struct gl_pixelstore_attrib *unpack,
const GLvoid * pixels)
{
if (format == GL_STENCIL_INDEX) {
_swrast_DrawPixels(ctx, x, y, width, height, format, type,
unpack, pixels);
return;
}
_mesa_meta_DrawPixels(ctx, x, y, width, height, format, type,
unpack, pixels);
}

View file

@ -1 +0,0 @@
../intel/intel_pixel_read.c

View file

@ -0,0 +1,202 @@
/**************************************************************************
*
* Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sub license, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial portions
* of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
**************************************************************************/
#include "main/glheader.h"
#include "main/enums.h"
#include "main/mtypes.h"
#include "main/macros.h"
#include "main/fbobject.h"
#include "main/image.h"
#include "main/bufferobj.h"
#include "main/readpix.h"
#include "main/state.h"
#include "intel_screen.h"
#include "intel_context.h"
#include "intel_blit.h"
#include "intel_buffers.h"
#include "intel_fbo.h"
#include "intel_mipmap_tree.h"
#include "intel_regions.h"
#include "intel_pixel.h"
#include "intel_buffer_objects.h"
#define FILE_DEBUG_FLAG DEBUG_PIXEL
/* For many applications, the new ability to pull the source buffers
* back out of the GTT and then do the packing/conversion operations
* in software will be as much of an improvement as trying to get the
* blitter and/or texture engine to do the work.
*
* This step is gated on private backbuffers.
*
* Obviously the frontbuffer can't be pulled back, so that is either
* an argument for blit/texture readpixels, or for blitting to a
* temporary and then pulling that back.
*
* When the destination is a pbo, however, it's not clear if it is
* ever going to be pulled to main memory (though the access param
* will be a good hint). So it sounds like we do want to be able to
* choose between blit/texture implementation on the gpu and pullback
* and cpu-based copying.
*
* Unless you can magically turn client memory into a PBO for the
* duration of this call, there will be a cpu-based copying step in
* any case.
*/
static bool
do_blit_readpixels(struct gl_context * ctx,
GLint x, GLint y, GLsizei width, GLsizei height,
GLenum format, GLenum type,
const struct gl_pixelstore_attrib *pack, GLvoid * pixels)
{
struct intel_context *intel = intel_context(ctx);
struct intel_buffer_object *dst = intel_buffer_object(pack->BufferObj);
GLuint dst_offset;
drm_intel_bo *dst_buffer;
bool all;
GLint dst_x, dst_y;
GLuint dirty;
DBG("%s\n", __FUNCTION__);
assert(_mesa_is_bufferobj(pack->BufferObj));
struct gl_renderbuffer *rb = ctx->ReadBuffer->_ColorReadBuffer;
struct intel_renderbuffer *irb = intel_renderbuffer(rb);
if (ctx->_ImageTransferState ||
!_mesa_format_matches_format_and_type(irb->mt->format, format, type,
false)) {
DBG("%s - bad format for blit\n", __FUNCTION__);
return false;
}
if (pack->SwapBytes || pack->LsbFirst) {
DBG("%s: bad packing params\n", __FUNCTION__);
return false;
}
int dst_stride = _mesa_image_row_stride(pack, width, format, type);
bool dst_flip = false;
/* Mesa flips the dst_stride for pack->Invert, but we want our mt to have a
* normal dst_stride.
*/
if (pack->Invert) {
dst_stride = -dst_stride;
dst_flip = true;
}
dst_offset = (GLintptr)pixels;
dst_offset += _mesa_image_offset(2, pack, width, height,
format, type, 0, 0, 0);
if (!_mesa_clip_copytexsubimage(ctx,
&dst_x, &dst_y,
&x, &y,
&width, &height)) {
return true;
}
dirty = intel->front_buffer_dirty;
intel_prepare_render(intel);
intel->front_buffer_dirty = dirty;
all = (width * height * irb->mt->cpp == dst->Base.Size &&
x == 0 && dst_offset == 0);
dst_buffer = intel_bufferobj_buffer(intel, dst,
all ? INTEL_WRITE_FULL :
INTEL_WRITE_PART);
struct intel_mipmap_tree *pbo_mt =
intel_miptree_create_for_bo(intel,
dst_buffer,
irb->mt->format,
dst_offset,
width, height,
dst_stride, I915_TILING_NONE);
if (!intel_miptree_blit(intel,
irb->mt, irb->mt_level, irb->mt_layer,
x, y, _mesa_is_winsys_fbo(ctx->ReadBuffer),
pbo_mt, 0, 0,
0, 0, dst_flip,
width, height, GL_COPY)) {
return false;
}
intel_miptree_release(&pbo_mt);
DBG("%s - DONE\n", __FUNCTION__);
return true;
}
void
intelReadPixels(struct gl_context * ctx,
GLint x, GLint y, GLsizei width, GLsizei height,
GLenum format, GLenum type,
const struct gl_pixelstore_attrib *pack, GLvoid * pixels)
{
struct intel_context *intel = intel_context(ctx);
bool dirty;
intel_flush_rendering_to_batch(ctx);
DBG("%s\n", __FUNCTION__);
if (_mesa_is_bufferobj(pack->BufferObj)) {
/* Using PBOs, so try the BLT based path. */
if (do_blit_readpixels(ctx, x, y, width, height, format, type, pack,
pixels)) {
return;
}
perf_debug("%s: fallback to CPU mapping in PBO case\n", __FUNCTION__);
}
/* glReadPixels() wont dirty the front buffer, so reset the dirty
* flag after calling intel_prepare_render(). */
dirty = intel->front_buffer_dirty;
intel_prepare_render(intel);
intel->front_buffer_dirty = dirty;
/* Update Mesa state before calling _mesa_readpixels().
* XXX this may not be needed since ReadPixels no longer uses the
* span code.
*/
if (ctx->NewState)
_mesa_update_state(ctx);
_mesa_readpixels(ctx, x, y, width, height, format, type, pack, pixels);
/* There's an intel_prepare_render() call in intelSpanRenderStart(). */
intel->front_buffer_dirty = dirty;
}

View file

@ -0,0 +1,300 @@
/**************************************************************************
*
* Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sub license, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial portions
* of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
**************************************************************************/
#define CMD_MI (0x0 << 29)
#define CMD_2D (0x2 << 29)
#define CMD_3D (0x3 << 29)
#define MI_NOOP (CMD_MI | 0)
#define MI_BATCH_BUFFER_END (CMD_MI | 0xA << 23)
#define MI_FLUSH (CMD_MI | (4 << 23))
#define FLUSH_MAP_CACHE (1 << 0)
#define INHIBIT_FLUSH_RENDER_CACHE (1 << 2)
#define MI_LOAD_REGISTER_IMM (CMD_MI | (0x22 << 23))
#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)
#define MI_WAIT_FOR_PLANE_A_FLIP (1<<2)
#define MI_STORE_REGISTER_MEM (CMD_MI | (0x24 << 23))
# define MI_STORE_REGISTER_MEM_USE_GGTT (1 << 22)
/* p189 */
#define _3DSTATE_LOAD_STATE_IMMEDIATE_1 (CMD_3D | (0x1d<<24) | (0x04<<16))
#define I1_LOAD_S(n) (1<<(4+n))
#define _3DSTATE_DRAWRECT_INFO (CMD_3D | (0x1d<<24) | (0x80<<16) | 0x3)
/** @{
*
* PIPE_CONTROL operation, a combination MI_FLUSH and register write with
* additional flushing control.
*/
#define _3DSTATE_PIPE_CONTROL (CMD_3D | (3 << 27) | (2 << 24))
#define PIPE_CONTROL_CS_STALL (1 << 20)
#define PIPE_CONTROL_GLOBAL_SNAPSHOT_COUNT_RESET (1 << 19)
#define PIPE_CONTROL_TLB_INVALIDATE (1 << 18)
#define PIPE_CONTROL_SYNC_GFDT (1 << 17)
#define PIPE_CONTROL_MEDIA_STATE_CLEAR (1 << 16)
#define PIPE_CONTROL_NO_WRITE (0 << 14)
#define PIPE_CONTROL_WRITE_IMMEDIATE (1 << 14)
#define PIPE_CONTROL_WRITE_DEPTH_COUNT (2 << 14)
#define PIPE_CONTROL_WRITE_TIMESTAMP (3 << 14)
#define PIPE_CONTROL_DEPTH_STALL (1 << 13)
#define PIPE_CONTROL_WRITE_FLUSH (1 << 12)
#define PIPE_CONTROL_INSTRUCTION_FLUSH (1 << 11)
#define PIPE_CONTROL_TC_FLUSH (1 << 10) /* GM45+ only */
#define PIPE_CONTROL_ISP_DIS (1 << 9)
#define PIPE_CONTROL_INTERRUPT_ENABLE (1 << 8)
/* GT */
#define PIPE_CONTROL_VF_CACHE_INVALIDATE (1 << 4)
#define PIPE_CONTROL_CONST_CACHE_INVALIDATE (1 << 3)
#define PIPE_CONTROL_STATE_CACHE_INVALIDATE (1 << 2)
#define PIPE_CONTROL_STALL_AT_SCOREBOARD (1 << 1)
#define PIPE_CONTROL_DEPTH_CACHE_FLUSH (1 << 0)
#define PIPE_CONTROL_PPGTT_WRITE (0 << 2)
#define PIPE_CONTROL_GLOBAL_GTT_WRITE (1 << 2)
/** @} */
/** @{
* 915 definitions
*
* 915 documents say that bits 31:28 and 1 are "undefined, must be zero."
*/
#define S0_VB_OFFSET_MASK 0x0ffffffc
#define S0_AUTO_CACHE_INV_DISABLE (1<<0)
/** @} */
/** @{
* 830 definitions
*/
#define S0_VB_OFFSET_MASK_830 0xffffff80
#define S0_VB_PITCH_SHIFT_830 1
#define S0_VB_ENABLE_830 (1<<0)
/** @} */
#define S1_VERTEX_WIDTH_SHIFT 24
#define S1_VERTEX_WIDTH_MASK (0x3f<<24)
#define S1_VERTEX_PITCH_SHIFT 16
#define S1_VERTEX_PITCH_MASK (0x3f<<16)
#define TEXCOORDFMT_2D 0x0
#define TEXCOORDFMT_3D 0x1
#define TEXCOORDFMT_4D 0x2
#define TEXCOORDFMT_1D 0x3
#define TEXCOORDFMT_2D_16 0x4
#define TEXCOORDFMT_4D_16 0x5
#define TEXCOORDFMT_NOT_PRESENT 0xf
#define S2_TEXCOORD_FMT0_MASK 0xf
#define S2_TEXCOORD_FMT1_SHIFT 4
#define S2_TEXCOORD_FMT(unit, type) ((type)<<(unit*4))
#define S2_TEXCOORD_NONE (~0)
#define S2_TEX_COUNT_SHIFT_830 12
#define S2_VERTEX_1_WIDTH_SHIFT_830 0
#define S2_VERTEX_0_WIDTH_SHIFT_830 6
/* S3 not interesting */
#define S4_POINT_WIDTH_SHIFT 23
#define S4_POINT_WIDTH_MASK (0x1ff<<23)
#define S4_LINE_WIDTH_SHIFT 19
#define S4_LINE_WIDTH_ONE (0x2<<19)
#define S4_LINE_WIDTH_MASK (0xf<<19)
#define S4_FLATSHADE_ALPHA (1<<18)
#define S4_FLATSHADE_FOG (1<<17)
#define S4_FLATSHADE_SPECULAR (1<<16)
#define S4_FLATSHADE_COLOR (1<<15)
#define S4_CULLMODE_BOTH (0<<13)
#define S4_CULLMODE_NONE (1<<13)
#define S4_CULLMODE_CW (2<<13)
#define S4_CULLMODE_CCW (3<<13)
#define S4_CULLMODE_MASK (3<<13)
#define S4_VFMT_POINT_WIDTH (1<<12)
#define S4_VFMT_SPEC_FOG (1<<11)
#define S4_VFMT_COLOR (1<<10)
#define S4_VFMT_DEPTH_OFFSET (1<<9)
#define S4_VFMT_XYZ (1<<6)
#define S4_VFMT_XYZW (2<<6)
#define S4_VFMT_XY (3<<6)
#define S4_VFMT_XYW (4<<6)
#define S4_VFMT_XYZW_MASK (7<<6)
#define S4_FORCE_DEFAULT_DIFFUSE (1<<5)
#define S4_FORCE_DEFAULT_SPECULAR (1<<4)
#define S4_LOCAL_DEPTH_OFFSET_ENABLE (1<<3)
#define S4_VFMT_FOG_PARAM (1<<2)
#define S4_SPRITE_POINT_ENABLE (1<<1)
#define S4_LINE_ANTIALIAS_ENABLE (1<<0)
#define S4_VFMT_MASK (S4_VFMT_POINT_WIDTH | \
S4_VFMT_SPEC_FOG | \
S4_VFMT_COLOR | \
S4_VFMT_DEPTH_OFFSET | \
S4_VFMT_XYZW_MASK | \
S4_VFMT_FOG_PARAM)
#define S5_WRITEDISABLE_ALPHA (1<<31)
#define S5_WRITEDISABLE_RED (1<<30)
#define S5_WRITEDISABLE_GREEN (1<<29)
#define S5_WRITEDISABLE_BLUE (1<<28)
#define S5_WRITEDISABLE_MASK (0xf<<28)
#define S5_FORCE_DEFAULT_POINT_SIZE (1<<27)
#define S5_LAST_PIXEL_ENABLE (1<<26)
#define S5_GLOBAL_DEPTH_OFFSET_ENABLE (1<<25)
#define S5_FOG_ENABLE (1<<24)
#define S5_STENCIL_REF_SHIFT 16
#define S5_STENCIL_REF_MASK (0xff<<16)
#define S5_STENCIL_TEST_FUNC_SHIFT 13
#define S5_STENCIL_TEST_FUNC_MASK (0x7<<13)
#define S5_STENCIL_FAIL_SHIFT 10
#define S5_STENCIL_FAIL_MASK (0x7<<10)
#define S5_STENCIL_PASS_Z_FAIL_SHIFT 7
#define S5_STENCIL_PASS_Z_FAIL_MASK (0x7<<7)
#define S5_STENCIL_PASS_Z_PASS_SHIFT 4
#define S5_STENCIL_PASS_Z_PASS_MASK (0x7<<4)
#define S5_STENCIL_WRITE_ENABLE (1<<3)
#define S5_STENCIL_TEST_ENABLE (1<<2)
#define S5_COLOR_DITHER_ENABLE (1<<1)
#define S5_LOGICOP_ENABLE (1<<0)
#define S6_ALPHA_TEST_ENABLE (1<<31)
#define S6_ALPHA_TEST_FUNC_SHIFT 28
#define S6_ALPHA_TEST_FUNC_MASK (0x7<<28)
#define S6_ALPHA_REF_SHIFT 20
#define S6_ALPHA_REF_MASK (0xff<<20)
#define S6_DEPTH_TEST_ENABLE (1<<19)
#define S6_DEPTH_TEST_FUNC_SHIFT 16
#define S6_DEPTH_TEST_FUNC_MASK (0x7<<16)
#define S6_CBUF_BLEND_ENABLE (1<<15)
#define S6_CBUF_BLEND_FUNC_SHIFT 12
#define S6_CBUF_BLEND_FUNC_MASK (0x7<<12)
#define S6_CBUF_SRC_BLEND_FACT_SHIFT 8
#define S6_CBUF_SRC_BLEND_FACT_MASK (0xf<<8)
#define S6_CBUF_DST_BLEND_FACT_SHIFT 4
#define S6_CBUF_DST_BLEND_FACT_MASK (0xf<<4)
#define S6_DEPTH_WRITE_ENABLE (1<<3)
#define S6_COLOR_WRITE_ENABLE (1<<2)
#define S6_TRISTRIP_PV_SHIFT 0
#define S6_TRISTRIP_PV_MASK (0x3<<0)
#define S7_DEPTH_OFFSET_CONST_MASK ~0
/* p143 */
#define _3DSTATE_BUF_INFO_CMD (CMD_3D | (0x1d<<24) | (0x8e<<16) | 1)
/* Dword 1 */
#define BUF_3D_ID_COLOR_BACK (0x3<<24)
#define BUF_3D_ID_DEPTH (0x7<<24)
#define BUF_3D_USE_FENCE (1<<23)
#define BUF_3D_TILED_SURFACE (1<<22)
#define BUF_3D_TILE_WALK_X 0
#define BUF_3D_TILE_WALK_Y (1<<21)
#define BUF_3D_PITCH(x) (((x)/4)<<2)
/* Dword 2 */
#define BUF_3D_ADDR(x) ((x) & ~0x3)
/* Primitive dispatch on 830-945 */
#define _3DPRIMITIVE (CMD_3D | (0x1f << 24))
#define PRIM_INDIRECT (1<<23)
#define PRIM_INLINE (0<<23)
#define PRIM_INDIRECT_SEQUENTIAL (0<<17)
#define PRIM_INDIRECT_ELTS (1<<17)
#define PRIM3D_TRILIST (0x0<<18)
#define PRIM3D_TRISTRIP (0x1<<18)
#define PRIM3D_TRISTRIP_RVRSE (0x2<<18)
#define PRIM3D_TRIFAN (0x3<<18)
#define PRIM3D_POLY (0x4<<18)
#define PRIM3D_LINELIST (0x5<<18)
#define PRIM3D_LINESTRIP (0x6<<18)
#define PRIM3D_RECTLIST (0x7<<18)
#define PRIM3D_POINTLIST (0x8<<18)
#define PRIM3D_DIB (0x9<<18)
#define PRIM3D_MASK (0x1f<<18)
#define XY_SETUP_BLT_CMD (CMD_2D | (0x01 << 22))
#define XY_COLOR_BLT_CMD (CMD_2D | (0x50 << 22))
#define XY_SRC_COPY_BLT_CMD (CMD_2D | (0x53 << 22))
#define XY_TEXT_IMMEDIATE_BLIT_CMD (CMD_2D | (0x31 << 22))
# define XY_TEXT_BYTE_PACKED (1 << 16)
/* BR00 */
#define XY_BLT_WRITE_ALPHA (1 << 21)
#define XY_BLT_WRITE_RGB (1 << 20)
#define XY_SRC_TILED (1 << 15)
#define XY_DST_TILED (1 << 11)
/* BR13 */
#define BR13_8 (0x0 << 24)
#define BR13_565 (0x1 << 24)
#define BR13_8888 (0x3 << 24)
#define FENCE_LINEAR 0
#define FENCE_XMAJOR 1
#define FENCE_YMAJOR 2
/* Pipeline Statistics Counter Registers */
#define IA_VERTICES_COUNT 0x2310
#define IA_PRIMITIVES_COUNT 0x2318
#define VS_INVOCATION_COUNT 0x2320
#define HS_INVOCATION_COUNT 0x2300
#define DS_INVOCATION_COUNT 0x2308
#define GS_INVOCATION_COUNT 0x2328
#define GS_PRIMITIVES_COUNT 0x2330
#define CL_INVOCATION_COUNT 0x2338
#define CL_PRIMITIVES_COUNT 0x2340
#define PS_INVOCATION_COUNT 0x2348
#define PS_DEPTH_COUNT 0x2350
#define SO_NUM_PRIM_STORAGE_NEEDED 0x2280
#define SO_PRIM_STORAGE_NEEDED0_IVB 0x5240
#define SO_PRIM_STORAGE_NEEDED1_IVB 0x5248
#define SO_PRIM_STORAGE_NEEDED2_IVB 0x5250
#define SO_PRIM_STORAGE_NEEDED3_IVB 0x5258
#define SO_NUM_PRIMS_WRITTEN 0x2288
#define SO_NUM_PRIMS_WRITTEN0_IVB 0x5200
#define SO_NUM_PRIMS_WRITTEN1_IVB 0x5208
#define SO_NUM_PRIMS_WRITTEN2_IVB 0x5210
#define SO_NUM_PRIMS_WRITTEN3_IVB 0x5218
#define GEN7_SO_WRITE_OFFSET(n) (0x5280 + (n) * 4)
#define TIMESTAMP 0x2358
#define BCS_SWCTRL 0x22200
# define BCS_SWCTRL_SRC_Y (1 << 0)
# define BCS_SWCTRL_DST_Y (1 << 1)

View file

@ -1 +0,0 @@
../intel/intel_regions.c

View file

@ -0,0 +1,353 @@
/**************************************************************************
*
* Copyright 2006 Tungsten Graphics, Inc., Cedar Park, Texas.
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sub license, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial portions
* of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
**************************************************************************/
/* Provide additional functionality on top of bufmgr buffers:
* - 2d semantics and blit operations
* - refcounting of buffers for multiple images in a buffer.
* - refcounting of buffer mappings.
* - some logic for moving the buffers to the best memory pools for
* given operations.
*
* Most of this is to make it easier to implement the fixed-layout
* mipmap tree required by intel hardware in the face of GL's
* programming interface where each image can be specifed in random
* order and it isn't clear what layout the tree should have until the
* last moment.
*/
#include <sys/ioctl.h>
#include <errno.h>
#include "main/hash.h"
#include "intel_context.h"
#include "intel_regions.h"
#include "intel_blit.h"
#include "intel_buffer_objects.h"
#include "intel_bufmgr.h"
#include "intel_batchbuffer.h"
#define FILE_DEBUG_FLAG DEBUG_REGION
/* This should be set to the maximum backtrace size desired.
* Set it to 0 to disable backtrace debugging.
*/
#define DEBUG_BACKTRACE_SIZE 0
#if DEBUG_BACKTRACE_SIZE == 0
/* Use the standard debug output */
#define _DBG(...) DBG(__VA_ARGS__)
#else
/* Use backtracing debug output */
#define _DBG(...) {debug_backtrace(); DBG(__VA_ARGS__);}
/* Backtracing debug support */
#include <execinfo.h>
static void
debug_backtrace(void)
{
void *trace[DEBUG_BACKTRACE_SIZE];
char **strings = NULL;
int traceSize;
register int i;
traceSize = backtrace(trace, DEBUG_BACKTRACE_SIZE);
strings = backtrace_symbols(trace, traceSize);
if (strings == NULL) {
DBG("no backtrace:");
return;
}
/* Spit out all the strings with a colon separator. Ignore
* the first, since we don't really care about the call
* to debug_backtrace() itself. Skip until the final "/" in
* the trace to avoid really long lines.
*/
for (i = 1; i < traceSize; i++) {
char *p = strings[i], *slash = strings[i];
while (*p) {
if (*p++ == '/') {
slash = p;
}
}
DBG("%s:", slash);
}
/* Free up the memory, and we're done */
free(strings);
}
#endif
static struct intel_region *
intel_region_alloc_internal(struct intel_screen *screen,
GLuint cpp,
GLuint width, GLuint height, GLuint pitch,
uint32_t tiling, drm_intel_bo *buffer)
{
struct intel_region *region;
region = calloc(sizeof(*region), 1);
if (region == NULL)
return region;
region->cpp = cpp;
region->width = width;
region->height = height;
region->pitch = pitch;
region->refcount = 1;
region->bo = buffer;
region->tiling = tiling;
_DBG("%s <-- %p\n", __FUNCTION__, region);
return region;
}
struct intel_region *
intel_region_alloc(struct intel_screen *screen,
uint32_t tiling,
GLuint cpp, GLuint width, GLuint height,
bool expect_accelerated_upload)
{
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;
buffer = drm_intel_bo_alloc_tiled(screen->bufmgr, "region",
width, height, cpp,
&tiling, &aligned_pitch, flags);
if (buffer == NULL)
return NULL;
region = intel_region_alloc_internal(screen, cpp, width, height,
aligned_pitch, tiling, buffer);
if (region == NULL) {
drm_intel_bo_unreference(buffer);
return NULL;
}
return region;
}
bool
intel_region_flink(struct intel_region *region, uint32_t *name)
{
if (region->name == 0) {
if (drm_intel_bo_flink(region->bo, &region->name))
return false;
}
*name = region->name;
return true;
}
struct intel_region *
intel_region_alloc_for_handle(struct intel_screen *screen,
GLuint cpp,
GLuint width, GLuint height, GLuint pitch,
GLuint handle, const char *name)
{
struct intel_region *region;
drm_intel_bo *buffer;
int ret;
uint32_t bit_6_swizzle, tiling;
buffer = intel_bo_gem_create_from_name(screen->bufmgr, name, handle);
if (buffer == NULL)
return NULL;
ret = drm_intel_bo_get_tiling(buffer, &tiling, &bit_6_swizzle);
if (ret != 0) {
fprintf(stderr, "Couldn't get tiling of buffer %d (%s): %s\n",
handle, name, strerror(-ret));
drm_intel_bo_unreference(buffer);
return NULL;
}
region = intel_region_alloc_internal(screen, cpp,
width, height, pitch, tiling, buffer);
if (region == NULL) {
drm_intel_bo_unreference(buffer);
return NULL;
}
region->name = handle;
return region;
}
struct intel_region *
intel_region_alloc_for_fd(struct intel_screen *screen,
GLuint cpp,
GLuint width, GLuint height, GLuint pitch,
int fd, const char *name)
{
struct intel_region *region;
drm_intel_bo *buffer;
int ret;
uint32_t bit_6_swizzle, tiling;
buffer = drm_intel_bo_gem_create_from_prime(screen->bufmgr,
fd, height * pitch);
if (buffer == NULL)
return NULL;
ret = drm_intel_bo_get_tiling(buffer, &tiling, &bit_6_swizzle);
if (ret != 0) {
fprintf(stderr, "Couldn't get tiling of buffer (%s): %s\n",
name, strerror(-ret));
drm_intel_bo_unreference(buffer);
return NULL;
}
region = intel_region_alloc_internal(screen, cpp,
width, height, pitch, tiling, buffer);
if (region == NULL) {
drm_intel_bo_unreference(buffer);
return NULL;
}
return region;
}
void
intel_region_reference(struct intel_region **dst, struct intel_region *src)
{
_DBG("%s: %p(%d) -> %p(%d)\n", __FUNCTION__,
*dst, *dst ? (*dst)->refcount : 0, src, src ? src->refcount : 0);
if (src != *dst) {
if (*dst)
intel_region_release(dst);
if (src)
src->refcount++;
*dst = src;
}
}
void
intel_region_release(struct intel_region **region_handle)
{
struct intel_region *region = *region_handle;
if (region == NULL) {
_DBG("%s NULL\n", __FUNCTION__);
return;
}
_DBG("%s %p %d\n", __FUNCTION__, region, region->refcount - 1);
ASSERT(region->refcount > 0);
region->refcount--;
if (region->refcount == 0) {
drm_intel_bo_unreference(region->bo);
free(region);
}
*region_handle = NULL;
}
/**
* This function computes masks that may be used to select the bits of the X
* and Y coordinates that indicate the offset within a tile. If the region is
* untiled, the masks are set to 0.
*/
void
intel_region_get_tile_masks(struct intel_region *region,
uint32_t *mask_x, uint32_t *mask_y,
bool map_stencil_as_y_tiled)
{
int cpp = region->cpp;
uint32_t tiling = region->tiling;
if (map_stencil_as_y_tiled)
tiling = I915_TILING_Y;
switch (tiling) {
default:
assert(false);
case I915_TILING_NONE:
*mask_x = *mask_y = 0;
break;
case I915_TILING_X:
*mask_x = 512 / cpp - 1;
*mask_y = 7;
break;
case I915_TILING_Y:
*mask_x = 128 / cpp - 1;
*mask_y = 31;
break;
}
}
/**
* Compute the offset (in bytes) from the start of the region to the given x
* and y coordinate. For tiled regions, caller must ensure that x and y are
* multiples of the tile size.
*/
uint32_t
intel_region_get_aligned_offset(struct intel_region *region, uint32_t x,
uint32_t y, bool map_stencil_as_y_tiled)
{
int cpp = region->cpp;
uint32_t pitch = region->pitch;
uint32_t tiling = region->tiling;
if (map_stencil_as_y_tiled) {
tiling = I915_TILING_Y;
/* When mapping a W-tiled stencil buffer as Y-tiled, each 64-high W-tile
* gets transformed into a 32-high Y-tile. Accordingly, the pitch of
* the resulting region is twice the pitch of the original region, since
* each row in the Y-tiled view corresponds to two rows in the actual
* W-tiled surface. So we need to correct the pitch before computing
* the offsets.
*/
pitch *= 2;
}
switch (tiling) {
default:
assert(false);
case I915_TILING_NONE:
return y * pitch + x * cpp;
case I915_TILING_X:
assert((x % (512 / cpp)) == 0);
assert((y % 8) == 0);
return y * pitch + x / (512 / cpp) * 4096;
case I915_TILING_Y:
assert((x % (128 / cpp)) == 0);
assert((y % 32) == 0);
return y * pitch + x / (128 / cpp) * 4096;
}
}

View file

@ -0,0 +1,161 @@
/**************************************************************************
*
* Copyright 2006 Tungsten Graphics, Inc., Cedar Park, Texas.
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sub license, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial portions
* of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
**************************************************************************/
#ifndef INTEL_REGIONS_H
#define INTEL_REGIONS_H
/** @file intel_regions.h
*
* Structure definitions and prototypes for intel_region handling,
* which is the basic structure for rectangular collections of pixels
* stored in a drm_intel_bo.
*/
#include <stdbool.h>
#include <xf86drm.h>
#include "main/mtypes.h"
#include "intel_bufmgr.h"
#ifdef __cplusplus
extern "C" {
#endif
struct intel_context;
struct intel_screen;
struct intel_buffer_object;
/**
* A layer on top of the bufmgr buffers that adds a few useful things:
*
* - Refcounting for local buffer references.
* - Refcounting for buffer maps
* - Buffer dimensions - pitch and height.
* - Blitter commands for copying 2D regions between buffers. (really???)
*/
struct intel_region
{
drm_intel_bo *bo; /**< buffer manager's buffer */
GLuint refcount; /**< Reference count for region */
GLuint cpp; /**< bytes per pixel */
GLuint width; /**< in pixels */
GLuint height; /**< in pixels */
GLuint pitch; /**< in bytes */
uint32_t tiling; /**< Which tiling mode the region is in */
uint32_t name; /**< Global name for the bo */
};
/* Allocate a refcounted region. Pointers to regions should only be
* copied by calling intel_reference_region().
*/
struct intel_region *intel_region_alloc(struct intel_screen *screen,
uint32_t tiling,
GLuint cpp, GLuint width,
GLuint height,
bool expect_accelerated_upload);
struct intel_region *
intel_region_alloc_for_handle(struct intel_screen *screen,
GLuint cpp,
GLuint width, GLuint height, GLuint pitch,
unsigned int handle, const char *name);
struct intel_region *
intel_region_alloc_for_fd(struct intel_screen *screen,
GLuint cpp,
GLuint width, GLuint height, GLuint pitch,
int fd, const char *name);
bool
intel_region_flink(struct intel_region *region, uint32_t *name);
void intel_region_reference(struct intel_region **dst,
struct intel_region *src);
void intel_region_release(struct intel_region **ib);
void intel_recreate_static_regions(struct intel_context *intel);
void
intel_region_get_tile_masks(struct intel_region *region,
uint32_t *mask_x, uint32_t *mask_y,
bool map_stencil_as_y_tiled);
uint32_t
intel_region_get_aligned_offset(struct intel_region *region, uint32_t x,
uint32_t y, bool map_stencil_as_y_tiled);
/**
* Used with images created with image_from_names
* to help support planar images.
*/
struct intel_image_format {
int fourcc;
int components;
int nplanes;
struct {
int buffer_index;
int width_shift;
int height_shift;
uint32_t dri_format;
int cpp;
} planes[3];
};
struct __DRIimageRec {
struct intel_region *region;
GLenum internal_format;
uint32_t dri_format;
GLuint format;
uint32_t offset;
/*
* Need to save these here between calls to
* image_from_names and calls to image_from_planar.
*/
uint32_t strides[3];
uint32_t offsets[3];
struct intel_image_format *planar_format;
/* particular miptree level */
GLuint width;
GLuint height;
GLuint tile_x;
GLuint tile_y;
bool has_depthstencil;
void *data;
};
#ifdef __cplusplus
}
#endif
#endif

View file

@ -1 +0,0 @@
../intel/intel_resolve_map.c

View file

@ -0,0 +1,111 @@
/*
* Copyright © 2011 Intel Corporation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
* IN THE SOFTWARE.
*/
#include "intel_resolve_map.h"
#include <assert.h>
#include <stdlib.h>
/**
* \brief Set that the miptree slice at (level, layer) needs a resolve.
*
* If a map element already exists with the given key, then the value is
* changed to the given value of \c need.
*/
void
intel_resolve_map_set(struct intel_resolve_map *head,
uint32_t level,
uint32_t layer,
enum gen6_hiz_op need)
{
struct intel_resolve_map **tail = &head->next;
struct intel_resolve_map *prev = head;
while (*tail) {
if ((*tail)->level == level && (*tail)->layer == layer) {
(*tail)->need = need;
return;
}
prev = *tail;
tail = &(*tail)->next;
}
*tail = malloc(sizeof(**tail));
(*tail)->prev = prev;
(*tail)->next = NULL;
(*tail)->level = level;
(*tail)->layer = layer;
(*tail)->need = need;
}
/**
* \brief Get an element from the map.
* \return null if element is not contained in map.
*/
struct intel_resolve_map*
intel_resolve_map_get(struct intel_resolve_map *head,
uint32_t level,
uint32_t layer)
{
struct intel_resolve_map *item = head->next;
while (item) {
if (item->level == level && item->layer == layer)
break;
else
item = item->next;
}
return item;
}
/**
* \brief Remove and free an element from the map.
*/
void
intel_resolve_map_remove(struct intel_resolve_map *elem)
{
if (elem->prev)
elem->prev->next = elem->next;
if (elem->next)
elem->next->prev = elem->prev;
free(elem);
}
/**
* \brief Remove and free all elements of the map.
*/
void
intel_resolve_map_clear(struct intel_resolve_map *head)
{
struct intel_resolve_map *next = head->next;
struct intel_resolve_map *trash;
while (next) {
trash = next;
next = next->next;
free(trash);
}
head->next = NULL;
}

View file

@ -0,0 +1,104 @@
/*
* Copyright © 2011 Intel Corporation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
* IN THE SOFTWARE.
*/
#pragma once
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
/**
* For an overview of the HiZ operations, see the following sections of the
* Sandy Bridge PRM, Volume 1, Part2:
* - 7.5.3.1 Depth Buffer Clear
* - 7.5.3.2 Depth Buffer Resolve
* - 7.5.3.3 Hierarchical Depth Buffer Resolve
*
* Of these, two get entered in the resolve map as needing to be done to the
* buffer: depth resolve and hiz resolve.
*/
enum gen6_hiz_op {
GEN6_HIZ_OP_DEPTH_CLEAR,
GEN6_HIZ_OP_DEPTH_RESOLVE,
GEN6_HIZ_OP_HIZ_RESOLVE,
GEN6_HIZ_OP_NONE,
};
/**
* \brief Map of miptree slices to needed resolves.
*
* The map is implemented as a linear doubly-linked list.
*
* In the intel_resolve_map*() functions, the \c head argument is not
* inspected for its data. It only serves as an anchor for the list.
*
* \par Design Discussion
*
* There are two possible ways to record which miptree slices need
* resolves. 1) Maintain a flag for every miptree slice in the texture,
* likely in intel_mipmap_level::slice, or 2) maintain a list of only
* those slices that need a resolve.
*
* Immediately before drawing, a full depth resolve performed on each
* enabled depth texture. If design 1 were chosen, then at each draw call
* it would be necessary to iterate over each miptree slice of each
* enabled depth texture in order to query if each slice needed a resolve.
* In the worst case, this would require 2^16 iterations: 16 texture
* units, 16 miplevels, and 256 depth layers (assuming maximums for OpenGL
* 2.1).
*
* By choosing design 2, the number of iterations is exactly the minimum
* necessary.
*/
struct intel_resolve_map {
uint32_t level;
uint32_t layer;
enum gen6_hiz_op need;
struct intel_resolve_map *next;
struct intel_resolve_map *prev;
};
void
intel_resolve_map_set(struct intel_resolve_map *head,
uint32_t level,
uint32_t layer,
enum gen6_hiz_op need);
struct intel_resolve_map*
intel_resolve_map_get(struct intel_resolve_map *head,
uint32_t level,
uint32_t layer);
void
intel_resolve_map_remove(struct intel_resolve_map *elem);
void
intel_resolve_map_clear(struct intel_resolve_map *head);
#ifdef __cplusplus
} /* extern "C" */
#endif

View file

@ -1 +0,0 @@
../intel/intel_screen.c

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,89 @@
/**************************************************************************
*
* Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sub license, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial portions
* of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
**************************************************************************/
#ifndef _INTEL_INIT_H_
#define _INTEL_INIT_H_
#include <stdbool.h>
#include <sys/time.h>
#include "dri_util.h"
#include "intel_bufmgr.h"
#include "i915_drm.h"
#include "xmlconfig.h"
struct intel_screen
{
int deviceID;
int gen;
int max_gl_core_version;
int max_gl_compat_version;
int max_gl_es1_version;
int max_gl_es2_version;
__DRIscreen *driScrnPriv;
bool no_hw;
/*
* The hardware hiz and separate stencil fields are needed in intel_screen,
* rather than solely in intel_context, because glXCreatePbuffer and
* glXCreatePixmap are not passed a GLXContext.
*/
bool hw_has_separate_stencil;
bool hw_must_use_separate_stencil;
bool hw_has_llc;
bool hw_has_swizzling;
bool no_vbo;
dri_bufmgr *bufmgr;
/**
* A unique ID for shader programs.
*/
unsigned program_id;
/**
* Configuration cache with default values for all contexts
*/
driOptionCache optionCache;
};
extern void intelDestroyContext(__DRIcontext * driContextPriv);
extern GLboolean intelUnbindContext(__DRIcontext * driContextPriv);
extern GLboolean
intelMakeCurrent(__DRIcontext * driContextPriv,
__DRIdrawable * driDrawPriv,
__DRIdrawable * driReadPriv);
double get_time(void);
void aub_dump_bmp(struct gl_context *ctx);
#endif

View file

@ -1 +0,0 @@
../intel/intel_state.c

View file

@ -0,0 +1,195 @@
/**************************************************************************
*
* Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sub license, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial portions
* of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
**************************************************************************/
#include "main/glheader.h"
#include "main/context.h"
#include "main/macros.h"
#include "main/enums.h"
#include "main/colormac.h"
#include "main/dd.h"
#include "intel_screen.h"
#include "intel_context.h"
int
intel_translate_shadow_compare_func(GLenum func)
{
switch (func) {
case GL_NEVER:
return COMPAREFUNC_ALWAYS;
case GL_LESS:
return COMPAREFUNC_LEQUAL;
case GL_LEQUAL:
return COMPAREFUNC_LESS;
case GL_GREATER:
return COMPAREFUNC_GEQUAL;
case GL_GEQUAL:
return COMPAREFUNC_GREATER;
case GL_NOTEQUAL:
return COMPAREFUNC_EQUAL;
case GL_EQUAL:
return COMPAREFUNC_NOTEQUAL;
case GL_ALWAYS:
return COMPAREFUNC_NEVER;
}
fprintf(stderr, "Unknown value in %s: %x\n", __FUNCTION__, func);
return COMPAREFUNC_NEVER;
}
int
intel_translate_compare_func(GLenum func)
{
switch (func) {
case GL_NEVER:
return COMPAREFUNC_NEVER;
case GL_LESS:
return COMPAREFUNC_LESS;
case GL_LEQUAL:
return COMPAREFUNC_LEQUAL;
case GL_GREATER:
return COMPAREFUNC_GREATER;
case GL_GEQUAL:
return COMPAREFUNC_GEQUAL;
case GL_NOTEQUAL:
return COMPAREFUNC_NOTEQUAL;
case GL_EQUAL:
return COMPAREFUNC_EQUAL;
case GL_ALWAYS:
return COMPAREFUNC_ALWAYS;
}
fprintf(stderr, "Unknown value in %s: %x\n", __FUNCTION__, func);
return COMPAREFUNC_ALWAYS;
}
int
intel_translate_stencil_op(GLenum op)
{
switch (op) {
case GL_KEEP:
return STENCILOP_KEEP;
case GL_ZERO:
return STENCILOP_ZERO;
case GL_REPLACE:
return STENCILOP_REPLACE;
case GL_INCR:
return STENCILOP_INCRSAT;
case GL_DECR:
return STENCILOP_DECRSAT;
case GL_INCR_WRAP:
return STENCILOP_INCR;
case GL_DECR_WRAP:
return STENCILOP_DECR;
case GL_INVERT:
return STENCILOP_INVERT;
default:
return STENCILOP_ZERO;
}
}
int
intel_translate_blend_factor(GLenum factor)
{
switch (factor) {
case GL_ZERO:
return BLENDFACT_ZERO;
case GL_SRC_ALPHA:
return BLENDFACT_SRC_ALPHA;
case GL_ONE:
return BLENDFACT_ONE;
case GL_SRC_COLOR:
return BLENDFACT_SRC_COLR;
case GL_ONE_MINUS_SRC_COLOR:
return BLENDFACT_INV_SRC_COLR;
case GL_DST_COLOR:
return BLENDFACT_DST_COLR;
case GL_ONE_MINUS_DST_COLOR:
return BLENDFACT_INV_DST_COLR;
case GL_ONE_MINUS_SRC_ALPHA:
return BLENDFACT_INV_SRC_ALPHA;
case GL_DST_ALPHA:
return BLENDFACT_DST_ALPHA;
case GL_ONE_MINUS_DST_ALPHA:
return BLENDFACT_INV_DST_ALPHA;
case GL_SRC_ALPHA_SATURATE:
return BLENDFACT_SRC_ALPHA_SATURATE;
case GL_CONSTANT_COLOR:
return BLENDFACT_CONST_COLOR;
case GL_ONE_MINUS_CONSTANT_COLOR:
return BLENDFACT_INV_CONST_COLOR;
case GL_CONSTANT_ALPHA:
return BLENDFACT_CONST_ALPHA;
case GL_ONE_MINUS_CONSTANT_ALPHA:
return BLENDFACT_INV_CONST_ALPHA;
}
fprintf(stderr, "Unknown value in %s: %x\n", __FUNCTION__, factor);
return BLENDFACT_ZERO;
}
int
intel_translate_logic_op(GLenum opcode)
{
switch (opcode) {
case GL_CLEAR:
return LOGICOP_CLEAR;
case GL_AND:
return LOGICOP_AND;
case GL_AND_REVERSE:
return LOGICOP_AND_RVRSE;
case GL_COPY:
return LOGICOP_COPY;
case GL_COPY_INVERTED:
return LOGICOP_COPY_INV;
case GL_AND_INVERTED:
return LOGICOP_AND_INV;
case GL_NOOP:
return LOGICOP_NOOP;
case GL_XOR:
return LOGICOP_XOR;
case GL_OR:
return LOGICOP_OR;
case GL_OR_INVERTED:
return LOGICOP_OR_INV;
case GL_NOR:
return LOGICOP_NOR;
case GL_EQUIV:
return LOGICOP_EQUIV;
case GL_INVERT:
return LOGICOP_INV;
case GL_OR_REVERSE:
return LOGICOP_OR_RVRSE;
case GL_NAND:
return LOGICOP_NAND;
case GL_SET:
return LOGICOP_SET;
default:
return LOGICOP_SET;
}
}

View file

@ -1 +0,0 @@
../intel/intel_syncobj.c

View file

@ -0,0 +1,124 @@
/*
* Copyright © 2008 Intel Corporation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
* IN THE SOFTWARE.
*
* Authors:
* Eric Anholt <eric@anholt.net>
*
*/
/** @file intel_syncobj.c
*
* Support for ARB_sync
*
* ARB_sync is implemented by flushing the current batchbuffer and keeping a
* reference on it. We can then check for completion or wait for completion
* using the normal buffer object mechanisms. This does mean that if an
* application is using many sync objects, it will emit small batchbuffers
* which may end up being a significant overhead. In other tests of removing
* gratuitous batchbuffer syncs in Mesa, it hasn't appeared to be a significant
* performance bottleneck, though.
*/
#include "main/simple_list.h"
#include "main/imports.h"
#include "intel_context.h"
#include "intel_batchbuffer.h"
#include "intel_reg.h"
static struct gl_sync_object *
intel_new_sync_object(struct gl_context *ctx, GLuint id)
{
struct intel_sync_object *sync;
sync = calloc(1, sizeof(struct intel_sync_object));
return &sync->Base;
}
static void
intel_delete_sync_object(struct gl_context *ctx, struct gl_sync_object *s)
{
struct intel_sync_object *sync = (struct intel_sync_object *)s;
drm_intel_bo_unreference(sync->bo);
free(sync);
}
static void
intel_fence_sync(struct gl_context *ctx, struct gl_sync_object *s,
GLenum condition, GLbitfield flags)
{
struct intel_context *intel = intel_context(ctx);
struct intel_sync_object *sync = (struct intel_sync_object *)s;
assert(condition == GL_SYNC_GPU_COMMANDS_COMPLETE);
intel_batchbuffer_emit_mi_flush(intel);
sync->bo = intel->batch.bo;
drm_intel_bo_reference(sync->bo);
intel_flush(ctx);
}
static void intel_client_wait_sync(struct gl_context *ctx, struct gl_sync_object *s,
GLbitfield flags, GLuint64 timeout)
{
struct intel_sync_object *sync = (struct intel_sync_object *)s;
if (sync->bo && drm_intel_gem_bo_wait(sync->bo, timeout) == 0) {
s->StatusFlag = 1;
drm_intel_bo_unreference(sync->bo);
sync->bo = NULL;
}
}
/* We have nothing to do for WaitSync. Our GL command stream is sequential,
* so given that the sync object has already flushed the batchbuffer,
* any batchbuffers coming after this waitsync will naturally not occur until
* the previous one is done.
*/
static void intel_server_wait_sync(struct gl_context *ctx, struct gl_sync_object *s,
GLbitfield flags, GLuint64 timeout)
{
}
static void intel_check_sync(struct gl_context *ctx, struct gl_sync_object *s)
{
struct intel_sync_object *sync = (struct intel_sync_object *)s;
if (sync->bo && !drm_intel_bo_busy(sync->bo)) {
drm_intel_bo_unreference(sync->bo);
sync->bo = NULL;
s->StatusFlag = 1;
}
}
void intel_init_syncobj_functions(struct dd_function_table *functions)
{
functions->NewSyncObject = intel_new_sync_object;
functions->DeleteSyncObject = intel_delete_sync_object;
functions->FenceSync = intel_fence_sync;
functions->CheckSync = intel_check_sync;
functions->ClientWaitSync = intel_client_wait_sync;
functions->ServerWaitSync = intel_server_wait_sync;
}

View file

@ -1 +0,0 @@
../intel/intel_tex.c

View file

@ -0,0 +1,189 @@
#include "swrast/swrast.h"
#include "main/renderbuffer.h"
#include "main/texobj.h"
#include "main/teximage.h"
#include "main/mipmap.h"
#include "drivers/common/meta.h"
#include "intel_context.h"
#include "intel_mipmap_tree.h"
#include "intel_tex.h"
#include "intel_fbo.h"
#define FILE_DEBUG_FLAG DEBUG_TEXTURE
static struct gl_texture_image *
intelNewTextureImage(struct gl_context * ctx)
{
DBG("%s\n", __FUNCTION__);
(void) ctx;
return (struct gl_texture_image *) CALLOC_STRUCT(intel_texture_image);
}
static void
intelDeleteTextureImage(struct gl_context * ctx, struct gl_texture_image *img)
{
/* nothing special (yet) for intel_texture_image */
_mesa_delete_texture_image(ctx, img);
}
static struct gl_texture_object *
intelNewTextureObject(struct gl_context * ctx, GLuint name, GLenum target)
{
struct intel_texture_object *obj = CALLOC_STRUCT(intel_texture_object);
(void) ctx;
DBG("%s\n", __FUNCTION__);
if (obj == NULL)
return NULL;
_mesa_initialize_texture_object(&obj->base, name, target);
obj->needs_validate = true;
return &obj->base;
}
static void
intelDeleteTextureObject(struct gl_context *ctx,
struct gl_texture_object *texObj)
{
struct intel_texture_object *intelObj = intel_texture_object(texObj);
intel_miptree_release(&intelObj->mt);
_mesa_delete_texture_object(ctx, texObj);
}
static GLboolean
intel_alloc_texture_image_buffer(struct gl_context *ctx,
struct gl_texture_image *image)
{
struct intel_context *intel = intel_context(ctx);
struct intel_texture_image *intel_image = intel_texture_image(image);
struct gl_texture_object *texobj = image->TexObject;
struct intel_texture_object *intel_texobj = intel_texture_object(texobj);
assert(image->Border == 0);
/* Quantize sample count */
if (image->NumSamples) {
image->NumSamples = intel_quantize_num_samples(intel->intelScreen, image->NumSamples);
if (!image->NumSamples)
return false;
}
/* Because the driver uses AllocTextureImageBuffer() internally, it may end
* up mismatched with FreeTextureImageBuffer(), but that is safe to call
* multiple times.
*/
ctx->Driver.FreeTextureImageBuffer(ctx, image);
if (!_swrast_init_texture_image(image))
return false;
if (intel_texobj->mt &&
intel_miptree_match_image(intel_texobj->mt, image)) {
intel_miptree_reference(&intel_image->mt, intel_texobj->mt);
DBG("%s: alloc obj %p level %d %dx%dx%d using object's miptree %p\n",
__FUNCTION__, texobj, image->Level,
image->Width, image->Height, image->Depth, intel_texobj->mt);
} else {
intel_image->mt = intel_miptree_create_for_teximage(intel, intel_texobj,
intel_image,
false);
/* 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.
*/
intel_miptree_reference(&intel_texobj->mt, intel_image->mt);
DBG("%s: alloc obj %p level %d %dx%dx%d using new miptree %p\n",
__FUNCTION__, texobj, image->Level,
image->Width, image->Height, image->Depth, intel_image->mt);
}
intel_texobj->needs_validate = true;
return true;
}
static void
intel_free_texture_image_buffer(struct gl_context * ctx,
struct gl_texture_image *texImage)
{
struct intel_texture_image *intelImage = intel_texture_image(texImage);
DBG("%s\n", __FUNCTION__);
intel_miptree_release(&intelImage->mt);
_swrast_free_texture_image_buffer(ctx, texImage);
}
/**
* Map texture memory/buffer into user space.
* Note: the region of interest parameters are ignored here.
* \param mode bitmask of GL_MAP_READ_BIT, GL_MAP_WRITE_BIT
* \param mapOut returns start of mapping of region of interest
* \param rowStrideOut returns row stride in bytes
*/
static void
intel_map_texture_image(struct gl_context *ctx,
struct gl_texture_image *tex_image,
GLuint slice,
GLuint x, GLuint y, GLuint w, GLuint h,
GLbitfield mode,
GLubyte **map,
GLint *stride)
{
struct intel_context *intel = intel_context(ctx);
struct intel_texture_image *intel_image = intel_texture_image(tex_image);
struct intel_mipmap_tree *mt = intel_image->mt;
/* Our texture data is always stored in a miptree. */
assert(mt);
/* Check that our caller wasn't confused about how to map a 1D texture. */
assert(tex_image->TexObject->Target != GL_TEXTURE_1D_ARRAY ||
h == 1);
/* intel_miptree_map operates on a unified "slice" number that references the
* cube face, since it's all just slices to the miptree code.
*/
if (tex_image->TexObject->Target == GL_TEXTURE_CUBE_MAP)
slice = tex_image->Face;
intel_miptree_map(intel, mt, tex_image->Level, slice, x, y, w, h, mode,
(void **)map, stride);
}
static void
intel_unmap_texture_image(struct gl_context *ctx,
struct gl_texture_image *tex_image, GLuint slice)
{
struct intel_context *intel = intel_context(ctx);
struct intel_texture_image *intel_image = intel_texture_image(tex_image);
struct intel_mipmap_tree *mt = intel_image->mt;
if (tex_image->TexObject->Target == GL_TEXTURE_CUBE_MAP)
slice = tex_image->Face;
intel_miptree_unmap(intel, mt, tex_image->Level, slice);
}
void
intelInitTextureFuncs(struct dd_function_table *functions)
{
functions->NewTextureObject = intelNewTextureObject;
functions->NewTextureImage = intelNewTextureImage;
functions->DeleteTextureImage = intelDeleteTextureImage;
functions->DeleteTexture = intelDeleteTextureObject;
functions->AllocTextureImageBuffer = intel_alloc_texture_image_buffer;
functions->FreeTextureImageBuffer = intel_free_texture_image_buffer;
functions->MapTextureImage = intel_map_texture_image;
functions->UnmapTextureImage = intel_unmap_texture_image;
}

View file

@ -0,0 +1,82 @@
/**************************************************************************
*
* Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sub license, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial portions
* of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
**************************************************************************/
#ifndef INTELTEX_INC
#define INTELTEX_INC
#include "main/mtypes.h"
#include "main/formats.h"
#include "intel_context.h"
struct intel_renderbuffer;
void intelInitTextureFuncs(struct dd_function_table *functions);
void intelInitTextureImageFuncs(struct dd_function_table *functions);
void intelInitTextureSubImageFuncs(struct dd_function_table *functions);
void intelInitTextureCopyImageFuncs(struct dd_function_table *functions);
void intelSetTexBuffer(__DRIcontext *pDRICtx,
GLint target, __DRIdrawable *pDraw);
void intelSetTexBuffer2(__DRIcontext *pDRICtx,
GLint target, GLint format, __DRIdrawable *pDraw);
struct intel_mipmap_tree *
intel_miptree_create_for_teximage(struct intel_context *intel,
struct intel_texture_object *intelObj,
struct intel_texture_image *intelImage,
bool expect_accelerated_upload);
GLuint intel_finalize_mipmap_tree(struct intel_context *intel, GLuint unit);
void intel_tex_map_level_images(struct intel_context *intel,
struct intel_texture_object *intelObj,
int level,
GLbitfield mode);
void intel_tex_unmap_level_images(struct intel_context *intel,
struct intel_texture_object *intelObj,
int level);
bool
intel_tex_image_s8z24_create_renderbuffers(struct intel_context *intel,
struct intel_texture_image *image);
bool
intel_texsubimage_tiled_memcpy(struct gl_context *ctx,
GLuint dims,
struct gl_texture_image *texImage,
GLint xoffset, GLint yoffset, GLint zoffset,
GLsizei width, GLsizei height, GLsizei depth,
GLenum format, GLenum type,
const GLvoid *pixels,
const struct gl_pixelstore_attrib *packing,
bool for_glTexImage);
#endif

View file

@ -1 +0,0 @@
../intel/intel_tex_copy.c

View file

@ -0,0 +1,132 @@
/**************************************************************************
*
* Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sub license, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial portions
* of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
**************************************************************************/
#include "main/mtypes.h"
#include "main/enums.h"
#include "main/image.h"
#include "main/teximage.h"
#include "main/texstate.h"
#include "main/fbobject.h"
#include "drivers/common/meta.h"
#include "intel_screen.h"
#include "intel_context.h"
#include "intel_mipmap_tree.h"
#include "intel_regions.h"
#include "intel_fbo.h"
#include "intel_tex.h"
#include "intel_blit.h"
#ifndef I915
#include "brw_context.h"
#endif
#define FILE_DEBUG_FLAG DEBUG_TEXTURE
static bool
intel_copy_texsubimage(struct intel_context *intel,
struct intel_texture_image *intelImage,
GLint dstx, GLint dsty, GLint slice,
struct intel_renderbuffer *irb,
GLint x, GLint y, GLsizei width, GLsizei height)
{
const GLenum internalFormat = intelImage->base.Base.InternalFormat;
intel_prepare_render(intel);
/* glCopyTexSubImage() can be called on a multisampled renderbuffer (if
* that renderbuffer is associated with the window system framebuffer),
* however the hardware blitter can't handle this case, so fall back to
* meta (which can, since it uses ReadPixels).
*/
if (irb->Base.Base.NumSamples != 0)
return false;
/* glCopyTexSubImage() can't be called on a multisampled texture. */
assert(intelImage->base.Base.NumSamples == 0);
if (!intelImage->mt || !irb || !irb->mt) {
if (unlikely(INTEL_DEBUG & DEBUG_PERF))
fprintf(stderr, "%s fail %p %p (0x%08x)\n",
__FUNCTION__, intelImage->mt, irb, internalFormat);
return false;
}
/* blit from src buffer to texture */
if (!intel_miptree_blit(intel,
irb->mt, irb->mt_level, irb->mt_layer,
x, y, irb->Base.Base.Name == 0,
intelImage->mt, intelImage->base.Base.Level,
intelImage->base.Base.Face + slice,
dstx, dsty, false,
width, height, GL_COPY)) {
return false;
}
return true;
}
static void
intelCopyTexSubImage(struct gl_context *ctx, GLuint dims,
struct gl_texture_image *texImage,
GLint xoffset, GLint yoffset, GLint slice,
struct gl_renderbuffer *rb,
GLint x, GLint y,
GLsizei width, GLsizei height)
{
struct intel_context *intel = intel_context(ctx);
#ifndef I915
/* Try BLORP first. It can handle almost everything. */
if (brw_blorp_copytexsubimage(intel, rb, texImage, slice, x, y,
xoffset, yoffset, width, height))
return;
#endif
/* Next, try the BLT engine. */
if (intel_copy_texsubimage(intel,
intel_texture_image(texImage),
xoffset, yoffset, slice,
intel_renderbuffer(rb), x, y, width, height)) {
return;
}
/* Finally, fall back to meta. This will likely be slow. */
perf_debug("%s - fallback to swrast\n", __FUNCTION__);
_mesa_meta_CopyTexSubImage(ctx, dims, texImage,
xoffset, yoffset, slice,
rb, x, y, width, height);
}
void
intelInitTextureCopyImageFuncs(struct dd_function_table *functions)
{
functions->CopyTexSubImage = intelCopyTexSubImage;
}

View file

@ -1 +0,0 @@
../intel/intel_tex_image.c

View file

@ -0,0 +1,399 @@
#include "main/glheader.h"
#include "main/macros.h"
#include "main/mtypes.h"
#include "main/enums.h"
#include "main/bufferobj.h"
#include "main/context.h"
#include "main/formats.h"
#include "main/image.h"
#include "main/pbo.h"
#include "main/renderbuffer.h"
#include "main/texcompress.h"
#include "main/texgetimage.h"
#include "main/texobj.h"
#include "main/teximage.h"
#include "main/texstore.h"
#include "intel_context.h"
#include "intel_mipmap_tree.h"
#include "intel_buffer_objects.h"
#include "intel_batchbuffer.h"
#include "intel_tex.h"
#include "intel_blit.h"
#include "intel_fbo.h"
#ifndef I915
#include "brw_context.h"
#endif
#define FILE_DEBUG_FLAG DEBUG_TEXTURE
/* Work back from the specified level of the image to the baselevel and create a
* miptree of that size.
*/
struct intel_mipmap_tree *
intel_miptree_create_for_teximage(struct intel_context *intel,
struct intel_texture_object *intelObj,
struct intel_texture_image *intelImage,
bool expect_accelerated_upload)
{
GLuint firstLevel;
GLuint lastLevel;
int width, height, depth;
GLuint i;
intel_miptree_get_dimensions_for_image(&intelImage->base.Base,
&width, &height, &depth);
DBG("%s\n", __FUNCTION__);
if (intelImage->base.Base.Level > intelObj->base.BaseLevel &&
(width == 1 ||
(intelObj->base.Target != GL_TEXTURE_1D && height == 1) ||
(intelObj->base.Target == GL_TEXTURE_3D && 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->base.Base.Level;
lastLevel = intelImage->base.Base.Level;
} else {
/* If this image disrespects BaseLevel, allocate from level zero.
* Usually BaseLevel == 0, so it's unlikely to happen.
*/
if (intelImage->base.Base.Level < intelObj->base.BaseLevel)
firstLevel = 0;
else
firstLevel = intelObj->base.BaseLevel;
/* Figure out image dimensions at start level. */
for (i = intelImage->base.Base.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.Sampler.MinFilter == GL_NEAREST ||
intelObj->base.Sampler.MinFilter == GL_LINEAR) &&
intelImage->base.Base.Level == firstLevel &&
(intel->gen < 4 || firstLevel == 0)) {
lastLevel = firstLevel;
} else {
lastLevel = (firstLevel +
_mesa_get_tex_max_num_levels(intelObj->base.Target,
width, height, depth) - 1);
}
}
return intel_miptree_create(intel,
intelObj->base.Target,
intelImage->base.Base.TexFormat,
firstLevel,
lastLevel,
width,
height,
depth,
expect_accelerated_upload,
intelImage->base.Base.NumSamples,
INTEL_MIPTREE_TILING_ANY);
}
/* XXX: Do this for TexSubImage also:
*/
static bool
try_pbo_upload(struct gl_context *ctx,
struct gl_texture_image *image,
const struct gl_pixelstore_attrib *unpack,
GLenum format, GLenum type, const void *pixels)
{
struct intel_texture_image *intelImage = intel_texture_image(image);
struct intel_context *intel = intel_context(ctx);
struct intel_buffer_object *pbo = intel_buffer_object(unpack->BufferObj);
GLuint src_offset;
drm_intel_bo *src_buffer;
if (!_mesa_is_bufferobj(unpack->BufferObj))
return false;
DBG("trying pbo upload\n");
if (intel->ctx._ImageTransferState ||
unpack->SkipPixels || unpack->SkipRows) {
DBG("%s: image transfer\n", __FUNCTION__);
return false;
}
ctx->Driver.AllocTextureImageBuffer(ctx, image);
if (!intelImage->mt) {
DBG("%s: no miptree\n", __FUNCTION__);
return false;
}
if (!_mesa_format_matches_format_and_type(intelImage->mt->format,
format, type, false)) {
DBG("%s: format mismatch (upload to %s with format 0x%x, type 0x%x)\n",
__FUNCTION__, _mesa_get_format_name(intelImage->mt->format),
format, type);
return false;
}
if (image->TexObject->Target == GL_TEXTURE_1D_ARRAY ||
image->TexObject->Target == GL_TEXTURE_2D_ARRAY) {
DBG("%s: no support for array textures\n", __FUNCTION__);
return false;
}
src_buffer = intel_bufferobj_source(intel, pbo, 64, &src_offset);
/* note: potential 64-bit ptr to 32-bit int cast */
src_offset += (GLuint) (unsigned long) pixels;
int src_stride =
_mesa_image_row_stride(unpack, image->Width, format, type);
struct intel_mipmap_tree *pbo_mt =
intel_miptree_create_for_bo(intel,
src_buffer,
intelImage->mt->format,
src_offset,
image->Width, image->Height,
src_stride, I915_TILING_NONE);
if (!pbo_mt)
return false;
if (!intel_miptree_blit(intel,
pbo_mt, 0, 0,
0, 0, false,
intelImage->mt, image->Level, image->Face,
0, 0, false,
image->Width, image->Height, GL_COPY)) {
DBG("%s: blit failed\n", __FUNCTION__);
return false;
}
intel_miptree_release(&pbo_mt);
DBG("%s: success\n", __FUNCTION__);
return true;
}
static void
intelTexImage(struct gl_context * ctx,
GLuint dims,
struct gl_texture_image *texImage,
GLenum format, GLenum type, const void *pixels,
const struct gl_pixelstore_attrib *unpack)
{
bool ok;
DBG("%s target %s level %d %dx%dx%d\n", __FUNCTION__,
_mesa_lookup_enum_by_nr(texImage->TexObject->Target),
texImage->Level, texImage->Width, texImage->Height, texImage->Depth);
ok = intel_texsubimage_tiled_memcpy(ctx, dims, texImage,
0, 0, 0, /*x,y,z offsets*/
texImage->Width,
texImage->Height,
texImage->Depth,
format, type, pixels, unpack,
true /*for_glTexImage*/);
if (ok)
return;
/* Attempt to use the blitter for PBO image uploads.
*/
if (dims <= 2 &&
try_pbo_upload(ctx, texImage, unpack, format, type, pixels)) {
return;
}
DBG("%s: upload image %dx%dx%d pixels %p\n",
__FUNCTION__, texImage->Width, texImage->Height, texImage->Depth,
pixels);
_mesa_store_teximage(ctx, dims, texImage,
format, type, pixels, unpack);
}
/**
* Binds a region to a texture image, like it was uploaded by glTexImage2D().
*
* Used for GLX_EXT_texture_from_pixmap and EGL image extensions,
*/
static void
intel_set_texture_image_region(struct gl_context *ctx,
struct gl_texture_image *image,
struct intel_region *region,
GLenum target,
GLenum internalFormat,
gl_format format,
uint32_t offset,
GLuint width,
GLuint height,
GLuint tile_x,
GLuint tile_y)
{
struct intel_context *intel = intel_context(ctx);
struct intel_texture_image *intel_image = intel_texture_image(image);
struct gl_texture_object *texobj = image->TexObject;
struct intel_texture_object *intel_texobj = intel_texture_object(texobj);
bool has_surface_tile_offset = false;
uint32_t draw_x, draw_y;
_mesa_init_teximage_fields(&intel->ctx, image,
width, height, 1,
0, internalFormat, format);
ctx->Driver.FreeTextureImageBuffer(ctx, image);
intel_image->mt = intel_miptree_create_layout(intel, target, image->TexFormat,
0, 0,
width, height, 1,
true, 0 /* num_samples */);
if (intel_image->mt == NULL)
return;
intel_region_reference(&intel_image->mt->region, region);
intel_image->mt->total_width = width;
intel_image->mt->total_height = height;
intel_image->mt->level[0].slice[0].x_offset = tile_x;
intel_image->mt->level[0].slice[0].y_offset = tile_y;
intel_miptree_get_tile_offsets(intel_image->mt, 0, 0, &draw_x, &draw_y);
#ifndef I915
has_surface_tile_offset = brw_context(ctx)->has_surface_tile_offset;
#endif
/* From "OES_EGL_image" error reporting. We report GL_INVALID_OPERATION
* for EGL images from non-tile aligned sufaces in gen4 hw and earlier which has
* trouble resolving back to destination image due to alignment issues.
*/
if (!has_surface_tile_offset &&
(draw_x != 0 || draw_y != 0)) {
_mesa_error(ctx, GL_INVALID_OPERATION, __func__);
intel_miptree_release(&intel_image->mt);
return;
}
intel_texobj->needs_validate = true;
intel_image->mt->offset = offset;
assert(region->pitch % region->cpp == 0);
intel_image->base.RowStride = region->pitch / region->cpp;
/* Immediately validate the image to the object. */
intel_miptree_reference(&intel_texobj->mt, intel_image->mt);
}
void
intelSetTexBuffer2(__DRIcontext *pDRICtx, GLint target,
GLint texture_format,
__DRIdrawable *dPriv)
{
struct gl_framebuffer *fb = dPriv->driverPrivate;
struct intel_context *intel = pDRICtx->driverPrivate;
struct gl_context *ctx = &intel->ctx;
struct intel_texture_object *intelObj;
struct intel_renderbuffer *rb;
struct gl_texture_object *texObj;
struct gl_texture_image *texImage;
int level = 0, internalFormat = 0;
gl_format texFormat = MESA_FORMAT_NONE;
texObj = _mesa_get_current_tex_object(ctx, target);
intelObj = intel_texture_object(texObj);
if (!intelObj)
return;
if (dPriv->lastStamp != dPriv->dri2.stamp ||
!pDRICtx->driScreenPriv->dri2.useInvalidate)
intel_update_renderbuffers(pDRICtx, dPriv);
rb = intel_get_renderbuffer(fb, BUFFER_FRONT_LEFT);
/* If the region isn't set, then intel_update_renderbuffers was unable
* to get the buffers for the drawable.
*/
if (!rb || !rb->mt)
return;
if (rb->mt->cpp == 4) {
if (texture_format == __DRI_TEXTURE_FORMAT_RGB) {
internalFormat = GL_RGB;
texFormat = MESA_FORMAT_XRGB8888;
}
else {
internalFormat = GL_RGBA;
texFormat = MESA_FORMAT_ARGB8888;
}
} else if (rb->mt->cpp == 2) {
internalFormat = GL_RGB;
texFormat = MESA_FORMAT_RGB565;
}
_mesa_lock_texture(&intel->ctx, texObj);
texImage = _mesa_get_tex_image(ctx, texObj, target, level);
intel_miptree_make_shareable(intel, rb->mt);
intel_set_texture_image_region(ctx, texImage, rb->mt->region, target,
internalFormat, texFormat, 0,
rb->mt->region->width,
rb->mt->region->height,
0, 0);
_mesa_unlock_texture(&intel->ctx, texObj);
}
void
intelSetTexBuffer(__DRIcontext *pDRICtx, GLint target, __DRIdrawable *dPriv)
{
/* The old interface didn't have the format argument, so copy our
* implementation's behavior at the time.
*/
intelSetTexBuffer2(pDRICtx, target, __DRI_TEXTURE_FORMAT_RGBA, dPriv);
}
static void
intel_image_target_texture_2d(struct gl_context *ctx, GLenum target,
struct gl_texture_object *texObj,
struct gl_texture_image *texImage,
GLeglImageOES image_handle)
{
struct intel_context *intel = intel_context(ctx);
__DRIscreen *screen;
__DRIimage *image;
screen = intel->intelScreen->driScrnPriv;
image = screen->dri2.image->lookupEGLImage(screen, image_handle,
screen->loaderPrivate);
if (image == NULL)
return;
/* Disallow depth/stencil textures: we don't have a way to pass the
* separate stencil miptree of a GL_DEPTH_STENCIL texture through.
*/
if (image->has_depthstencil) {
_mesa_error(ctx, GL_INVALID_OPERATION, __func__);
return;
}
intel_set_texture_image_region(ctx, texImage, image->region,
target, image->internal_format,
image->format, image->offset,
image->width, image->height,
image->tile_x, image->tile_y);
}
void
intelInitTextureImageFuncs(struct dd_function_table *functions)
{
functions->TexImage = intelTexImage;
functions->EGLImageTargetTexture2D = intel_image_target_texture_2d;
}

View file

@ -1 +0,0 @@
../intel/intel_tex_layout.c

View file

@ -0,0 +1,214 @@
/**************************************************************************
*
* Copyright 2006 Tungsten Graphics, Inc., Cedar Park, Texas.
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sub license, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial portions
* of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
**************************************************************************/
/*
* Authors:
* Keith Whitwell <keith@tungstengraphics.com>
* Michel Dänzer <michel@tungstengraphics.com>
*/
#include "intel_mipmap_tree.h"
#include "intel_tex_layout.h"
#include "intel_context.h"
#include "main/image.h"
#include "main/macros.h"
static unsigned int
intel_horizontal_texture_alignment_unit(struct intel_context *intel,
gl_format format)
{
/**
* From the "Alignment Unit Size" section of various specs, namely:
* - Gen3 Spec: "Memory Data Formats" Volume, Section 1.20.1.4
* - i965 and G45 PRMs: Volume 1, Section 6.17.3.4.
* - Ironlake and Sandybridge PRMs: Volume 1, Part 1, Section 7.18.3.4
* - BSpec (for Ivybridge and slight variations in separate stencil)
*
* +----------------------------------------------------------------------+
* | | alignment unit width ("i") |
* | Surface Property |-----------------------------|
* | | 915 | 965 | ILK | SNB | IVB |
* +----------------------------------------------------------------------+
* | YUV 4:2:2 format | 8 | 4 | 4 | 4 | 4 |
* | BC1-5 compressed format (DXTn/S3TC) | 4 | 4 | 4 | 4 | 4 |
* | FXT1 compressed format | 8 | 8 | 8 | 8 | 8 |
* | Depth Buffer (16-bit) | 4 | 4 | 4 | 4 | 8 |
* | Depth Buffer (other) | 4 | 4 | 4 | 4 | 4 |
* | Separate Stencil Buffer | N/A | N/A | 8 | 8 | 8 |
* | All Others | 4 | 4 | 4 | 4 | 4 |
* +----------------------------------------------------------------------+
*
* On IVB+, non-special cases can be overridden by setting the SURFACE_STATE
* "Surface Horizontal Alignment" field to HALIGN_4 or HALIGN_8.
*/
if (_mesa_is_format_compressed(format)) {
/* The hardware alignment requirements for compressed textures
* happen to match the block boundaries.
*/
unsigned int i, j;
_mesa_get_format_block_size(format, &i, &j);
return i;
}
if (format == MESA_FORMAT_S8)
return 8;
/* The depth alignment requirements in the table above are for rendering to
* depth miplevels using the LOD control fields. We don't use LOD control
* fields, and instead use page offsets plus intra-tile x/y offsets, which
* require that the low 3 bits are zero. To reduce the number of x/y
* offset workaround blits we do, align the X to 8, which depth texturing
* can handle (sadly, it can't handle 8 in the Y direction).
*/
if (intel->gen >= 7 &&
_mesa_get_format_base_format(format) == GL_DEPTH_COMPONENT)
return 8;
return 4;
}
static unsigned int
intel_vertical_texture_alignment_unit(struct intel_context *intel,
gl_format format)
{
/**
* From the "Alignment Unit Size" section of various specs, namely:
* - Gen3 Spec: "Memory Data Formats" Volume, Section 1.20.1.4
* - i965 and G45 PRMs: Volume 1, Section 6.17.3.4.
* - Ironlake and Sandybridge PRMs: Volume 1, Part 1, Section 7.18.3.4
* - BSpec (for Ivybridge and slight variations in separate stencil)
*
* +----------------------------------------------------------------------+
* | | alignment unit height ("j") |
* | Surface Property |-----------------------------|
* | | 915 | 965 | ILK | SNB | IVB |
* +----------------------------------------------------------------------+
* | BC1-5 compressed format (DXTn/S3TC) | 4 | 4 | 4 | 4 | 4 |
* | FXT1 compressed format | 4 | 4 | 4 | 4 | 4 |
* | Depth Buffer | 2 | 2 | 2 | 4 | 4 |
* | Separate Stencil Buffer | N/A | N/A | N/A | 4 | 8 |
* | Multisampled (4x or 8x) render target | N/A | N/A | N/A | 4 | 4 |
* | All Others | 2 | 2 | 2 | 2 | 2 |
* +----------------------------------------------------------------------+
*
* On SNB+, non-special cases can be overridden by setting the SURFACE_STATE
* "Surface Vertical Alignment" field to VALIGN_2 or VALIGN_4.
*
* We currently don't support multisampling.
*/
if (_mesa_is_format_compressed(format))
return 4;
if (format == MESA_FORMAT_S8)
return intel->gen >= 7 ? 8 : 4;
GLenum base_format = _mesa_get_format_base_format(format);
if (intel->gen >= 6 &&
(base_format == GL_DEPTH_COMPONENT ||
base_format == GL_DEPTH_STENCIL)) {
return 4;
}
return 2;
}
void
intel_get_texture_alignment_unit(struct intel_context *intel,
gl_format format,
unsigned int *w, unsigned int *h)
{
*w = intel_horizontal_texture_alignment_unit(intel, format);
*h = intel_vertical_texture_alignment_unit(intel, format);
}
void i945_miptree_layout_2d(struct intel_mipmap_tree *mt)
{
GLuint level;
GLuint x = 0;
GLuint y = 0;
GLuint width = mt->physical_width0;
GLuint height = mt->physical_height0;
GLuint depth = mt->physical_depth0; /* number of array layers. */
mt->total_width = mt->physical_width0;
if (mt->compressed) {
mt->total_width = ALIGN(mt->physical_width0, mt->align_w);
}
/* May need to adjust width to accomodate the placement of
* the 2nd mipmap. This occurs when the alignment
* constraints of mipmap placement push the right edge of the
* 2nd mipmap out past the width of its parent.
*/
if (mt->first_level != mt->last_level) {
GLuint mip1_width;
if (mt->compressed) {
mip1_width = ALIGN(minify(mt->physical_width0, 1), mt->align_w) +
ALIGN(minify(mt->physical_width0, 2), mt->align_w);
} else {
mip1_width = ALIGN(minify(mt->physical_width0, 1), mt->align_w) +
minify(mt->physical_width0, 2);
}
if (mip1_width > mt->total_width) {
mt->total_width = mip1_width;
}
}
mt->total_height = 0;
for ( level = mt->first_level ; level <= mt->last_level ; level++ ) {
GLuint img_height;
intel_miptree_set_level_info(mt, level, x, y, width,
height, depth);
img_height = ALIGN(height, mt->align_h);
if (mt->compressed)
img_height /= mt->align_h;
/* Because the images are packed better, the final offset
* might not be the maximal one:
*/
mt->total_height = MAX2(mt->total_height, y + img_height);
/* Layout_below: step right after second mipmap.
*/
if (level == mt->first_level + 1) {
x += ALIGN(width, mt->align_w);
}
else {
y += img_height;
}
width = minify(width, 1);
height = minify(height, 1);
}
}

View file

@ -0,0 +1,40 @@
/**************************************************************************
*
* Copyright 2006 Tungsten Graphics, Inc., Cedar Park, Texas.
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sub license, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial portions
* of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
**************************************************************************/
/*
* Authors:
* Keith Whitwell <keith@tungstengraphics.com>
* Michel Dänzer <michel@tungstengraphics.com>
*/
#include "main/macros.h"
extern void i945_miptree_layout_2d(struct intel_mipmap_tree *mt);
void
intel_get_texture_alignment_unit(struct intel_context *intel,
gl_format format,
unsigned int *w, unsigned int *h);

View file

@ -0,0 +1,84 @@
/**************************************************************************
*
* Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sub license, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial portions
* of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
**************************************************************************/
#ifndef _INTEL_TEX_OBJ_H
#define _INTEL_TEX_OBJ_H
#include "swrast/s_context.h"
struct intel_texture_object
{
struct gl_texture_object base;
/* 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.
*/
unsigned int _MaxLevel;
/* On validation any active images held in main memory or in other
* regions will be copied to this region and the old storage freed.
*/
struct intel_mipmap_tree *mt;
/**
* Set when mipmap trees in the texture images of this texture object
* might not all be the mipmap tree above.
*/
bool needs_validate;
};
/**
* intel_texture_image is a subclass of swrast_texture_image because we
* sometimes fall back to using the swrast module for software rendering.
*/
struct intel_texture_image
{
struct swrast_texture_image base;
/* If intelImage->mt != NULL, image data is stored here.
* Else if intelImage->base.Buffer != NULL, image is stored there.
* Else there is no image data.
*/
struct intel_mipmap_tree *mt;
};
static INLINE struct intel_texture_object *
intel_texture_object(struct gl_texture_object *obj)
{
return (struct intel_texture_object *) obj;
}
static INLINE struct intel_texture_image *
intel_texture_image(struct gl_texture_image *img)
{
return (struct intel_texture_image *) img;
}
#endif /* _INTEL_TEX_OBJ_H */

View file

@ -1 +0,0 @@
../intel/intel_tex_subimage.c

View file

@ -0,0 +1,335 @@
/**************************************************************************
*
* Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sub license, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial portions
* of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
**************************************************************************/
#include "main/bufferobj.h"
#include "main/macros.h"
#include "main/mtypes.h"
#include "main/pbo.h"
#include "main/texobj.h"
#include "main/texstore.h"
#include "main/texcompress.h"
#include "main/enums.h"
#include "intel_batchbuffer.h"
#include "intel_context.h"
#include "intel_tex.h"
#include "intel_mipmap_tree.h"
#include "intel_blit.h"
#define FILE_DEBUG_FLAG DEBUG_TEXTURE
static bool
intel_blit_texsubimage(struct gl_context * ctx,
struct gl_texture_image *texImage,
GLint xoffset, GLint yoffset,
GLint width, GLint height,
GLenum format, GLenum type, const void *pixels,
const struct gl_pixelstore_attrib *packing)
{
struct intel_context *intel = intel_context(ctx);
struct intel_texture_image *intelImage = intel_texture_image(texImage);
/* Try to do a blit upload of the subimage if the texture is
* currently busy.
*/
if (!intelImage->mt)
return false;
/* The blitter can't handle Y tiling */
if (intelImage->mt->region->tiling == I915_TILING_Y)
return false;
if (texImage->TexObject->Target != GL_TEXTURE_2D)
return false;
/* On gen6, it's probably not worth swapping to the blit ring to do
* this because of all the overhead involved.
*/
if (intel->gen >= 6)
return false;
if (!drm_intel_bo_busy(intelImage->mt->region->bo))
return false;
DBG("BLT subimage %s target %s level %d offset %d,%d %dx%d\n",
__FUNCTION__,
_mesa_lookup_enum_by_nr(texImage->TexObject->Target),
texImage->Level, xoffset, yoffset, width, height);
pixels = _mesa_validate_pbo_teximage(ctx, 2, width, height, 1,
format, type, pixels, packing,
"glTexSubImage");
if (!pixels)
return false;
struct intel_mipmap_tree *temp_mt =
intel_miptree_create(intel, GL_TEXTURE_2D, texImage->TexFormat,
0, 0,
width, height, 1,
false, 0, INTEL_MIPTREE_TILING_NONE);
if (!temp_mt)
goto err;
GLubyte *dst = intel_miptree_map_raw(intel, temp_mt);
if (!dst)
goto err;
if (!_mesa_texstore(ctx, 2, texImage->_BaseFormat,
texImage->TexFormat,
temp_mt->region->pitch,
&dst,
width, height, 1,
format, type, pixels, packing)) {
_mesa_error(ctx, GL_OUT_OF_MEMORY, "intelTexSubImage");
}
intel_miptree_unmap_raw(intel, temp_mt);
bool ret;
ret = intel_miptree_blit(intel,
temp_mt, 0, 0,
0, 0, false,
intelImage->mt, texImage->Level, texImage->Face,
xoffset, yoffset, false,
width, height, GL_COPY);
assert(ret);
intel_miptree_release(&temp_mt);
_mesa_unmap_teximage_pbo(ctx, packing);
return ret;
err:
_mesa_error(ctx, GL_OUT_OF_MEMORY, "intelTexSubImage");
intel_miptree_release(&temp_mt);
_mesa_unmap_teximage_pbo(ctx, packing);
return false;
}
/**
* \brief A fast path for glTexImage and glTexSubImage.
*
* \param for_glTexImage Was this called from glTexImage or glTexSubImage?
*
* This fast path is taken when the hardware natively supports the texture
* format (such as GL_BGRA) and when the texture memory is X-tiled. It uploads
* the texture data by mapping the texture memory without a GTT fence, thus
* acquiring a tiled view of the memory, and then memcpy'ing sucessive
* subspans within each tile.
*
* This is a performance win over the conventional texture upload path because
* it avoids the performance penalty of writing through the write-combine
* buffer. In the conventional texture upload path,
* texstore.c:store_texsubimage(), the texture memory is mapped through a GTT
* fence, thus acquiring a linear view of the memory, then each row in the
* image is memcpy'd. In this fast path, we replace each row's memcpy with
* a sequence of memcpy's over each bit6 swizzle span in the row.
*
* This fast path's use case is Google Chrome's paint rectangles. Chrome (as
* of version 21) renders each page as a tiling of 256x256 GL_BGRA textures.
* Each page's content is initially uploaded with glTexImage2D and damaged
* regions are updated with glTexSubImage2D. On some workloads, the
* performance gain of this fastpath on Sandybridge is over 5x.
*/
bool
intel_texsubimage_tiled_memcpy(struct gl_context * ctx,
GLuint dims,
struct gl_texture_image *texImage,
GLint xoffset, GLint yoffset, GLint zoffset,
GLsizei width, GLsizei height, GLsizei depth,
GLenum format, GLenum type,
const GLvoid *pixels,
const struct gl_pixelstore_attrib *packing,
bool for_glTexImage)
{
struct intel_context *intel = intel_context(ctx);
struct intel_texture_image *image = intel_texture_image(texImage);
/* The miptree's buffer. */
drm_intel_bo *bo;
int error = 0;
/* This fastpath is restricted to a specific texture type: level 0 of
* a 2D BGRA texture. It could be generalized to support more types by
* varying the arithmetic loop below.
*/
if (!intel->has_llc ||
format != GL_BGRA ||
type != GL_UNSIGNED_BYTE ||
texImage->TexFormat != MESA_FORMAT_ARGB8888 ||
texImage->TexObject->Target != GL_TEXTURE_2D ||
texImage->Level != 0 ||
pixels == NULL ||
_mesa_is_bufferobj(packing->BufferObj) ||
packing->Alignment > 4 ||
packing->SkipPixels > 0 ||
packing->SkipRows > 0 ||
(packing->RowLength != 0 && packing->RowLength != width) ||
packing->SwapBytes ||
packing->LsbFirst ||
packing->Invert)
return false;
if (for_glTexImage)
ctx->Driver.AllocTextureImageBuffer(ctx, texImage);
if (!image->mt ||
image->mt->region->tiling != I915_TILING_X) {
/* The algorithm below is written only for X-tiled memory. */
return false;
}
/* Since we are going to write raw data to the miptree, we need to resolve
* any pending fast color clears before we start.
*/
intel_miptree_resolve_color(intel, image->mt);
bo = image->mt->region->bo;
if (drm_intel_bo_references(intel->batch.bo, bo)) {
perf_debug("Flushing before mapping a referenced bo.\n");
intel_batchbuffer_flush(intel);
}
if (unlikely(intel->perf_debug)) {
if (drm_intel_bo_busy(bo)) {
perf_debug("Mapping a busy BO, causing a stall on the GPU.\n");
}
}
error = drm_intel_bo_map(bo, true /*write_enable*/);
if (error || bo->virtual == NULL) {
DBG("%s: failed to map bo\n", __FUNCTION__);
return false;
}
/* We postponed printing this message until having committed to executing
* the function.
*/
DBG("%s: level=%d offset=(%d,%d) (w,h)=(%d,%d)\n",
__FUNCTION__, texImage->Level, xoffset, yoffset, width, height);
/* In the tiling algorithm below, some variables are in units of pixels,
* others are in units of bytes, and others (such as height) are unitless.
* Each variable name is suffixed with its units.
*/
const uint32_t x_max_pixels = xoffset + width;
const uint32_t y_max_pixels = yoffset + height;
const uint32_t tile_size_bytes = 4096;
const uint32_t tile_width_bytes = 512;
const uint32_t tile_width_pixels = 128;
const uint32_t tile_height = 8;
const uint32_t cpp = 4; /* chars per pixel of GL_BGRA */
const uint32_t swizzle_width_pixels = 16;
const uint32_t stride_bytes = image->mt->region->pitch;
const uint32_t width_tiles = stride_bytes / tile_width_bytes;
for (uint32_t y_pixels = yoffset; y_pixels < y_max_pixels; ++y_pixels) {
const uint32_t y_offset_bytes = (y_pixels / tile_height) * width_tiles * tile_size_bytes
+ (y_pixels % tile_height) * tile_width_bytes;
for (uint32_t x_pixels = xoffset; x_pixels < x_max_pixels; x_pixels += swizzle_width_pixels) {
const uint32_t x_offset_bytes = (x_pixels / tile_width_pixels) * tile_size_bytes
+ (x_pixels % tile_width_pixels) * cpp;
intptr_t offset_bytes = y_offset_bytes + x_offset_bytes;
if (intel->has_swizzling) {
#if 0
/* Clear, unoptimized version. */
bool bit6 = (offset_bytes >> 6) & 1;
bool bit9 = (offset_bytes >> 9) & 1;
bool bit10 = (offset_bytes >> 10) & 1;
if (bit9 ^ bit10)
offset_bytes ^= (1 << 6);
#else
/* Optimized, obfuscated version. */
offset_bytes ^= ((offset_bytes >> 3) ^ (offset_bytes >> 4))
& (1 << 6);
#endif
}
const uint32_t swizzle_bound_pixels = ALIGN(x_pixels + 1, swizzle_width_pixels);
const uint32_t memcpy_bound_pixels = MIN2(x_max_pixels, swizzle_bound_pixels);
const uint32_t copy_size = cpp * (memcpy_bound_pixels - x_pixels);
memcpy(bo->virtual + offset_bytes, pixels, copy_size);
pixels += copy_size;
x_pixels -= (x_pixels % swizzle_width_pixels);
}
}
drm_intel_bo_unmap(bo);
return true;
}
static void
intelTexSubImage(struct gl_context * ctx,
GLuint dims,
struct gl_texture_image *texImage,
GLint xoffset, GLint yoffset, GLint zoffset,
GLsizei width, GLsizei height, GLsizei depth,
GLenum format, GLenum type,
const GLvoid * pixels,
const struct gl_pixelstore_attrib *packing)
{
bool ok;
ok = intel_texsubimage_tiled_memcpy(ctx, dims, texImage,
xoffset, yoffset, zoffset,
width, height, depth,
format, type, pixels, packing,
false /*for_glTexImage*/);
if (ok)
return;
/* The intel_blit_texsubimage() function only handles 2D images */
if (dims != 2 || !intel_blit_texsubimage(ctx, texImage,
xoffset, yoffset,
width, height,
format, type, pixels, packing)) {
_mesa_store_texsubimage(ctx, dims, texImage,
xoffset, yoffset, zoffset,
width, height, depth,
format, type, pixels, packing);
}
}
void
intelInitTextureSubImageFuncs(struct dd_function_table *functions)
{
functions->TexSubImage = intelTexSubImage;
}

View file

@ -1 +0,0 @@
../intel/intel_tex_validate.c

View file

@ -0,0 +1,141 @@
#include "main/mtypes.h"
#include "main/macros.h"
#include "main/samplerobj.h"
#include "main/texobj.h"
#include "intel_context.h"
#include "intel_mipmap_tree.h"
#include "intel_blit.h"
#include "intel_tex.h"
#include "intel_tex_layout.h"
#define FILE_DEBUG_FLAG DEBUG_TEXTURE
/**
* 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_update_max_level(struct intel_texture_object *intelObj,
struct gl_sampler_object *sampler)
{
struct gl_texture_object *tObj = &intelObj->base;
int maxlevel;
if (sampler->MinFilter == GL_NEAREST ||
sampler->MinFilter == GL_LINEAR) {
maxlevel = tObj->BaseLevel;
} else {
maxlevel = tObj->_MaxLevel;
}
if (intelObj->_MaxLevel != maxlevel) {
intelObj->_MaxLevel = maxlevel;
intelObj->needs_validate = true;
}
}
/*
*/
GLuint
intel_finalize_mipmap_tree(struct intel_context *intel, GLuint unit)
{
struct gl_context *ctx = &intel->ctx;
struct gl_texture_object *tObj = intel->ctx.Texture.Unit[unit]._Current;
struct intel_texture_object *intelObj = intel_texture_object(tObj);
struct gl_sampler_object *sampler = _mesa_get_samplerobj(ctx, unit);
GLuint face, i;
GLuint nr_faces = 0;
struct intel_texture_image *firstImage;
int width, height, depth;
/* TBOs require no validation -- they always just point to their BO. */
if (tObj->Target == GL_TEXTURE_BUFFER)
return true;
/* We know/require this is true by now:
*/
assert(intelObj->base._BaseComplete);
/* What levels must the tree include at a minimum?
*/
intel_update_max_level(intelObj, sampler);
if (intelObj->mt && intelObj->mt->first_level != tObj->BaseLevel)
intelObj->needs_validate = true;
if (!intelObj->needs_validate)
return true;
firstImage = intel_texture_image(tObj->Image[0][tObj->BaseLevel]);
/* Check tree can hold all active levels. Check tree matches
* target, imageFormat, etc.
*
* 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 &&
(!intel_miptree_match_image(intelObj->mt, &firstImage->base.Base) ||
intelObj->mt->first_level != tObj->BaseLevel ||
intelObj->mt->last_level < intelObj->_MaxLevel)) {
intel_miptree_release(&intelObj->mt);
}
/* May need to create a new tree:
*/
if (!intelObj->mt) {
intel_miptree_get_dimensions_for_image(&firstImage->base.Base,
&width, &height, &depth);
perf_debug("Creating new %s %dx%dx%d %d..%d miptree to handle finalized "
"texture miptree.\n",
_mesa_get_format_name(firstImage->base.Base.TexFormat),
width, height, depth, tObj->BaseLevel, intelObj->_MaxLevel);
intelObj->mt = intel_miptree_create(intel,
intelObj->base.Target,
firstImage->base.Base.TexFormat,
tObj->BaseLevel,
intelObj->_MaxLevel,
width,
height,
depth,
true,
0 /* num_samples */,
INTEL_MIPTREE_TILING_ANY);
if (!intelObj->mt)
return false;
}
/* Pull in any images not in the object's tree:
*/
nr_faces = _mesa_num_tex_faces(intelObj->base.Target);
for (face = 0; face < nr_faces; face++) {
for (i = tObj->BaseLevel; i <= intelObj->_MaxLevel; i++) {
struct intel_texture_image *intelImage =
intel_texture_image(intelObj->base.Image[face][i]);
/* skip too small size mipmap */
if (intelImage == NULL)
break;
if (intelObj->mt != intelImage->mt) {
intel_miptree_copy_teximage(intel, intelImage, intelObj->mt,
false /* invalidate */);
}
/* After we're done, we'd better agree that our layout is
* appropriate, or we'll end up hitting this function again on the
* next draw
*/
assert(intel_miptree_match_image(intelObj->mt, &intelImage->base.Base));
}
}
intelObj->needs_validate = false;
return true;
}