Merge branch 'drm-gem'

This commit is contained in:
Jesse Barnes 2008-08-06 12:40:47 -07:00
commit f9504eff31
36 changed files with 6193 additions and 454 deletions

View File

@ -19,7 +19,7 @@
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
AUTOMAKE_OPTIONS = foreign
SUBDIRS = src man
SUBDIRS = uxa src man
EXTRA_DIST = README
DISTCLEANFILES = doltcompile

View File

@ -196,9 +196,10 @@ if test "x$GCC" = "xyes"; then
-Wnested-externs -fno-strict-aliasing"
fi
PKG_CHECK_MODULES(DRM, [libdrm >= 2.4.0])
AM_CONDITIONAL(DRI, test x$DRI = xyes)
if test "$DRI" = yes; then
PKG_CHECK_MODULES(DRI, [libdrm xf86driproto glproto])
PKG_CHECK_MODULES(DRI, [xf86driproto glproto])
AC_DEFINE(XF86DRI,1,[Enable DRI driver support])
AC_DEFINE(XF86DRI_DEVEL,1,[Enable developmental DRI driver support])
PKG_CHECK_MODULES(DRI_MM, [libdrm >= 2.4.0],[DRI_MM=yes], [DRI_MM=no])
@ -208,17 +209,6 @@ if test "$DRI" = yes; then
if test "$have_damage_h" = yes; then
AC_DEFINE(DAMAGE,1,[Use Damage extension])
fi
save_CFLAGS="$CFLAGS"
CFLAGS="$XORG_CFLAGS $DRI_CFLAGS"
AC_CHECK_TYPE(drm_i915_flip_t,
[AC_DEFINE(HAVE_I915_FLIP, 1,
[Have drm_i915_flip_t and related definitions])],
[], [
#include <inttypes.h>
#include <i915_drm.h>
])
CFLAGS="$save_CFLAGS"
fi
AM_CONDITIONAL(VIDEO_DEBUG, test x$VIDEO_DEBUG = xyes)
@ -261,6 +251,7 @@ XORG_CHECK_LINUXDOC
AC_OUTPUT([
Makefile
uxa/Makefile
src/Makefile
src/xvmc/Makefile
src/bios_reader/Makefile

View File

@ -30,13 +30,14 @@ SUBDIRS = xvmc bios_reader ch7017 ch7xxx ivch sil164 tfp410 $(REGDUMPER)
# _ladir passes a dummy rpath to libtool so the thing will actually link
# TODO: -nostdlib/-Bstatic/-lgcc platform magic, not installing the .a, etc.
AM_CFLAGS = @WARN_CFLAGS@ @XORG_CFLAGS@ @DRI_CFLAGS@ @PCIACCESS_CFLAGS@ \
@XMODES_CFLAGS@ -DI830_XV -DI830_USE_XAA -DI830_USE_EXA
AM_CFLAGS = @WARN_CFLAGS@ @XORG_CFLAGS@ @DRM_CFLAGS@ @DRI_CFLAGS@ \
@PCIACCESS_CFLAGS@ -I../uxa \
@XMODES_CFLAGS@ -DI830_XV -DI830_USE_XAA -DI830_USE_EXA -DI830_USE_UXA
intel_drv_la_LTLIBRARIES = intel_drv.la
intel_drv_la_LDFLAGS = -module -avoid-version
intel_drv_ladir = @moduledir@/drivers
intel_drv_la_LIBADD = -lm
intel_drv_la_LIBADD = -lm ../uxa/libuxa.la
if XSERVER_LIBPCIACCESS
intel_drv_la_LIBADD += @PCIACCESS_LIBS@
endif
@ -93,6 +94,8 @@ intel_drv_la_SOURCES = \
i830_accel.c \
i830_bios.c \
i830_bios.h \
i830_batchbuffer.c \
i830_batchbuffer.h \
i830_common.h \
i830_crt.c \
i830_cursor.c \
@ -154,7 +157,6 @@ INTEL_G4I = \
exa_wm.g4i \
exa_wm_affine.g4i \
exa_wm_projective.g4i
INTEL_G4B = \
packed_yuv_sf.g4b \
@ -176,7 +178,7 @@ INTEL_G4B = \
exa_wm_write.g4b \
exa_wm_yuv_rgb.g4b \
exa_wm_xy.g4b
EXTRA_DIST = \
$(XMODE_SRCS) \
$(INTEL_G4A) \

View File

@ -405,7 +405,8 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
/* Current active ring head address:
*/
#define ACTHD 0x2074
#define ACTHD_I965 0x2074
#define ACTHD 0x20C8
/* Current primary/secondary DMA fetch addresses:
*/
@ -490,6 +491,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
* - new bits for i810
* - new register hwstam (mask)
*/
#define HWS_PGA 0x2080
#define PWRCTXA 0x2088 /* 965GM+ only */
#define PWRCTX_EN (1<<0)
#define HWSTAM 0x2098 /* p290 */
@ -2417,6 +2419,13 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#define STATE3D_COLOR_FACTOR ((0x3<<29)|(0x1d<<24)|(0x01<<16))
/* Batch */
#define MI_BATCH_BUFFER ((0x30 << 23) | 1)
#define MI_BATCH_BUFFER_START (0x31 << 23)
#define MI_BATCH_BUFFER_END (0xA << 23)
#define MI_BATCH_NON_SECURE (1)
#define MI_BATCH_NON_SECURE_I965 (1 << 8)
/* STATE3D_FOG_MODE stuff */
#define ENABLE_FOG_SOURCE (1<<27)
#define ENABLE_FOG_CONST (1<<24)

View File

@ -69,9 +69,6 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#ifdef XF86DRI
#include "xf86drm.h"
#ifdef XF86DRI_MM
#include "xf86mm.h"
#endif
#include "sarea.h"
#define _XF86DRI_SERVER_
#include "dri.h"
@ -81,6 +78,9 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#include "damage.h"
#endif
#endif
#include "dri_bufmgr.h"
#include "intel_bufmgr.h"
#include "i915_drm.h"
#ifdef I830_USE_EXA
#include "exa.h"
@ -88,6 +88,14 @@ Bool I830EXAInit(ScreenPtr pScreen);
unsigned long long I830TexOffsetStart(PixmapPtr pPix);
#endif
#ifdef I830_USE_UXA
#include "uxa.h"
Bool i830_uxa_init(ScreenPtr pScreen);
dri_bo *i830_uxa_get_pixmap_bo (PixmapPtr pixmap);
void i830_uxa_create_screen_resources(ScreenPtr pScreen);
void i830_uxa_block_handler (ScreenPtr pScreen);
#endif
#ifdef I830_USE_XAA
Bool I830XAAInit(ScreenPtr pScreen);
#endif
@ -95,7 +103,6 @@ Bool I830XAAInit(ScreenPtr pScreen);
typedef struct _I830OutputRec I830OutputRec, *I830OutputPtr;
#include "common.h"
#include "i830_ring.h"
#include "i830_sdvo.h"
#include "i2c_vid.h"
@ -194,10 +201,10 @@ struct _i830_memory {
i830_memory *prev;
/** @} */
#ifdef XF86DRI_MM
drmBO bo;
dri_bo *bo;
uint32_t alignment;
uint32_t gem_name;
Bool lifetime_fixed_offset;
#endif
};
typedef struct {
@ -355,6 +362,14 @@ enum backlight_control {
BCM_KERNEL,
};
typedef enum accel_method {
ACCEL_UNINIT = 0,
ACCEL_NONE,
ACCEL_XAA,
ACCEL_EXA,
ACCEL_UXA
} accel_method_t;
typedef struct _I830Rec {
unsigned char *MMIOBase;
unsigned char *GTTBase;
@ -398,6 +413,8 @@ typedef struct _I830Rec {
i830_memory *exa_offscreen;
i830_memory *gen4_render_state_mem;
#endif
i830_memory *fake_bufmgr_mem;
/* Regions allocated either from the above pools, or from agpgart. */
I830RingBuffer *LpRing;
@ -408,6 +425,17 @@ typedef struct _I830Rec {
/** Offset in the ring for the next DWORD emit */
uint32_t ring_next;
dri_bufmgr *bufmgr;
uint8_t *batch_ptr;
/** Byte offset in batch_ptr for the next dword to be emitted. */
unsigned int batch_used;
/** Position in batch_ptr at the start of the current BEGIN_BATCH */
unsigned int batch_emit_start;
/** Number of bytes to be emitted in the current BEGIN_BATCH. */
uint32_t batch_emitting;
dri_bo *batch_bo;
#ifdef I830_XV
/* For Xvideo */
i830_memory *overlay_regs;
@ -445,6 +473,8 @@ typedef struct _I830Rec {
#endif
#endif
Bool need_mi_flush;
Bool NeedRingBufferLow;
Bool allowPageFlip;
Bool TripleBuffer;
@ -481,8 +511,7 @@ typedef struct _I830Rec {
Bool fence_used[FENCE_NEW_NR];
Bool useEXA;
Bool noAccel;
accel_method_t accel;
Bool SWCursor;
#ifdef I830_USE_XAA
XAAInfoRecPtr AccelInfoRec;
@ -503,8 +532,19 @@ typedef struct _I830Rec {
#ifdef I830_USE_EXA
ExaDriverPtr EXADriverPtr;
#endif
#ifdef I830_USE_UXA
uxa_driver_t *uxa_driver;
Bool need_flush;
Bool need_sync;
#endif
#if defined(I830_USE_EXA) || defined(I830_USE_UXA)
PixmapPtr pSrcPixmap;
#endif
int accel_pixmap_pitch_alignment;
int accel_pixmap_offset_alignment;
int accel_max_x;
int accel_max_y;
I830WriteIndexedByteFunc writeControl;
I830ReadIndexedByteFunc readControl;
@ -676,6 +716,12 @@ typedef struct _I830Rec {
#define I830_SELECT_DEPTH 2
#define I830_SELECT_THIRD 3
unsigned long intel_get_pixmap_offset(PixmapPtr pPix);
unsigned long intel_get_pixmap_pitch(PixmapPtr pPix);
/* Batchbuffer support macros and functions */
#include "i830_batchbuffer.h"
/* I830 specific functions */
extern int I830WaitLpRing(ScrnInfoPtr pScrn, int n, int timeout_millis);
extern void I830SetPIOAccess(I830Ptr pI830);
@ -747,8 +793,6 @@ extern Bool I830DRISetHWS(ScrnInfoPtr pScrn);
extern Bool I830DRIInstIrqHandler(ScrnInfoPtr pScrn);
#endif
unsigned long intel_get_pixmap_offset(PixmapPtr pPix);
unsigned long intel_get_pixmap_pitch(PixmapPtr pPix);
extern Bool I830AccelInit(ScreenPtr pScreen);
extern void I830SetupForScreenToScreenCopy(ScrnInfoPtr pScrn, int xdir,
int ydir, int rop,
@ -783,6 +827,7 @@ Bool i830_allocate_2d_memory(ScrnInfoPtr pScrn);
Bool i830_allocate_texture_memory(ScrnInfoPtr pScrn);
Bool i830_allocate_pwrctx(ScrnInfoPtr pScrn);
Bool i830_allocate_3d_memory(ScrnInfoPtr pScrn);
void i830_init_bufmgr(ScrnInfoPtr pScrn);
#ifdef INTEL_XVMC
Bool i830_allocate_xvmc_buffer(ScrnInfoPtr pScrn, const char *name,
i830_memory **buffer, unsigned long size, int flags);
@ -885,7 +930,7 @@ static inline int i830_fb_compression_supported(I830Ptr pI830)
/* fbc depends on tiled surface. And we don't support tiled
* front buffer with XAA now.
*/
if (!pI830->tiling || (IS_I965G(pI830) && !pI830->useEXA))
if (!pI830->tiling || (IS_I965G(pI830) && pI830->accel <= ACCEL_XAA))
return FALSE;
return TRUE;
}
@ -903,13 +948,6 @@ Bool i830_pixmap_tiled(PixmapPtr p);
if (pitch > KB(8)) I830FALLBACK("pitch exceeds 3d limit 8K\n");\
} while(0)
/* Batchbuffer compatibility handling */
#define BEGIN_BATCH(n) BEGIN_LP_RING(n)
#define ENSURE_BATCH(n)
#define OUT_BATCH(d) OUT_RING(d)
#define OUT_BATCH_F(x) OUT_RING_F(x)
#define ADVANCE_BATCH() ADVANCE_LP_RING()
extern const int I830PatternROP[16];
extern const int I830CopyROP[16];

View File

@ -54,21 +54,25 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*/
#include <errno.h>
#include "xf86.h"
#include "xaarop.h"
#include "i830.h"
#include "i810_reg.h"
#include "i830_debug.h"
#include "i830_ring.h"
#include "i915_drm.h"
unsigned long
intel_get_pixmap_offset(PixmapPtr pPix)
{
#if defined(I830_USE_EXA) || defined(I830_USE_UXA)
ScreenPtr pScreen = pPix->drawable.pScreen;
ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
I830Ptr pI830 = I830PTR(pScrn);
#ifdef I830_USE_EXA
if (pI830->useEXA)
if (pI830->accel == ACCEL_EXA)
return exaGetPixmapOffset(pPix);
#endif
return (unsigned long)pPix->devPrivate.ptr - (unsigned long)pI830->FbBase;
@ -77,17 +81,15 @@ intel_get_pixmap_offset(PixmapPtr pPix)
unsigned long
intel_get_pixmap_pitch(PixmapPtr pPix)
{
#ifdef I830_USE_EXA
ScreenPtr pScreen = pPix->drawable.pScreen;
ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
I830Ptr pI830 = I830PTR(pScrn);
#ifdef I830_USE_EXA
if (pI830->useEXA)
if (pI830->accel == ACCEL_EXA)
return exaGetPixmapPitch(pPix);
#endif
#ifdef I830_USE_XAA
return (unsigned long)pPix->devKind;
#endif
}
int
@ -146,6 +148,9 @@ I830WaitLpRing(ScrnInfoPtr pScrn, int n, int timeout_millis)
#endif
#ifdef I830_USE_EXA
pI830->EXADriverPtr = NULL;
#endif
#ifdef I830_USE_UXA
pI830->uxa_driver = NULL;
#endif
FatalError("lockup\n");
}
@ -168,12 +173,11 @@ void
I830Sync(ScrnInfoPtr pScrn)
{
I830Ptr pI830 = I830PTR(pScrn);
int flags = MI_WRITE_DIRTY_STATE | MI_INVALIDATE_MAP_CACHE;
if (I810_DEBUG & (DEBUG_VERBOSE_ACCEL | DEBUG_VERBOSE_SYNC))
ErrorF("I830Sync\n");
if (pI830->noAccel)
if (pI830->accel == ACCEL_NONE)
return;
#ifdef XF86DRI
@ -186,24 +190,40 @@ I830Sync(ScrnInfoPtr pScrn)
if (pI830->entityPrivate && !pI830->entityPrivate->RingRunning) return;
if (IS_I965G(pI830))
flags = 0;
I830EmitFlush(pScrn);
/* Send a flush instruction and then wait till the ring is empty.
* This is stronger than waiting for the blitter to finish as it also
* flushes the internal graphics caches.
*/
{
BEGIN_BATCH(2);
OUT_BATCH(MI_FLUSH | flags);
OUT_BATCH(MI_NOOP); /* pad to quadword */
ADVANCE_BATCH();
intel_batch_flush(pScrn);
if (pI830->directRenderingEnabled) {
struct drm_i915_irq_emit emit;
struct drm_i915_irq_wait wait;
int ret;
/* Most of the uses of I830Sync while using GEM should actually be
* using set_domain on a specific buffer. We're not there yet, so fake
* it up using irq_emit/wait. It's still better than spinning on
* register reads for idle.
*/
emit.irq_seq = &wait.irq_seq;
ret = drmCommandWrite(pI830->drmSubFD, DRM_I830_IRQ_EMIT, &emit,
sizeof(emit));
if (ret != 0)
FatalError("Failure to emit IRQ: %s\n", strerror(-ret));
do {
ret = drmCommandWrite(pI830->drmSubFD, DRM_I830_IRQ_WAIT, &wait,
sizeof(wait));
} while (ret == -EINTR);
if (ret != 0)
FatalError("Failure to wait for IRQ: %s\n", strerror(-ret));
if (!pI830->memory_manager)
i830_refresh_ring(pScrn);
} else {
i830_wait_ring_idle(pScrn);
}
i830_wait_ring_idle(pScrn);
pI830->LpRing->space = pI830->LpRing->mem->size - 8;
pI830->nextColorExpandBuf = 0;
}
@ -259,15 +279,73 @@ I830SelectBuffer(ScrnInfoPtr pScrn, int buffer)
Bool
I830AccelInit(ScreenPtr pScreen)
{
#ifdef I830_USE_EXA
ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
I830Ptr pI830 = I830PTR(pScrn);
if (pI830->useEXA)
/* Limits are described in the BLT engine chapter under Graphics Data Size
* Limitations, and the descriptions of SURFACE_STATE, 3DSTATE_BUFFER_INFO,
* 3DSTATE_DRAWING_RECTANGLE, 3DSTATE_MAP_INFO, and 3DSTATE_MAP_INFO.
*
* i845 through i965 limits 2D rendering to 65536 lines and pitch of 32768.
*
* i965 limits 3D surface to (2*element size)-aligned offset if un-tiled.
* i965 limits 3D surface to 4kB-aligned offset if tiled.
* i965 limits 3D surfaces to w,h of ?,8192.
* i965 limits 3D surface to pitch of 1B - 128kB.
* i965 limits 3D surface pitch alignment to 1 or 2 times the element size.
* i965 limits 3D surface pitch alignment to 512B if tiled.
* i965 limits 3D destination drawing rect to w,h of 8192,8192.
*
* i915 limits 3D textures to 4B-aligned offset if un-tiled.
* i915 limits 3D textures to ~4kB-aligned offset if tiled.
* i915 limits 3D textures to width,height of 2048,2048.
* i915 limits 3D textures to pitch of 16B - 8kB, in dwords.
* i915 limits 3D destination to ~4kB-aligned offset if tiled.
* i915 limits 3D destination to pitch of 16B - 8kB, in dwords, if un-tiled.
* i915 limits 3D destination to pitch of 512B - 8kB, in tiles, if tiled.
* i915 limits 3D destination to POT aligned pitch if tiled.
* i915 limits 3D destination drawing rect to w,h of 2048,2048.
*
* i845 limits 3D textures to 4B-aligned offset if un-tiled.
* i845 limits 3D textures to ~4kB-aligned offset if tiled.
* i845 limits 3D textures to width,height of 2048,2048.
* i845 limits 3D textures to pitch of 4B - 8kB, in dwords.
* i845 limits 3D destination to 4B-aligned offset if un-tiled.
* i845 limits 3D destination to ~4kB-aligned offset if tiled.
* i845 limits 3D destination to pitch of 8B - 8kB, in dwords.
* i845 limits 3D destination drawing rect to w,h of 2048,2048.
*
* For the tiled issues, the only tiled buffer we draw to should be
* the front, which will have an appropriate pitch/offset already set up,
* so EXA doesn't need to worry.
*/
if (IS_I965G(pI830)) {
pI830->accel_pixmap_offset_alignment = 4 * 2;
pI830->accel_pixmap_pitch_alignment = 16;
pI830->accel_max_x = 8192;
pI830->accel_max_y = 8192;
} else {
pI830->accel_pixmap_offset_alignment = 4;
pI830->accel_pixmap_pitch_alignment = 16;
pI830->accel_max_x = 2048;
pI830->accel_max_y = 2048;
}
switch (pI830->accel) {
#ifdef I830_USE_UXA
case ACCEL_UXA:
return i830_uxa_init(pScreen);
#endif
#ifdef I830_USE_EXA
case ACCEL_EXA:
return I830EXAInit(pScreen);
#endif
#ifdef I830_USE_XAA
return I830XAAInit(pScreen);
case ACCEL_XAA:
return I830XAAInit(pScreen);
#endif
case ACCEL_UNINIT:
case ACCEL_NONE:
break;
}
return FALSE;
}

167
src/i830_batchbuffer.c Normal file
View File

@ -0,0 +1,167 @@
/* -*- c-basic-offset: 4 -*- */
/*
* Copyright © 2006 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>
*
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <assert.h>
#include <stdlib.h>
#include <errno.h>
#include "xf86.h"
#include "i830.h"
#include "i830_ring.h"
#include "i915_drm.h"
static void
intel_next_batch(ScrnInfoPtr pScrn)
{
I830Ptr pI830 = I830PTR(pScrn);
/* The 865 has issues with larger-than-page-sized batch buffers. */
if (IS_I865G(pI830))
pI830->batch_bo = dri_bo_alloc(pI830->bufmgr, "batch", 4096, 4096);
else
pI830->batch_bo = dri_bo_alloc(pI830->bufmgr, "batch", 4096 * 4, 4096);
dri_bo_map(pI830->batch_bo, 1);
pI830->batch_used = 0;
pI830->batch_ptr = pI830->batch_bo->virtual;
}
void
intel_batch_init(ScrnInfoPtr pScrn)
{
I830Ptr pI830 = I830PTR(pScrn);
pI830->batch_emit_start = 0;
pI830->batch_emitting = 0;
intel_next_batch(pScrn);
}
void
intel_batch_teardown(ScrnInfoPtr pScrn)
{
I830Ptr pI830 = I830PTR(pScrn);
if (pI830->batch_ptr != NULL) {
dri_bo_unmap(pI830->batch_bo);
pI830->batch_ptr = NULL;
}
}
void
intel_batch_flush(ScrnInfoPtr pScrn)
{
I830Ptr pI830 = I830PTR(pScrn);
if (pI830->batch_used == 0)
return;
/* Emit a padding dword if we aren't going to be quad-word aligned. */
if ((pI830->batch_used & 4) == 0) {
*(uint32_t *)(pI830->batch_ptr + pI830->batch_used) = MI_NOOP;
pI830->batch_used += 4;
}
/* Mark the end of the batchbuffer. */
*(uint32_t *)(pI830->batch_ptr + pI830->batch_used) = MI_BATCH_BUFFER_END;
pI830->batch_used += 4;
dri_bo_unmap(pI830->batch_bo);
pI830->batch_ptr = NULL;
if (pI830->memory_manager) {
struct drm_i915_gem_execbuffer *exec;
int ret;
exec = dri_process_relocs(pI830->batch_bo);
exec->batch_start_offset = 0;
exec->batch_len = pI830->batch_used;
exec->cliprects_ptr = 0;
exec->num_cliprects = 0;
exec->DR1 = 0;
exec->DR4 = 0xffffffff;
do {
ret = drmCommandWriteRead(pI830->drmSubFD, DRM_I915_GEM_EXECBUFFER,
exec, sizeof(*exec));
} while (ret == -EINTR);
if (ret != 0)
FatalError("Failed to submit batchbuffer: %s\n", strerror(errno));
} else {
dri_process_relocs(pI830->batch_bo);
if (pI830->directRenderingEnabled) {
struct drm_i915_batchbuffer batch;
int ret;
batch.start = pI830->batch_bo->offset;
batch.used = pI830->batch_used;
batch.cliprects = NULL;
batch.num_cliprects = 0;
batch.DR1 = 0;
batch.DR4 = 0xffffffff;
ret = drmCommandWrite(pI830->drmSubFD, DRM_I915_BATCHBUFFER,
&batch, sizeof(batch));
if (ret != 0)
FatalError("Failed to submit batchbuffer: %s\n", strerror(errno));
i830_refresh_ring(pScrn);
} else {
if (!IS_I830(pI830) && !IS_845G(pI830)) {
BEGIN_LP_RING(2);
OUT_RING(MI_BATCH_BUFFER_START | (2 << 6));
OUT_RING(pI830->batch_bo->offset);
ADVANCE_LP_RING();
} else {
BEGIN_LP_RING(4);
OUT_RING(MI_BATCH_BUFFER);
OUT_RING(pI830->batch_bo->offset);
OUT_RING(pI830->batch_bo->offset + pI830->batch_used - 4);
OUT_RING(MI_NOOP);
ADVANCE_LP_RING();
}
}
}
dri_post_submit(pI830->batch_bo);
dri_bo_unreference(pI830->batch_bo);
intel_next_batch(pScrn);
/* Mark that we need to flush whatever potential rendering we've done in the
* blockhandler. We could set this less often, but it's probably not worth
* the work.
*/
pI830->need_mi_flush = TRUE;
}

148
src/i830_batchbuffer.h Normal file
View File

@ -0,0 +1,148 @@
/**************************************************************************
Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas.
Copyright © 2002 David Dawes
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 PRECISION INSIGHT 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_BATCHBUFFER_H
#define _INTEL_BATCHBUFFER_H
#define BATCH_RESERVED 16
void intel_batch_init(ScrnInfoPtr pScrn);
void intel_batch_teardown(ScrnInfoPtr pScrn);
void intel_batch_flush(ScrnInfoPtr pScrn);
static inline int
intel_batch_space(I830Ptr pI830)
{
return (pI830->batch_bo->size - BATCH_RESERVED) - (pI830->batch_used);
}
static inline void
intel_batch_require_space(ScrnInfoPtr pScrn, I830Ptr pI830, GLuint sz)
{
assert(sz < pI830->batch_bo->size - 8);
if (intel_batch_space(pI830) < sz)
intel_batch_flush(pScrn);
}
static inline void
intel_batch_emit_dword(I830Ptr pI830, uint32_t dword)
{
assert(pI830->batch_ptr != NULL);
assert(intel_batch_space(pI830) >= 4);
*(uint32_t *)(pI830->batch_ptr + pI830->batch_used) = dword;
pI830->batch_used += 4;
}
static inline void
intel_batch_emit_reloc (I830Ptr pI830,
dri_bo *bo,
uint32_t read_domains,
uint32_t write_domains,
uint32_t delta)
{
assert(intel_batch_space(pI830) >= 4);
*(uint32_t *)(pI830->batch_ptr + pI830->batch_used) = bo->offset + delta;
intel_bo_emit_reloc (pI830->batch_bo, read_domains, write_domains, delta,
pI830->batch_used, bo);
pI830->batch_used += 4;
}
static inline void
intel_batch_emit_reloc_pixmap(I830Ptr pI830, PixmapPtr pPixmap,
uint32_t read_domains, uint32_t write_domain,
uint32_t delta)
{
#if I830_USE_UXA
dri_bo *bo = i830_uxa_get_pixmap_bo(pPixmap);
#endif
uint32_t offset;
assert(pI830->batch_ptr != NULL);
assert(intel_batch_space(pI830) >= 4);
#if I830_USE_UXA
if (bo) {
intel_batch_emit_reloc(pI830, bo, read_domains, write_domain, delta);
return;
}
#endif
offset = intel_get_pixmap_offset(pPixmap);
*(uint32_t *)(pI830->batch_ptr + pI830->batch_used) = offset + delta;
pI830->batch_used += 4;
}
#define OUT_BATCH(dword) intel_batch_emit_dword(pI830, dword)
#define OUT_RELOC(bo, read_domains, write_domains, delta) \
intel_batch_emit_reloc (pI830, bo, read_domains, write_domains, delta)
#define OUT_RELOC_PIXMAP(pPixmap, reads, write, delta) \
intel_batch_emit_reloc_pixmap(pI830, pPixmap, reads, write, delta)
union intfloat {
float f;
unsigned int ui;
};
#define OUT_BATCH_F(x) do { \
union intfloat tmp; \
tmp.f = (float)(x); \
OUT_BATCH(tmp.ui); \
} while(0)
#define BEGIN_BATCH(n) \
do { \
if (pI830->batch_emitting != 0) \
FatalError("%s: BEGIN_BATCH called without closing " \
"ADVANCE_BATCH\n", __FUNCTION__); \
pI830->batch_emitting = (n) * 4; \
intel_batch_require_space(pScrn, pI830, pI830->batch_emitting); \
pI830->batch_emit_start = pI830->batch_used; \
} while (0)
#define ADVANCE_BATCH() do { \
if (pI830->batch_emitting == 0) \
FatalError("%s: ADVANCE_BATCH called with no matching " \
"BEGIN_BATCH\n", __FUNCTION__); \
if (pI830->batch_used > pI830->batch_emit_start + pI830->batch_emitting) \
FatalError("%s: ADVANCE_BATCH: exceeded allocation %d/%d\n ", \
__FUNCTION__, \
pI830->batch_used - pI830->batch_emit_start, \
pI830->batch_emitting); \
if (pI830->batch_used < pI830->batch_emit_start + pI830->batch_emitting) \
FatalError("%s: ADVANCE_BATCH: under-used allocation %d/%d\n ", \
__FUNCTION__, \
pI830->batch_used - pI830->batch_emit_start, \
pI830->batch_emitting); \
if ((pI830->batch_emitting > 8) && (I810_DEBUG & DEBUG_ALWAYS_SYNC)) { \
/* Note: not actually syncing, just flushing each batch. */ \
intel_batch_flush(pScrn); \
} \
pI830->batch_emitting = 0; \
} while (0)
#endif /* _INTEL_BATCHBUFFER_H */

View File

@ -1314,6 +1314,8 @@ i830_valid_command (uint32_t cmd)
if (!mi_cmds[opcode])
return -1;
break;
case 1:
return -1;
case 2: /* 2D */
count = (cmd & 0x1f) + 2;
opcode = (cmd >> 22) & 0x7f;
@ -1471,13 +1473,12 @@ i830_dump_cmds (ScrnInfoPtr pScrn,
/* check for MI_BATCH_BUFFER_START */
if ((data & batch_start_mask) == batch_start_cmd)
{
uint32_t batch = ptr[1];
uint32_t batch = ptr[1] & ~3;
if (batch < pI830->FbMapSize) {
ErrorF ("\t%08x: %08x\n", (ring + 4) & mask, batch);
ErrorF ("Batch buffer at 0x%08x {\n", batch);
i830_dump_cmds (pScrn, pI830->FbBase, batch,
pI830->FbMapSize - batch,
0xffffffff, acthd);
batch + 256, 0xffffffff, acthd);
ErrorF ("}\n");
ring = (ring + (count - 1) * 4) & mask;
}
@ -1501,8 +1502,8 @@ i830_dump_ring(ScrnInfoPtr pScrn, uint32_t acthd)
mask = pI830->LpRing->tail_mask;
virt = pI830->LpRing->virtual_start;
ErrorF ("Ring at virtual %p head 0x%x tail 0x%x count %d\n",
virt, head, tail, (((tail + mask + 1) - head) & mask) >> 2);
ErrorF ("Ring at virtual %p head 0x%x tail 0x%x count %d acthd 0x%x\n",
virt, head, tail, (((tail + mask + 1) - head) & mask) >> 2, acthd);
/* walk back by instructions */
for (cmd = (head - 256) & mask;
@ -1547,7 +1548,7 @@ i830_dump_error_state(ScrnInfoPtr pScrn)
ErrorF("hwstam: 0x%04x ier: 0x%04x imr: 0x%04x iir: 0x%04x\n",
INREG16(HWSTAM), INREG16(IER), INREG16(IMR), INREG16(IIR));
i830_dump_ring (pScrn, 0);
i830_dump_ring (pScrn, INREG(ACTHD));
}
void
@ -1584,7 +1585,7 @@ i965_dump_error_state(ScrnInfoPtr pScrn)
"imr: 0x%08x iir: 0x%08x\n",
INREG(HWSTAM), INREG(IER), INREG(IMR), INREG(IIR));
acthd = INREG(ACTHD);
acthd = INREG(ACTHD_I965);
ErrorF("acthd: 0x%08x dma_fadd_p: 0x%08x\n",
acthd, INREG(DMA_FADD_P));
ErrorF("ecoskpd: 0x%08x excc: 0x%08x\n",

View File

@ -65,6 +65,9 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
#include <stdio.h>
#include <string.h>
#include <assert.h>
#include <sys/types.h>
#include <sys/ioctl.h>
#include <errno.h>
#include "xf86.h"
#include "xf86_OSproc.h"
@ -83,23 +86,6 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
#include "i915_drm.h"
/* This block and the corresponding configure test can be removed when
* libdrm >= 2.3.1 is required.
*/
#ifndef HAVE_I915_FLIP
#define DRM_VBLANK_FLIP 0x8000000
typedef struct drm_i915_flip {
int pipes;
} drm_i915_flip_t;
#undef DRM_IOCTL_I915_FLIP
#define DRM_IOCTL_I915_FLIP DRM_IOW(DRM_COMMAND_BASE + DRM_I915_FLIP, \
drm_i915_flip_t)
#endif
#include "dristruct.h"
static Bool I830InitVisualConfigs(ScreenPtr pScreen);
@ -172,22 +158,31 @@ I830InitDma(ScrnInfoPtr pScrn)
memset(&info, 0, sizeof(drmI830Init));
info.func = I830_INIT_DMA;
info.ring_start = ring->mem->offset + pI830->LinearAddr;
info.ring_end = ring->mem->end + pI830->LinearAddr;
info.ring_size = ring->mem->size;
/* Initialize fields that are used in the absence of GEM */
if (!pI830->memory_manager) {
info.ring_start = ring->mem->offset + pI830->LinearAddr;
info.ring_end = ring->mem->end + pI830->LinearAddr;
info.ring_size = ring->mem->size;
/* Not used as of the middle of GEM development. */
info.mmio_offset = (unsigned int)pI830DRI->regs;
/* Not used as of before GEM development */
info.front_offset = pI830->front_buffer->offset;
info.back_offset = pI830->back_buffer->offset;
info.depth_offset = pI830->depth_buffer->offset;
info.pitch = pScrn->displayWidth;
info.back_pitch = pScrn->displayWidth;
info.depth_pitch = pScrn->displayWidth;
info.w = pScrn->virtualX;
info.h = pScrn->virtualY;
}
info.mmio_offset = (unsigned int)pI830DRI->regs;
info.sarea_priv_offset = sizeof(XF86DRISAREARec);
info.front_offset = pI830->front_buffer->offset;
info.back_offset = pI830->back_buffer->offset;
info.depth_offset = pI830->depth_buffer->offset;
info.w = pScrn->virtualX;
info.h = pScrn->virtualY;
info.pitch = pScrn->displayWidth;
info.back_pitch = pScrn->displayWidth;
info.depth_pitch = pScrn->displayWidth;
/* This should probably have been moved alongside offset/pitch in the sarea.
*/
info.cpp = pI830->cpp;
if (drmCommandWrite(pI830->drmSubFD, DRM_I830_INIT,
@ -594,7 +589,7 @@ I830DRIScreenInit(ScreenPtr pScreen)
#if DRIINFO_MAJOR_VERSION > 5 || \
(DRIINFO_MAJOR_VERSION == 5 && DRIINFO_MINOR_VERSION >= 3)
if (pI830->useEXA)
if (pI830->accel == ACCEL_EXA)
pDRIInfo->texOffsetStart = I830TexOffsetStart;
#endif
@ -796,17 +791,20 @@ I830DRIDoMappings(ScreenPtr pScreen)
xf86DrvMsg(pScreen->myNum, X_INFO, "[drm] Registers = 0x%08x\n",
(int)pI830DRI->regs);
if (drmAddMap(pI830->drmSubFD,
(drm_handle_t)pI830->LpRing->mem->offset + pI830->LinearAddr,
pI830->LpRing->mem->size, DRM_AGP, 0,
(drmAddress) &pI830->ring_map) < 0) {
xf86DrvMsg(pScreen->myNum, X_ERROR,
"[drm] drmAddMap(ring_map) failed. Disabling DRI\n");
DRICloseScreen(pScreen);
return FALSE;
if (!pI830->memory_manager) {
if (drmAddMap(pI830->drmSubFD,
(drm_handle_t)pI830->LpRing->mem->offset +
pI830->LinearAddr,
pI830->LpRing->mem->size, DRM_AGP, 0,
(drmAddress) &pI830->ring_map) < 0) {
xf86DrvMsg(pScreen->myNum, X_ERROR,
"[drm] drmAddMap(ring_map) failed. Disabling DRI\n");
DRICloseScreen(pScreen);
return FALSE;
}
xf86DrvMsg(pScreen->myNum, X_INFO, "[drm] ring buffer = 0x%08x\n",
(int)pI830->ring_map);
}
xf86DrvMsg(pScreen->myNum, X_INFO, "[drm] ring buffer = 0x%08x\n",
(int)pI830->ring_map);
if (!I830InitDma(pScrn)) {
DRICloseScreen(pScreen);
@ -957,6 +955,7 @@ I830DRICloseScreen(ScreenPtr pScreen)
xfree(pI830->pVisualConfigs);
if (pI830->pVisualConfigsPriv)
xfree(pI830->pVisualConfigsPriv);
pI830->directRenderingEnabled = FALSE;
}
static Bool
@ -1071,9 +1070,8 @@ I830DRISwapContext(ScreenPtr pScreen, DRISyncType syncType,
if (!pScrn->vtSema)
return;
pI830->LockHeld = 1;
i830_refresh_ring(pScrn);
I830EmitFlush(pScrn);
if (!pI830->memory_manager)
i830_refresh_ring(pScrn);
#ifdef DAMAGE
if (!pI830->pDamage && pI830->allowPageFlip) {
@ -1128,8 +1126,6 @@ I830DRISwapContext(ScreenPtr pScreen, DRISyncType syncType,
}
#endif
I830EmitFlush(pScrn);
#ifdef DAMAGE
/* Try flipping back to the front page if necessary */
if (sPriv && !sPriv->pf_enabled && sPriv->pf_current_page != 0) {
@ -1515,6 +1511,27 @@ I830DRIClipNotify(ScreenPtr pScreen, WindowPtr *ppWin, int num)
}
#endif /* DRI_SUPPORTS_CLIP_NOTIFY */
static int
i830_name_buffer (ScrnInfoPtr pScrn, i830_memory *mem)
{
if (mem && mem->bo)
{
if (!mem->gem_name)
{
int ret;
ret = intel_bo_flink(mem->bo, &mem->gem_name);
if (ret != 0)
{
xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
"[drm] failed to name buffer %d\n", -errno);
return -1;
}
}
return mem->gem_name;
}
return -1;
}
/**
* Update the SAREA fields with current buffer information.
*
@ -1546,20 +1563,10 @@ i830_update_sarea(ScrnInfoPtr pScrn, drmI830Sarea *sarea)
sarea->log_tex_granularity = pI830->TexGranularity;
sarea->front_bo_handle = -1;
sarea->back_bo_handle = -1;
sarea->third_bo_handle = -1;
sarea->depth_bo_handle = -1;
#ifdef XF86DRI_MM
if (pI830->front_buffer->bo.size)
sarea->front_bo_handle = pI830->front_buffer->bo.handle;
if (pI830->back_buffer->bo.size)
sarea->back_bo_handle = pI830->back_buffer->bo.handle;
if (pI830->third_buffer != NULL && pI830->third_buffer->bo.size)
sarea->third_bo_handle = pI830->third_buffer->bo.handle;
if (pI830->depth_buffer->bo.size)
sarea->depth_bo_handle = pI830->depth_buffer->bo.handle;
#endif
sarea->front_bo_handle = i830_name_buffer (pScrn, pI830->front_buffer);
sarea->back_bo_handle = i830_name_buffer (pScrn, pI830->back_buffer);
sarea->third_bo_handle = i830_name_buffer (pScrn, pI830->third_buffer);
sarea->depth_bo_handle = i830_name_buffer (pScrn, pI830->depth_buffer);
/* The rotation is now handled entirely by the X Server, so just leave the
* DRI unaware.
@ -1755,7 +1762,8 @@ I830DRILock(ScrnInfoPtr pScrn)
if (pI830->directRenderingEnabled && !pI830->LockHeld) {
DRILock(screenInfo.screens[pScrn->scrnIndex], 0);
pI830->LockHeld = 1;
i830_refresh_ring(pScrn);
if (!pI830->memory_manager)
i830_refresh_ring(pScrn);
return TRUE;
}
else

View File

@ -59,5 +59,4 @@ typedef struct {
int dummy;
} I830DRIContextRec, *I830DRIContextPtr;
#endif

View File

@ -209,9 +209,7 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
#ifdef XF86DRI
#include "dri.h"
#include <sys/ioctl.h>
#ifdef XF86DRI_MM
#include "xf86mm.h"
#endif
#include "i915_drm.h"
#endif
#ifdef I830_USE_EXA
@ -292,9 +290,7 @@ static PciChipsets I830PciChipsets[] = {
*/
typedef enum {
#if defined(I830_USE_XAA) && defined(I830_USE_EXA)
OPTION_ACCELMETHOD,
#endif
OPTION_NOACCEL,
OPTION_SW_CURSOR,
OPTION_CACHE_LINES,
@ -308,7 +304,7 @@ typedef enum {
OPTION_LVDS24BITMODE,
OPTION_FBC,
OPTION_TILING,
#ifdef XF86DRI_MM
#ifdef XF86DRI
OPTION_INTELTEXPOOL,
#endif
OPTION_LVDSFIXEDMODE,
@ -320,9 +316,7 @@ typedef enum {
} I830Opts;
static OptionInfoRec I830Options[] = {
#if defined(I830_USE_XAA) && defined(I830_USE_EXA)
{OPTION_ACCELMETHOD, "AccelMethod", OPTV_ANYSTR, {0}, FALSE},
#endif
{OPTION_NOACCEL, "NoAccel", OPTV_BOOLEAN, {0}, FALSE},
{OPTION_SW_CURSOR, "SWcursor", OPTV_BOOLEAN, {0}, FALSE},
{OPTION_CACHE_LINES, "CacheLines", OPTV_INTEGER, {0}, FALSE},
@ -336,7 +330,7 @@ static OptionInfoRec I830Options[] = {
{OPTION_LVDS24BITMODE, "LVDS24Bit", OPTV_BOOLEAN, {0}, FALSE},
{OPTION_FBC, "FramebufferCompression", OPTV_BOOLEAN, {0}, TRUE},
{OPTION_TILING, "Tiling", OPTV_BOOLEAN, {0}, TRUE},
#ifdef XF86DRI_MM
#ifdef XF86DRI
{OPTION_INTELTEXPOOL,"Legacy3D", OPTV_BOOLEAN, {0}, FALSE},
#endif
{OPTION_LVDSFIXEDMODE, "LVDSFixedMode", OPTV_BOOLEAN, {0}, FALSE},
@ -855,7 +849,7 @@ i830_update_front_offset(ScrnInfoPtr pScrn)
/* If we are still in ScreenInit, there is no screen pixmap to be updated
* yet. We'll fix it up at CreateScreenResources.
*/
if (!pI830->starting) {
if (!pI830->starting && pI830->accel != ACCEL_UXA) {
if (!pScreen->ModifyPixmapHeader(pScreen->GetScreenPixmap(pScreen),
-1, -1, -1, -1, -1,
(pointer)(pI830->FbBase +
@ -882,6 +876,10 @@ i830CreateScreenResources(ScreenPtr pScreen)
i830_update_front_offset(pScrn);
#ifdef I830_USE_UXA
if (pI830->accel == ACCEL_UXA)
i830_uxa_create_screen_resources(pScreen);
#endif
return TRUE;
}
@ -1340,6 +1338,15 @@ i830_detect_chipset(ScrnInfoPtr pScrn)
return TRUE;
}
static const char *accel_name[] =
{
"unspecified",
"no",
"XAA",
"EXA",
"UXA",
};
/**
* This is called per zaphod head (so usually just once) to do initialization
* before the Screen is created.
@ -1556,7 +1563,7 @@ I830PreInit(ScrnInfoPtr pScrn, int flags)
num_pipe, num_pipe > 1 ? "s" : "");
if (xf86ReturnOptValBool(pI830->Options, OPTION_NOACCEL, FALSE)) {
pI830->noAccel = TRUE;
pI830->accel = ACCEL_NONE;
}
/*
@ -1570,29 +1577,38 @@ I830PreInit(ScrnInfoPtr pScrn, int flags)
* All this *could* go away if we removed XAA support from this driver,
* for example. :)
*/
if (!pI830->noAccel) {
#ifdef I830_USE_EXA
pI830->useEXA = TRUE;
#else
pI830->useEXA = FALSE;
if (pI830->accel == ACCEL_UNINIT) {
pI830->accel = ACCEL_NONE;
#ifdef I830_USE_XAA
pI830->accel = ACCEL_XAA;
#endif
#if defined(I830_USE_XAA) && defined(I830_USE_EXA)
#ifdef I830_USE_UXA
pI830->accel = ACCEL_UXA;
#endif
#ifdef I830_USE_EXA
pI830->accel = ACCEL_EXA;
#endif
#if I830_USE_XAA + I830_USE_EXA + I830_USE_UXA >= 2
from = X_DEFAULT;
if ((s = (char *)xf86GetOptValString(pI830->Options,
OPTION_ACCELMETHOD))) {
if (!xf86NameCmp(s, "EXA")) {
from = X_CONFIG;
pI830->useEXA = TRUE;
pI830->accel = ACCEL_EXA;
}
else if (!xf86NameCmp(s, "XAA")) {
from = X_CONFIG;
pI830->useEXA = FALSE;
pI830->accel = ACCEL_XAA;
}
else if (!xf86NameCmp(s, "UXA")) {
from = X_CONFIG;
pI830->accel = ACCEL_UXA;
}
}
#endif
xf86DrvMsg(pScrn->scrnIndex, from, "Using %s for acceleration\n",
pI830->useEXA ? "EXA" : "XAA");
}
xf86DrvMsg(pScrn->scrnIndex, from, "Using %s acceleration\n",
accel_name[pI830->accel]);
if (xf86ReturnOptValBool(pI830->Options, OPTION_SW_CURSOR, FALSE)) {
pI830->SWCursor = TRUE;
@ -1603,7 +1619,7 @@ I830PreInit(ScrnInfoPtr pScrn, int flags)
#ifdef XF86DRI
if (!pI830->directRenderingDisabled) {
if (pI830->noAccel || pI830->SWCursor) {
if (pI830->accel == ACCEL_NONE || pI830->SWCursor) {
xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "DRI is disabled because it "
"needs HW cursor and 2D acceleration.\n");
pI830->directRenderingDisabled = TRUE;
@ -1618,7 +1634,7 @@ I830PreInit(ScrnInfoPtr pScrn, int flags)
from = X_PROBED;
#ifdef XF86DRI_MM
#ifdef XF86DRI
if (!IS_I965G(pI830)) {
Bool tmp;
@ -1780,7 +1796,7 @@ I830PreInit(ScrnInfoPtr pScrn, int flags)
if (!IS_I965G(pI830) && pScrn->virtualY > 2048) {
xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Cannot support > 2048 vertical lines. disabling acceleration.\n");
pI830->noAccel = TRUE;
pI830->accel = ACCEL_NONE;
}
/* Set display resolution */
@ -1794,18 +1810,19 @@ I830PreInit(ScrnInfoPtr pScrn, int flags)
xf86LoaderReqSymLists(I810fbSymbols, NULL);
switch (pI830->accel) {
#ifdef I830_USE_XAA
if (!pI830->noAccel && !pI830->useEXA) {
case ACCEL_XAA:
if (!xf86LoadSubModule(pScrn, "xaa")) {
PreInitCleanup(pScrn);
return FALSE;
}
xf86LoaderReqSymLists(I810xaaSymbols, NULL);
}
break;
#endif
#ifdef I830_USE_EXA
if (!pI830->noAccel && pI830->useEXA) {
case ACCEL_EXA: {
XF86ModReqInfo req;
int errmaj, errmin;
@ -1823,8 +1840,12 @@ I830PreInit(ScrnInfoPtr pScrn, int flags)
return FALSE;
}
xf86LoaderReqSymLists(I830exaSymbols, NULL);
break;
}
#endif
default:
break;
}
if (!pI830->SWCursor) {
if (!xf86LoadSubModule(pScrn, "ramdac")) {
PreInitCleanup(pScrn);
@ -1884,11 +1905,11 @@ i830_stop_ring(ScrnInfoPtr pScrn, Bool flush)
pI830->entityPrivate->RingRunning = 0;
/* Flush the ring buffer (if enabled), then disable it. */
if (!pI830->noAccel) {
if (pI830->accel != ACCEL_NONE) {
temp = INREG(LP_RING + RING_LEN);
if (temp & RING_VALID) {
i830_refresh_ring(pScrn);
I830Sync(pScrn);
i830_wait_ring_idle(pScrn);
}
OUTREG(LP_RING + RING_LEN, 0);
@ -1906,7 +1927,7 @@ i830_start_ring(ScrnInfoPtr pScrn)
DPRINTF(PFX, "SetRingRegs\n");
if (pI830->noAccel)
if (pI830->accel == ACCEL_NONE)
return;
if (!I830IsPrimary(pScrn)) return;
@ -2447,7 +2468,7 @@ IntelEmitInvarientState(ScrnInfoPtr pScrn)
I830Ptr pI830 = I830PTR(pScrn);
uint32_t ctx_addr;
if (pI830->noAccel)
if (pI830->accel == ACCEL_NONE)
return;
#ifdef XF86DRI
@ -2502,15 +2523,31 @@ I830BlockHandler(int i,
pI830->BlockHandler = pScreen->BlockHandler;
pScreen->BlockHandler = I830BlockHandler;
/* Emit a flush of the rendering cache, or on the 965 and beyond
* rendering results may not hit the framebuffer until significantly
* later. In the direct rendering case this is already done just
* after the page flipping updates, so there's no need to duplicate
* the effort here.
*/
if (pScrn->vtSema && !pI830->noAccel && !pI830->directRenderingEnabled)
I830EmitFlush(pScrn);
if (pScrn->vtSema && pI830->accel != ACCEL_NONE) {
/* Emit a flush of the rendering cache, or on the 965 and beyond
* rendering results may not hit the framebuffer until significantly
* later.
*/
if (pI830->accel != ACCEL_NONE && (pI830->need_mi_flush || pI830->batch_used))
I830EmitFlush(pScrn);
/* Flush the batch, so that any rendering is executed in a timely
* fashion.
*/
intel_batch_flush(pScrn);
#ifdef XF86DRI
if (pI830->memory_manager)
drmCommandNone(pI830->drmSubFD, DRM_I915_GEM_THROTTLE);
#endif
pI830->need_mi_flush = FALSE;
#ifdef XF86DRI
drmCommandNone(pI830->drmSubFD, DRM_I915_GEM_THROTTLE);
#endif
}
if (pI830->accel == ACCEL_UXA)
i830_uxa_block_handler (pScreen);
/*
* Check for FIFO underruns at block time (which amounts to just
* periodically). If this happens, it means our DSPARB or some other
@ -2718,6 +2755,70 @@ i830_memory_init(ScrnInfoPtr pScrn)
return FALSE;
}
/**
* Returns a cookie to be waited on. This is just a stub implementation, and
* should be hooked up to the emit/wait irq functions when available (DRI
* enabled).
*/
static unsigned int
i830_fake_fence_emit(void *priv)
{
static unsigned int fence = 0;
/* Match DRM in not using half the range. The fake bufmgr relies on this. */
if (++fence >= 0x8000000)
fence = 1;
return fence;
}
/**
* Waits on a cookie representing a request to be passed.
*
* Stub implementation that should be replaced with DRM functions when
* available.
*/
static int
i830_fake_fence_wait(void *priv, unsigned int fence)
{
ScrnInfoPtr pScrn = priv;
i830_wait_ring_idle(pScrn);
return 0;
}
void
i830_init_bufmgr(ScrnInfoPtr pScrn)
{
I830Ptr pI830 = I830PTR(pScrn);
if (pI830->bufmgr) return;
if (pI830->memory_manager) {
int batch_size;
batch_size = 4096 * 4;
/* The 865 has issues with larger-than-page-sized batch buffers. */
if (IS_I865G(pI830))
batch_size = 4096;
pI830->bufmgr = intel_bufmgr_gem_init(pI830->drmSubFD, batch_size);
intel_bufmgr_gem_enable_reuse(pI830->bufmgr);
} else {
assert(pI830->FbBase != NULL);
pI830->bufmgr = intel_bufmgr_fake_init(pI830->fake_bufmgr_mem->offset,
pI830->FbBase +
pI830->fake_bufmgr_mem->offset,
pI830->fake_bufmgr_mem->size,
i830_fake_fence_emit,
i830_fake_fence_wait,
pScrn);
}
}
static Bool
I830ScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv)
{
@ -2935,12 +3036,12 @@ I830ScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv)
pI830->XvEnabled = !pI830->XvDisabled;
if (pI830->XvEnabled) {
if (!I830IsPrimary(pScrn)) {
if (!pI8301->XvEnabled || pI830->noAccel) {
if (!pI8301->XvEnabled || pI830->accel == ACCEL_NONE) {
pI830->XvEnabled = FALSE;
xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Xv is disabled.\n");
}
} else
if (pI830->noAccel || pI830->StolenOnly) {
if (pI830->accel == ACCEL_NONE || pI830->StolenOnly) {
xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Xv is disabled because it "
"needs 2D accel and AGPGART.\n");
pI830->XvEnabled = FALSE;
@ -2950,18 +3051,18 @@ I830ScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv)
pI830->XvEnabled = FALSE;
#endif
if (!pI830->noAccel) {
if (pI830->LpRing->mem->size == 0) {
if (pI830->accel != ACCEL_NONE) {
if (pI830->memory_manager == NULL && pI830->LpRing->mem->size == 0) {
xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
"Disabling acceleration because the ring buffer "
"allocation failed.\n");
pI830->noAccel = TRUE;
pI830->accel = ACCEL_NONE;
}
}
#ifdef I830_XV
if (pI830->XvEnabled) {
if (pI830->noAccel) {
if (pI830->accel == ACCEL_NONE) {
xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Disabling Xv because it "
"needs 2D acceleration.\n");
pI830->XvEnabled = FALSE;
@ -2983,7 +3084,7 @@ I830ScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv)
*/
if (pI830->directRenderingEnabled) {
if (pI830->noAccel || pI830->SWCursor || (pI830->StolenOnly && I830IsPrimary(pScrn))) {
if (pI830->accel == ACCEL_NONE || pI830->SWCursor || (pI830->StolenOnly && I830IsPrimary(pScrn))) {
xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "DRI is disabled because it "
"needs HW cursor, 2D accel and AGPGART.\n");
pI830->directRenderingEnabled = FALSE;
@ -3047,6 +3148,8 @@ I830ScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv)
pI830->xoffset = (pScrn->fbOffset / pI830->cpp) % pScrn->displayWidth;
pI830->yoffset = (pScrn->fbOffset / pI830->cpp) / pScrn->displayWidth;
i830_init_bufmgr(pScrn);
vgaHWSetMmioFuncs(hwp, pI830->MMIOBase, 0);
vgaHWGetIOBase(hwp);
DPRINTF(PFX, "assert( if(!vgaHWMapMem(pScrn)) )\n");
@ -3055,7 +3158,7 @@ I830ScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv)
DPRINTF(PFX, "assert( if(!I830EnterVT(scrnIndex, 0)) )\n");
if (!pI830->useEXA) {
if (pI830->accel <= ACCEL_XAA) {
if (I830IsPrimary(pScrn)) {
if (!I830InitFBManager(pScreen, &(pI830->FbMemBox))) {
xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
@ -3103,7 +3206,7 @@ I830ScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv)
DPRINTF(PFX,
"assert( if(!I830InitFBManager(pScreen, &(pI830->FbMemBox))) )\n");
if (!pI830->noAccel) {
if (pI830->accel != ACCEL_NONE) {
if (!I830AccelInit(pScreen)) {
xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
"Hardware acceleration initialization failed\n");
@ -3290,9 +3393,19 @@ I830LeaveVT(int scrnIndex, int flags)
xf86_hide_cursors (pScrn);
I830Sync(pScrn);
RestoreHWState(pScrn);
i830_stop_ring(pScrn, TRUE);
/* Evict everything from the bufmgr, as we're about to lose ownership of
* the graphics memory.
*/
if (!pI830->memory_manager)
intel_bufmgr_fake_evict_all(pI830->bufmgr);
intel_batch_teardown(pScrn);
if (!pI830->memory_manager)
i830_stop_ring(pScrn, TRUE);
if (pI830->debug_modes) {
i830CompareRegsToSnapshot(pScrn, "After LeaveVT");
@ -3302,18 +3415,20 @@ I830LeaveVT(int scrnIndex, int flags)
if (I830IsPrimary(pScrn))
i830_unbind_all_memory(pScrn);
/* Tell the kernel to evict all buffer objects and block new buffer
* allocations until we relese the lock.
*/
#ifdef XF86DRI_MM
if (pI830->directRenderingOpen) {
if (pI830->memory_manager != NULL && pScrn->vtSema) {
drmMMLock(pI830->drmSubFD, DRM_BO_MEM_TT, 1, 0);
}
}
#endif /* XF86DRI_MM */
#ifdef XF86DRI
if (pI830->memory_manager) {
int ret;
if (pI830->useEXA && IS_I965G(pI830))
/* Tell the kernel to evict all buffer objects and block GTT usage while
* we're no longer in control of the chip.
*/
ret = drmCommandNone(pI830->drmSubFD, DRM_I915_GEM_LEAVEVT);
if (ret != 0)
FatalError("DRM_I915_LEAVEVT failed: %s\n", strerror(ret));
}
#endif /* XF86DRI */
if ((pI830->accel == ACCEL_EXA || pI830->accel == ACCEL_UXA) && IS_I965G(pI830))
gen4_render_state_cleanup(pScrn);
if (pI830->AccelInfoRec)
@ -3342,16 +3457,18 @@ I830EnterVT(int scrnIndex, int flags)
pI830->leaving = FALSE;
#ifdef XF86DRI_MM
if (pI830->directRenderingEnabled) {
/* Unlock the memory manager first of all so that we can pin our
* buffer objects
#ifdef XF86DRI
if (pI830->memory_manager) {
int ret;
/* Tell the kernel that we're back in control and ready for GTT
* usage.
*/
if (pI830->memory_manager != NULL && pScrn->vtSema) {
drmMMUnlock(pI830->drmSubFD, DRM_BO_MEM_TT, 1);
}
ret = drmCommandNone(pI830->drmSubFD, DRM_I915_GEM_ENTERVT);
if (ret != 0)
FatalError("DRM_I915_ENTERVT failed: %s\n", strerror(ret));
}
#endif /* XF86DRI_MM */
#endif /* XF86DRI */
if (I830IsPrimary(pScrn))
if (!i830_bind_all_memory(pScrn))
@ -3362,7 +3479,9 @@ I830EnterVT(int scrnIndex, int flags)
/* Update the screen pixmap in case the buffer moved */
i830_update_front_offset(pScrn);
if (pI830->useEXA && IS_I965G(pI830))
intel_batch_init(pScrn);
if ((pI830->accel == ACCEL_EXA || pI830->accel == ACCEL_UXA) && IS_I965G(pI830))
gen4_render_state_init(pScrn);
if (i830_check_error_state(pScrn)) {
@ -3370,8 +3489,11 @@ I830EnterVT(int scrnIndex, int flags)
"Existing errors found in hardware state.\n");
}
i830_stop_ring(pScrn, FALSE);
i830_start_ring(pScrn);
/* Re-set up the ring. */
if (!pI830->memory_manager) {
i830_stop_ring(pScrn, FALSE);
i830_start_ring(pScrn);
}
if (!pI830->SWCursor)
I830InitHWCursor(pScrn);
@ -3402,7 +3524,7 @@ I830EnterVT(int scrnIndex, int flags)
* operation which accessing that page, like irq install, etc.
*/
if (pI830->starting) {
if (HWS_NEED_GFX(pI830) && !I830DRISetHWS(pScrn)) {
if (pI830->hw_status != NULL && !I830DRISetHWS(pScrn)) {
xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
"Fail to setup hardware status page.\n");
I830DRICloseScreen(pScrn->pScreen);
@ -3429,7 +3551,8 @@ I830EnterVT(int scrnIndex, int flags)
I830DRIResume(screenInfo.screens[scrnIndex]);
i830_refresh_ring(pScrn);
if (!pI830->memory_manager)
i830_refresh_ring(pScrn);
I830Sync(pScrn);
sarea->texAge++;
@ -3482,16 +3605,11 @@ I830CloseScreen(int scrnIndex, ScreenPtr pScreen)
if (pScrn->vtSema == TRUE) {
I830LeaveVT(scrnIndex, 0);
#ifdef XF86DRI_MM
if (pI830->directRenderingEnabled) {
if (pI830->memory_manager != NULL) {
drmMMUnlock(pI830->drmSubFD, DRM_BO_MEM_TT, 1);
}
}
#endif /* XF86DRI_MM */
}
dri_bufmgr_destroy(pI830->bufmgr);
pI830->bufmgr = NULL;
if (pI830->devicesTimer)
TimerCancel(pI830->devicesTimer);
pI830->devicesTimer = NULL;
@ -3513,11 +3631,18 @@ I830CloseScreen(int scrnIndex, ScreenPtr pScreen)
}
#endif
#ifdef I830_USE_EXA
if (pI830->useEXA && pI830->EXADriverPtr) {
if (pI830->EXADriverPtr) {
exaDriverFini(pScreen);
xfree(pI830->EXADriverPtr);
pI830->EXADriverPtr = NULL;
}
#endif
#ifdef I830_USE_UXA
if (pI830->uxa_driver) {
uxa_driver_fini (pScreen);
xfree (pI830->uxa_driver);
pI830->uxa_driver = NULL;
}
#endif
xf86_cursors_fini (pScreen);
@ -3747,19 +3872,34 @@ i830WaitSync(ScrnInfoPtr pScrn)
{
I830Ptr pI830 = I830PTR(pScrn);
switch (pI830->accel) {
#ifdef I830_USE_XAA
if (!pI830->noAccel && !pI830->useEXA && pI830->AccelInfoRec
&& pI830->AccelInfoRec->NeedToSync) {
(*pI830->AccelInfoRec->Sync)(pScrn);
pI830->AccelInfoRec->NeedToSync = FALSE;
}
case ACCEL_XAA:
if (pI830->AccelInfoRec && pI830->AccelInfoRec->NeedToSync) {
(*pI830->AccelInfoRec->Sync)(pScrn);
pI830->AccelInfoRec->NeedToSync = FALSE;
}
break;
#endif
#ifdef I830_USE_EXA
if (!pI830->noAccel && pI830->useEXA && pI830->EXADriverPtr) {
ScreenPtr pScreen = screenInfo.screens[pScrn->scrnIndex];
exaWaitSync(pScreen);
}
case ACCEL_EXA:
if (pI830->EXADriverPtr) {
ScreenPtr pScreen = screenInfo.screens[pScrn->scrnIndex];
exaWaitSync(pScreen);
}
break;
#endif
#ifdef I830_USE_UXA
case ACCEL_UXA:
if (pI830->uxa_driver && pI830->need_sync) {
pI830->need_sync = FALSE;
I830Sync(pScrn);
}
break;
#endif
default:
break;
}
}
void
@ -3767,16 +3907,30 @@ i830MarkSync(ScrnInfoPtr pScrn)
{
I830Ptr pI830 = I830PTR(pScrn);
switch (pI830->accel) {
#ifdef I830_USE_XAA
if (!pI830->useEXA && pI830->AccelInfoRec)
pI830->AccelInfoRec->NeedToSync = TRUE;
case ACCEL_XAA:
if (pI830->AccelInfoRec)
pI830->AccelInfoRec->NeedToSync = TRUE;
break;
#endif
#ifdef I830_USE_EXA
if (pI830->useEXA && pI830->EXADriverPtr) {
ScreenPtr pScreen = screenInfo.screens[pScrn->scrnIndex];
exaMarkSync(pScreen);
}
case ACCEL_EXA:
if (pI830->EXADriverPtr) {
ScreenPtr pScreen = screenInfo.screens[pScrn->scrnIndex];
exaMarkSync(pScreen);
}
break;
#endif
#ifdef I830_USE_UXA
case ACCEL_UXA:
if (pI830->uxa_driver)
pI830->need_sync = TRUE;
break;
#endif
default:
break;
}
}
void

View File

@ -42,6 +42,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#endif
#define ALWAYS_SYNC 0
#define ALWAYS_FLUSH 0
#ifdef DEBUG_I830FALLBACK
#define I830FALLBACK(s, arg...) \
@ -121,6 +122,21 @@ i830_pixmap_tiled(PixmapPtr pPixmap)
return FALSE;
}
static unsigned long
i830_pixmap_pitch(PixmapPtr pixmap)
{
return pixmap->devKind;
}
static int
i830_pixmap_pitch_is_aligned(PixmapPtr pixmap)
{
ScrnInfoPtr pScrn = xf86Screens[pixmap->drawable.pScreen->myNum];
I830Ptr pI830 = I830PTR(pScrn);
return i830_pixmap_pitch(pixmap) % pI830->accel_pixmap_pitch_alignment == 0;
}
static Bool
i830_exa_pixmap_is_offscreen(PixmapPtr pPixmap)
{
@ -162,7 +178,7 @@ I830EXAPrepareSolid(PixmapPtr pPixmap, int alu, Pixel planemask, Pixel fg)
{
ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum];
I830Ptr pI830 = I830PTR(pScrn);
unsigned long offset, pitch;
unsigned long pitch;
if (!EXA_PM_IS_SOLID(&pPixmap->drawable, planemask))
I830FALLBACK("planemask is not solid");
@ -172,12 +188,9 @@ I830EXAPrepareSolid(PixmapPtr pPixmap, int alu, Pixel planemask, Pixel fg)
i830_exa_check_pitch_2d(pPixmap);
offset = exaGetPixmapOffset(pPixmap);
pitch = exaGetPixmapPitch(pPixmap);
pitch = i830_pixmap_pitch(pPixmap);
if (offset % pI830->EXADriverPtr->pixmapOffsetAlign != 0)
I830FALLBACK("pixmap offset not aligned");
if (pitch % pI830->EXADriverPtr->pixmapPitchAlign != 0)
if (!i830_pixmap_pitch_is_aligned(pPixmap))
I830FALLBACK("pixmap pitch not aligned");
pI830->BR[13] = (I830PatternROP[alu] & 0xff) << 16 ;
@ -202,11 +215,10 @@ I830EXASolid(PixmapPtr pPixmap, int x1, int y1, int x2, int y2)
{
ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum];
I830Ptr pI830 = I830PTR(pScrn);
unsigned long offset, pitch;
unsigned long pitch;
uint32_t cmd;
offset = exaGetPixmapOffset(pPixmap);
pitch = exaGetPixmapPitch(pPixmap);
pitch = i830_pixmap_pitch(pPixmap);
{
BEGIN_BATCH(6);
@ -227,7 +239,7 @@ I830EXASolid(PixmapPtr pPixmap, int x1, int y1, int x2, int y2)
OUT_BATCH(pI830->BR[13] | pitch);
OUT_BATCH((y1 << 16) | (x1 & 0xffff));
OUT_BATCH((y2 << 16) | (x2 & 0xffff));
OUT_BATCH(offset);
OUT_RELOC_PIXMAP(pPixmap, I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER, 0);
OUT_BATCH(pI830->BR[16]);
ADVANCE_BATCH();
}
@ -236,11 +248,16 @@ I830EXASolid(PixmapPtr pPixmap, int x1, int y1, int x2, int y2)
static void
I830EXADoneSolid(PixmapPtr pPixmap)
{
#if ALWAYS_SYNC
#if ALWAYS_SYNC || ALWAYS_FLUSH || 1
ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum];
#if ALWAYS_FLUSH || 1
intel_batch_flush(pScrn);
#endif
#if ALWAYS_SYNC
I830Sync(pScrn);
#endif
#endif
}
/**
@ -285,15 +302,13 @@ I830EXACopy(PixmapPtr pDstPixmap, int src_x1, int src_y1, int dst_x1,
I830Ptr pI830 = I830PTR(pScrn);
uint32_t cmd;
int dst_x2, dst_y2;
unsigned int dst_off, dst_pitch, src_off, src_pitch;
unsigned int dst_pitch, src_pitch;
dst_x2 = dst_x1 + w;
dst_y2 = dst_y1 + h;
dst_off = exaGetPixmapOffset(pDstPixmap);
dst_pitch = exaGetPixmapPitch(pDstPixmap);
src_off = exaGetPixmapOffset(pI830->pSrcPixmap);
src_pitch = exaGetPixmapPitch(pI830->pSrcPixmap);
dst_pitch = i830_pixmap_pitch(pDstPixmap);
src_pitch = i830_pixmap_pitch(pI830->pSrcPixmap);
{
BEGIN_BATCH(8);
@ -322,10 +337,10 @@ I830EXACopy(PixmapPtr pDstPixmap, int src_x1, int src_y1, int dst_x1,
OUT_BATCH(pI830->BR[13] | dst_pitch);
OUT_BATCH((dst_y1 << 16) | (dst_x1 & 0xffff));
OUT_BATCH((dst_y2 << 16) | (dst_x2 & 0xffff));
OUT_BATCH(dst_off);
OUT_RELOC_PIXMAP(pDstPixmap, I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER, 0);
OUT_BATCH((src_y1 << 16) | (src_x1 & 0xffff));
OUT_BATCH(src_pitch);
OUT_BATCH(src_off);
OUT_RELOC_PIXMAP(pI830->pSrcPixmap, I915_GEM_DOMAIN_RENDER, 0, 0);
ADVANCE_BATCH();
}
@ -334,11 +349,37 @@ I830EXACopy(PixmapPtr pDstPixmap, int src_x1, int src_y1, int dst_x1,
static void
I830EXADoneCopy(PixmapPtr pDstPixmap)
{
#if ALWAYS_SYNC
#if ALWAYS_SYNC || ALWAYS_FLUSH
ScrnInfoPtr pScrn = xf86Screens[pDstPixmap->drawable.pScreen->myNum];
#if ALWAYS_FLUSH
intel_batch_flush(pScrn);
#endif
#if ALWAYS_SYNC
I830Sync(pScrn);
#endif
#endif
}
/**
* Do any cleanup from the Composite operation.
*
* This is shared between i830 through i965.
*/
void
i830_done_composite(PixmapPtr pDst)
{
#if ALWAYS_SYNC || ALWAYS_FLUSH
ScrnInfoPtr pScrn = xf86Screens[pDst->drawable.pScreen->myNum];
#if ALWAYS_FLUSH
intel_batch_flush(pScrn);
#endif
#if ALWAYS_SYNC
I830Sync(pScrn);
#endif
#endif
}
#define xFixedToFloat(val) \
@ -436,7 +477,7 @@ I830EXAInit(ScreenPtr pScreen)
pI830->EXADriverPtr = exaDriverAlloc();
if (pI830->EXADriverPtr == NULL) {
pI830->noAccel = TRUE;
pI830->accel = ACCEL_NONE;
return FALSE;
}
memset(pI830->EXADriverPtr, 0, sizeof(*pI830->EXADriverPtr));
@ -472,55 +513,10 @@ I830EXAInit(ScreenPtr pScreen)
pI830->EXADriverPtr->offScreenBase,
pI830->EXADriverPtr->memorySize);
/* Limits are described in the BLT engine chapter under Graphics Data Size
* Limitations, and the descriptions of SURFACE_STATE, 3DSTATE_BUFFER_INFO,
* 3DSTATE_DRAWING_RECTANGLE, 3DSTATE_MAP_INFO, and 3DSTATE_MAP_INFO.
*
* i845 through i965 limits 2D rendering to 65536 lines and pitch of 32768.
*
* i965 limits 3D surface to (2*element size)-aligned offset if un-tiled.
* i965 limits 3D surface to 4kB-aligned offset if tiled.
* i965 limits 3D surfaces to w,h of ?,8192.
* i965 limits 3D surface to pitch of 1B - 128kB.
* i965 limits 3D surface pitch alignment to 1 or 2 times the element size.
* i965 limits 3D surface pitch alignment to 512B if tiled.
* i965 limits 3D destination drawing rect to w,h of 8192,8192.
*
* i915 limits 3D textures to 4B-aligned offset if un-tiled.
* i915 limits 3D textures to ~4kB-aligned offset if tiled.
* i915 limits 3D textures to width,height of 2048,2048.
* i915 limits 3D textures to pitch of 16B - 8kB, in dwords.
* i915 limits 3D destination to ~4kB-aligned offset if tiled.
* i915 limits 3D destination to pitch of 16B - 8kB, in dwords, if un-tiled.
* i915 limits 3D destination to pitch of 512B - 8kB, in tiles, if tiled.
* i915 limits 3D destination to POT aligned pitch if tiled.
* i915 limits 3D destination drawing rect to w,h of 2048,2048.
*
* i845 limits 3D textures to 4B-aligned offset if un-tiled.
* i845 limits 3D textures to ~4kB-aligned offset if tiled.
* i845 limits 3D textures to width,height of 2048,2048.
* i845 limits 3D textures to pitch of 4B - 8kB, in dwords.
* i845 limits 3D destination to 4B-aligned offset if un-tiled.
* i845 limits 3D destination to ~4kB-aligned offset if tiled.
* i845 limits 3D destination to pitch of 8B - 8kB, in dwords.
* i845 limits 3D destination drawing rect to w,h of 2048,2048.
*
* For the tiled issues, the only tiled buffer we draw to should be
* the front, which will have an appropriate pitch/offset already set up,
* so EXA doesn't need to worry.
*/
if (IS_I965G(pI830)) {
pI830->EXADriverPtr->pixmapOffsetAlign = 4 * 2;
pI830->EXADriverPtr->pixmapPitchAlign = 16;
pI830->EXADriverPtr->maxX = 8192;
pI830->EXADriverPtr->maxY = 8192;
} else {
pI830->EXADriverPtr->pixmapOffsetAlign = 4;
pI830->EXADriverPtr->pixmapPitchAlign = 16;
pI830->EXADriverPtr->maxX = 2048;
pI830->EXADriverPtr->maxY = 2048;
}
pI830->EXADriverPtr->pixmapOffsetAlign = pI830->accel_pixmap_offset_alignment;
pI830->EXADriverPtr->pixmapPitchAlign = pI830->accel_pixmap_pitch_alignment;
pI830->EXADriverPtr->maxX = pI830->accel_max_x;
pI830->EXADriverPtr->maxY = pI830->accel_max_y;
/* Sync */
pI830->EXADriverPtr->WaitMarker = I830EXASync;
@ -564,7 +560,7 @@ I830EXAInit(ScreenPtr pScreen)
pI830->EXADriverPtr->exa_minor = 0;
if(!exaDriverInit(pScreen, pI830->EXADriverPtr)) {
xfree(pI830->EXADriverPtr);
pI830->noAccel = TRUE;
pI830->accel = ACCEL_NONE;
return FALSE;
}
}
@ -574,6 +570,206 @@ I830EXAInit(ScreenPtr pScreen)
return TRUE;
}
static DevPrivateKey uxa_pixmap_key = &uxa_pixmap_key;
static void
i830_uxa_set_pixmap_bo (PixmapPtr pixmap, dri_bo *bo)
{
dixSetPrivate(&pixmap->devPrivates, uxa_pixmap_key, bo);
}
dri_bo *
i830_uxa_get_pixmap_bo (PixmapPtr pixmap)
{
return dixLookupPrivate(&pixmap->devPrivates, uxa_pixmap_key);
}
static Bool
i830_uxa_prepare_access (PixmapPtr pixmap, uxa_access_t access)
{
dri_bo *bo = i830_uxa_get_pixmap_bo (pixmap);
if (bo) {
ScreenPtr screen = pixmap->drawable.pScreen;
ScrnInfoPtr scrn = xf86Screens[screen->myNum];
I830Ptr i830 = I830PTR(scrn);
intel_batch_flush(scrn);
if (i830->need_sync) {
I830Sync(scrn);
i830->need_sync = FALSE;
}
if (dri_bo_map (bo, access == UXA_ACCESS_RW) != 0)
return FALSE;
pixmap->devPrivate.ptr = bo->virtual;
}
return TRUE;
}
static void
i830_uxa_finish_access (PixmapPtr pixmap)
{
dri_bo *bo = i830_uxa_get_pixmap_bo (pixmap);
if (bo) {
ScreenPtr screen = pixmap->drawable.pScreen;
ScrnInfoPtr scrn = xf86Screens[screen->myNum];
I830Ptr i830 = I830PTR(scrn);
dri_bo_unmap (bo);
pixmap->devPrivate.ptr = NULL;
if (bo == i830->front_buffer->bo)
i830->need_flush = TRUE;
}
}
void
i830_uxa_block_handler (ScreenPtr screen)
{
ScrnInfoPtr scrn = xf86Screens[screen->myNum];
I830Ptr i830 = I830PTR(scrn);
if (i830->need_flush) {
dri_bo_wait_rendering (i830->front_buffer->bo);
i830->need_flush = FALSE;
}
}
static Bool
i830_uxa_pixmap_is_offscreen(PixmapPtr pixmap)
{
return i830_uxa_get_pixmap_bo (pixmap) != NULL;
}
static PixmapPtr
i830_uxa_create_pixmap (ScreenPtr screen, int w, int h, int depth, unsigned usage)
{
ScrnInfoPtr scrn = xf86Screens[screen->myNum];
I830Ptr i830 = I830PTR(scrn);
dri_bo *bo;
int stride;
PixmapPtr pixmap;
if (w > 32767 || h > 32767)
return NullPixmap;
pixmap = fbCreatePixmap (screen, 0, 0, depth, usage);
if (w && h)
{
stride = ROUND_TO((w * pixmap->drawable.bitsPerPixel + 7) / 8,
i830->accel_pixmap_pitch_alignment);
bo = dri_bo_alloc (i830->bufmgr, "pixmap", stride * h,
i830->accel_pixmap_offset_alignment);
if (!bo) {
fbDestroyPixmap (pixmap);
return NullPixmap;
}
screen->ModifyPixmapHeader (pixmap, w, h, 0, 0, stride, NULL);
i830_uxa_set_pixmap_bo (pixmap, bo);
}
return pixmap;
}
static Bool
i830_uxa_destroy_pixmap (PixmapPtr pixmap)
{
if (pixmap->refcnt == 1) {
dri_bo *bo = i830_uxa_get_pixmap_bo (pixmap);
if (bo)
dri_bo_unreference (bo);
}
fbDestroyPixmap (pixmap);
return TRUE;
}
void i830_uxa_create_screen_resources(ScreenPtr pScreen)
{
ScrnInfoPtr scrn = xf86Screens[pScreen->myNum];
I830Ptr i830 = I830PTR(scrn);
dri_bo *bo = i830->front_buffer->bo;
if (bo != NULL) {
PixmapPtr pixmap = pScreen->GetScreenPixmap(pScreen);
i830_uxa_set_pixmap_bo (pixmap, bo);
}
}
Bool
i830_uxa_init (ScreenPtr pScreen)
{
ScrnInfoPtr scrn = xf86Screens[pScreen->myNum];
I830Ptr i830 = I830PTR(scrn);
if (!dixRequestPrivate(uxa_pixmap_key, 0))
return FALSE;
i830->uxa_driver = uxa_driver_alloc();
if (i830->uxa_driver == NULL) {
i830->accel = ACCEL_NONE;
return FALSE;
}
memset(i830->uxa_driver, 0, sizeof(*i830->uxa_driver));
i830->bufferOffset = 0;
i830->uxa_driver->uxa_major = 1;
i830->uxa_driver->uxa_minor = 0;
/* Solid fill */
i830->uxa_driver->prepare_solid = I830EXAPrepareSolid;
i830->uxa_driver->solid = I830EXASolid;
i830->uxa_driver->done_solid = I830EXADoneSolid;
/* Copy */
i830->uxa_driver->prepare_copy = I830EXAPrepareCopy;
i830->uxa_driver->copy = I830EXACopy;
i830->uxa_driver->done_copy = I830EXADoneCopy;
/* Composite */
if (!IS_I9XX(i830)) {
i830->uxa_driver->check_composite = i830_check_composite;
i830->uxa_driver->prepare_composite = i830_prepare_composite;
i830->uxa_driver->composite = i830_composite;
i830->uxa_driver->done_composite = i830_done_composite;
} else if (IS_I915G(i830) || IS_I915GM(i830) ||
IS_I945G(i830) || IS_I945GM(i830) || IS_G33CLASS(i830))
{
i830->uxa_driver->check_composite = i915_check_composite;
i830->uxa_driver->prepare_composite = i915_prepare_composite;
i830->uxa_driver->composite = i830_composite;
i830->uxa_driver->done_composite = i830_done_composite;
} else {
i830->uxa_driver->check_composite = i965_check_composite;
i830->uxa_driver->prepare_composite = i965_prepare_composite;
i830->uxa_driver->composite = i965_composite;
i830->uxa_driver->done_composite = i830_done_composite;
}
i830->uxa_driver->prepare_access = i830_uxa_prepare_access;
i830->uxa_driver->finish_access = i830_uxa_finish_access;
i830->uxa_driver->pixmap_is_offscreen = i830_uxa_pixmap_is_offscreen;
if(!uxa_driver_init(pScreen, i830->uxa_driver)) {
xf86DrvMsg(scrn->scrnIndex, X_INFO,
"UXA initialization failed\n");
xfree(i830->uxa_driver);
i830->accel = ACCEL_NONE;
return FALSE;
}
pScreen->CreatePixmap = i830_uxa_create_pixmap;
pScreen->DestroyPixmap = i830_uxa_destroy_pixmap;
I830SelectBuffer(scrn, I830_SELECT_FRONT);
return TRUE;
}
#ifdef XF86DRI
#ifndef ExaOffscreenMarkUsed

View File

@ -101,12 +101,16 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#include <string.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/ioctl.h>
#include "xf86.h"
#include "xf86_OSproc.h"
#include "i830.h"
#include "i810_reg.h"
#ifdef XF86DRI
#include "i915_drm.h"
#endif
#define ALIGN(i,m) (((i) + (m) - 1) & ~((m) - 1))
@ -161,28 +165,18 @@ i830_bind_memory(ScrnInfoPtr pScrn, i830_memory *mem)
if (mem == NULL || mem->bound)
return TRUE;
#ifdef XF86DRI_MM
if (mem->bo.size != 0) {
I830Ptr pI830 = I830PTR(pScrn);
int ret;
ret = drmBOSetStatus(pI830->drmSubFD, &mem->bo,
DRM_BO_FLAG_MEM_VRAM |
DRM_BO_FLAG_MEM_TT |
DRM_BO_FLAG_READ |
DRM_BO_FLAG_WRITE |
DRM_BO_FLAG_NO_EVICT,
DRM_BO_MASK_MEM |
DRM_BO_FLAG_READ |
DRM_BO_FLAG_WRITE |
DRM_BO_FLAG_NO_EVICT,
0, 0, 0);
if (ret != 0)
#ifdef XF86DRI
if (mem->bo != NULL) {
if (intel_bo_pin (mem->bo, mem->alignment) != 0) {
xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
"Failed to pin %s: %s\n",
mem->name, strerror(errno));
return FALSE;
}
mem->bound = TRUE;
mem->offset = mem->bo.offset;
mem->end = mem->bo.offset + mem->size;
mem->offset = mem->bo->offset;
mem->end = mem->offset + mem->size;
}
#endif
@ -216,16 +210,9 @@ i830_unbind_memory(ScrnInfoPtr pScrn, i830_memory *mem)
if (mem->tiling != TILE_NONE)
i830_clear_tiling(pScrn, mem->fence_nr);
#ifdef XF86DRI_MM
if (mem->bo.size != 0) {
I830Ptr pI830 = I830PTR(pScrn);
int ret;
ret = drmBOSetStatus(pI830->drmSubFD, &mem->bo,
0, DRM_BO_FLAG_NO_EVICT,
0, 0, 0);
if (ret == 0) {
#ifdef XF86DRI
if (mem->bo != NULL) {
if (intel_bo_unpin (mem->bo) == 0) {
mem->bound = FALSE;
/* Give buffer obviously wrong offset/end until it's re-pinned. */
mem->offset = -1;
@ -254,11 +241,10 @@ i830_free_memory(ScrnInfoPtr pScrn, i830_memory *mem)
/* Free any AGP memory. */
i830_unbind_memory(pScrn, mem);
#ifdef XF86DRI_MM
if (mem->bo.size != 0) {
#ifdef XF86DRI
if (mem->bo != NULL) {
I830Ptr pI830 = I830PTR(pScrn);
drmBOUnreference(pI830->drmSubFD, &mem->bo);
dri_bo_unreference (mem->bo);
if (pI830->bo_list == mem) {
pI830->bo_list = mem->next;
if (mem->next)
@ -315,12 +301,10 @@ i830_reset_allocations(ScrnInfoPtr pScrn)
}
/* Free any allocations in buffer objects */
#ifdef XF86DRI_MM
if (pI830->memory_manager) {
while (pI830->bo_list != NULL)
i830_free_memory(pScrn, pI830->bo_list);
}
#endif
/* Null out the pointers for all the allocations we just freed. This is
* kind of gross, but at least it's just one place now.
@ -346,6 +330,7 @@ i830_reset_allocations(ScrnInfoPtr pScrn)
pI830->textures = NULL;
#endif
pI830->LpRing->mem = NULL;
pI830->fake_bufmgr_mem = NULL;
}
void
@ -370,7 +355,7 @@ i830_free_3d_memory(ScrnInfoPtr pScrn)
* given range.
*
* This sets up the kernel memory manager to manage as much of the memory
* as we think it can, while leaving enough to us to fulfill our non-TTM
* as we think it can, while leaving enough to us to fulfill our non-GEM
* static allocations. Some of these exist because of the need for physical
* addresses to reference.
*/
@ -379,8 +364,10 @@ i830_allocator_init(ScrnInfoPtr pScrn, unsigned long offset, unsigned long size)
{
I830Ptr pI830 = I830PTR(pScrn);
i830_memory *start, *end;
#ifdef XF86DRI_MM
#ifdef XF86DRI
int dri_major, dri_minor, dri_patch;
struct drm_i915_getparam gp;
int has_gem;
#endif
start = xcalloc(1, sizeof(*start));
@ -418,15 +405,22 @@ i830_allocator_init(ScrnInfoPtr pScrn, unsigned long offset, unsigned long size)
pI830->memory_list = start;
#ifdef XF86DRI_MM
#ifdef XF86DRI
DRIQueryVersion(&dri_major, &dri_minor, &dri_patch);
has_gem = 0;
gp.param = I915_PARAM_HAS_GEM;
gp.value = &has_gem;
(void)drmCommandWriteRead(pI830->drmSubFD, DRM_I915_GETPARAM,
&gp, sizeof(gp));
/* Now that we have our manager set up, initialize the kernel MM if
* possible, covering almost all of the aperture. We need libdri interface
* 5.4 or newer so we can rely on the lock being held after DRIScreenInit,
* rather than after DRIFinishScreenInit.
*/
if (pI830->directRenderingEnabled && pI830->drmMinor >= 7 &&
if (pI830->directRenderingEnabled && has_gem &&
(dri_major > 5 || (dri_major == 5 && dri_minor >= 4)))
{
int mmsize;
@ -437,7 +431,7 @@ i830_allocator_init(ScrnInfoPtr pScrn, unsigned long offset, unsigned long size)
mmsize = size;
/* EXA area is fixed. */
if (pI830->useEXA) {
if (pI830->accel == ACCEL_EXA) {
mmsize -= ROUND_TO_PAGE(3 * pScrn->displayWidth * pI830->cpp *
pScrn->virtualY);
}
@ -456,13 +450,9 @@ i830_allocator_init(ScrnInfoPtr pScrn, unsigned long offset, unsigned long size)
}
if (pI830->fb_compression)
mmsize -= MB(6) + ROUND_TO_PAGE(FBC_LL_SIZE + FBC_LL_PAD);
/* Can't do TTM on stolen memory */
/* Can't do GEM on stolen memory */
mmsize -= pI830->stolen_size;
/* new chipsets need non-stolen status page */
if (HWS_NEED_GFX(pI830) && HWS_NEED_NONSTOLEN(pI830))
mmsize -= HWSTATUS_PAGE_SIZE;
/* Create the aperture allocation */
pI830->memory_manager =
i830_allocate_aperture(pScrn, "DRI memory manager",
@ -470,19 +460,22 @@ i830_allocator_init(ScrnInfoPtr pScrn, unsigned long offset, unsigned long size)
ALIGN_BOTH_ENDS | NEED_NON_STOLEN);
if (pI830->memory_manager != NULL) {
struct drm_i915_gem_init init;
int ret;
init.gtt_start = pI830->memory_manager->offset;
init.gtt_end = pI830->memory_manager->offset +
pI830->memory_manager->size;
/* Tell the kernel to manage it */
ret = drmMMInit(pI830->drmSubFD,
pI830->memory_manager->offset / GTT_PAGE_SIZE,
pI830->memory_manager->size / GTT_PAGE_SIZE,
DRM_BO_MEM_TT);
ret = ioctl(pI830->drmSubFD, DRM_IOCTL_I915_GEM_INIT, &init);
if (ret != 0) {
xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
"Failed to initialize kernel memory manager\n");
i830_free_memory(pScrn, pI830->memory_manager);
pI830->memory_manager = NULL;
}
i830_init_bufmgr(pScrn);
} else {
xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
"Failed to allocate space for kernel memory manager\n");
@ -490,7 +483,7 @@ i830_allocator_init(ScrnInfoPtr pScrn, unsigned long offset, unsigned long size)
pI830->memory_manager = NULL;
}
}
#endif /* XF86DRI_MM */
#endif /* XF86DRI */
return TRUE;
}
@ -503,14 +496,12 @@ i830_allocator_fini(ScrnInfoPtr pScrn)
/* Free most of the allocations */
i830_reset_allocations(pScrn);
#ifdef XF86DRI_MM
/* The memory manager is more special */
if (pI830->memory_manager) {
drmMMTakedown(pI830->drmSubFD, DRM_BO_MEM_TT);
/* XXX drmMMTakedown(pI830->drmSubFD, DRM_BO_MEM_TT);*/
i830_free_memory(pScrn, pI830->memory_manager);
pI830->memory_manager = NULL;
}
#endif /* XF86DRI_MM */
/* Free the start/end markers */
free(pI830->memory_list->next);
@ -628,6 +619,7 @@ i830_allocate_aperture(ScrnInfoPtr pScrn, const char *name,
size = ALIGN(size, GTT_PAGE_SIZE);
mem->size = size;
mem->allocated_size = size;
mem->alignment = alignment;
if (alignment < GTT_PAGE_SIZE)
alignment = GTT_PAGE_SIZE;
@ -719,15 +711,13 @@ i830_allocate_agp_memory(ScrnInfoPtr pScrn, i830_memory *mem, int flags)
return TRUE;
}
#ifdef XF86DRI_MM
#ifdef XF86DRI
static i830_memory *
i830_allocate_memory_bo(ScrnInfoPtr pScrn, const char *name,
unsigned long size, unsigned long align, int flags)
{
I830Ptr pI830 = I830PTR(pScrn);
i830_memory *mem;
unsigned long mask;
int ret;
assert((flags & NEED_PHYSICAL_ADDR) == 0);
@ -745,37 +735,27 @@ i830_allocate_memory_bo(ScrnInfoPtr pScrn, const char *name,
return NULL;
}
/*
* Create buffers in local memory to avoid having the creation order
* determine the TT offset. Driver acceleration
* cannot handle changed front buffer TT offsets yet ,
* so let's keep our fingers crossed.
*/
mem->bo = dri_bo_alloc (pI830->bufmgr, name, size, align);
mask = DRM_BO_FLAG_READ | DRM_BO_FLAG_WRITE | DRM_BO_FLAG_MAPPABLE |
DRM_BO_FLAG_MEM_LOCAL;
if (flags & ALLOW_SHARING)
mask |= DRM_BO_FLAG_SHAREABLE;
ret = drmBOCreate(pI830->drmSubFD, size, align / GTT_PAGE_SIZE, NULL,
mask, 0, &mem->bo);
if (ret) {
if (!mem->bo) {
xfree(mem->name);
xfree(mem);
return NULL;
}
/* Give buffer obviously wrong offset/end until it's pinned. */
mem->offset = -1;
mem->end = -1;
mem->size = size;
mem->allocated_size = size;
mem->alignment = align;
if (flags & NEED_LIFETIME_FIXED)
mem->lifetime_fixed_offset = TRUE;
/* Bind it if we currently control the VT */
if (pScrn->vtSema) {
if (!i830_bind_memory(pScrn, mem)) {
drmBOUnreference(pI830->drmSubFD, &mem->bo);
dri_bo_unreference (mem->bo);
xfree(mem->name);
xfree(mem);
return NULL;
@ -791,7 +771,7 @@ i830_allocate_memory_bo(ScrnInfoPtr pScrn, const char *name,
return mem;
}
#endif /* XF86DRI_MM */
#endif /* XF86DRI */
/* Allocates video memory at the given size and alignment.
*
@ -817,7 +797,7 @@ i830_allocate_memory(ScrnInfoPtr pScrn, const char *name,
{
i830_memory *mem;
#ifdef XF86DRI_MM
#ifdef XF86DRI
I830Ptr pI830 = I830PTR(pScrn);
if (pI830->memory_manager && !(flags & NEED_PHYSICAL_ADDR) &&
@ -825,7 +805,7 @@ i830_allocate_memory(ScrnInfoPtr pScrn, const char *name,
{
return i830_allocate_memory_bo(pScrn, name, size, alignment, flags);
} else
#endif
#endif /* XF86DRI */
{
mem = i830_allocate_aperture(pScrn, name, size, alignment, flags);
if (mem == NULL)
@ -902,6 +882,30 @@ i830_allocate_memory_tiled(ScrnInfoPtr pScrn, const char *name,
mem->pitch = pitch;
mem->fence_nr = -1;
#ifdef XF86DRI
if (mem->bo != 0) {
uint32_t tiling_mode = I915_TILING_NONE;
int ret;
if (tile_format == TILE_XMAJOR)
tiling_mode = I915_TILING_X;
else
tiling_mode = I915_TILING_Y;
ret = intel_bo_set_tiling (mem->bo, &tiling_mode);
if (ret != 0 || tiling_mode == I915_TILING_NONE) {
xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
"Failed to set tiling on %s: %s\n",
mem->name,
ret == 0 ? "rejected by kernel" : strerror(errno));
i830_free_memory(pScrn, mem);
return i830_allocate_memory(pScrn, name, size, alignment,
flags);
return FALSE;
}
}
#endif
return mem;
}
@ -955,7 +959,6 @@ i830_describe_allocations(ScrnInfoPtr pScrn, int verbosity, const char *prefix)
"%s0x%08lx: end of aperture\n",
prefix, pI830->FbMapSize);
#ifdef XF86DRI_MM
if (pI830->memory_manager) {
xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity,
"%sBO memory allocation layout:\n", prefix);
@ -985,7 +988,6 @@ i830_describe_allocations(ScrnInfoPtr pScrn, int verbosity, const char *prefix)
"%s0x%08lx: end of memory manager\n",
prefix, pI830->memory_manager->end);
}
#endif /* XF86DRI_MM */
}
static Bool
@ -993,7 +995,7 @@ i830_allocate_ringbuffer(ScrnInfoPtr pScrn)
{
I830Ptr pI830 = I830PTR(pScrn);
if (pI830->noAccel || pI830->LpRing->mem != NULL)
if (pI830->accel == ACCEL_NONE || pI830->memory_manager || pI830->LpRing->mem != NULL)
return TRUE;
/* We don't have any mechanism in the DRM yet to alert it that we've moved
@ -1138,7 +1140,7 @@ i830_allocate_framebuffer(ScrnInfoPtr pScrn, I830Ptr pI830, BoxPtr FbMemBox,
minspace = pitch * pScrn->virtualY;
avail = pScrn->videoRam * 1024;
if (!pI830->useEXA) {
if (pI830->accel == ACCEL_XAA) {
maxCacheLines = (avail - minspace) / pitch;
/* This shouldn't happen. */
if (maxCacheLines < 0) {
@ -1169,7 +1171,7 @@ i830_allocate_framebuffer(ScrnInfoPtr pScrn, I830Ptr pI830, BoxPtr FbMemBox,
"Allocating %d scanlines for pixmap cache\n",
cacheLines);
} else {
/* For EXA, we have a separate allocation for the linear allocator
/* For non-XAA, we have a separate allocation for the linear allocator
* which also does the pixmap cache.
*/
cacheLines = 0;
@ -1184,7 +1186,7 @@ i830_allocate_framebuffer(ScrnInfoPtr pScrn, I830Ptr pI830, BoxPtr FbMemBox,
* acceleration operations (non-XY COLOR_BLT) can't be done to tiled
* buffers.
*/
if (!pI830->useEXA && IS_I965G(pI830))
if (pI830->accel <= ACCEL_XAA && IS_I965G(pI830))
tiling = FALSE;
else
tiling = pI830->tiling;
@ -1372,8 +1374,18 @@ i830_allocate_2d_memory(ScrnInfoPtr pScrn)
return FALSE;
}
if (pI830->memory_manager == NULL) {
pI830->fake_bufmgr_mem = i830_allocate_memory(pScrn, "fake bufmgr",
MB(1), GTT_PAGE_SIZE, 0);
if (pI830->fake_bufmgr_mem == NULL) {
xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
"Failed to allocate fake bufmgr space.\n");
return FALSE;
}
}
/* even in XAA, 965G needs state mem buffer for rendering */
if (IS_I965G(pI830) && !pI830->noAccel &&
if (IS_I965G(pI830) && pI830->accel != ACCEL_NONE &&
pI830->gen4_render_state_mem == NULL)
{
pI830->gen4_render_state_mem =
@ -1411,7 +1423,7 @@ i830_allocate_2d_memory(ScrnInfoPtr pScrn)
return FALSE;
#ifdef I830_USE_EXA
if (pI830->useEXA) {
if (pI830->accel == ACCEL_EXA) {
if (pI830->exa_offscreen == NULL) {
/* Default EXA to having 3 screens worth of offscreen memory space
* (for pixmaps).
@ -1439,10 +1451,10 @@ i830_allocate_2d_memory(ScrnInfoPtr pScrn)
}
#endif /* I830_USE_EXA */
if (!pI830->noAccel && !pI830->useEXA) {
if (pI830->accel == ACCEL_XAA) {
/* The lifetime fixed offset of xaa scratch is probably not required,
* but we do some setup using it at XAAInit() time. And XAA may not
* end up being supported with TTM anyway.
* end up being supported with GEM anyway.
*/
pI830->xaa_scratch =
i830_allocate_memory(pScrn, "xaa scratch", MAX_SCRATCH_BUFFER_SIZE,
@ -1619,8 +1631,10 @@ i830_allocate_texture_memory(ScrnInfoPtr pScrn)
size / 1024);
return FALSE;
}
/* The offset must stay constant currently because we don't ever update
* the DRI maps after screen init.
/* Now that the DRM uses the sarea to get the offsets of the buffers,
* and we update the classic DRM mappings and the sarea contents on
* changes, the NEED_LIFETIME_FIXED is no longer true and should be
* made conditional on DRM version.
*/
pI830->textures = i830_allocate_memory(pScrn, "classic textures", size,
GTT_PAGE_SIZE,
@ -1682,7 +1696,7 @@ i830_allocate_3d_memory(ScrnInfoPtr pScrn)
DPRINTF(PFX, "i830_allocate_3d_memory\n");
if (HWS_NEED_GFX(pI830)) {
if (!pI830->memory_manager && HWS_NEED_GFX(pI830)) {
if (!i830_allocate_hwstatus(pScrn))
return FALSE;
}
@ -1952,12 +1966,10 @@ i830_bind_all_memory(ScrnInfoPtr pScrn)
FatalError("Couldn't bind memory for %s\n", mem->name);
}
}
#ifdef XF86DRI_MM
for (mem = pI830->bo_list; mem != NULL; mem = mem->next) {
if (!mem->lifetime_fixed_offset && !i830_bind_memory(pScrn, mem))
FatalError("Couldn't bind memory for BO %s\n", mem->name);
}
#endif
}
if (!pI830->SWCursor)
i830_update_cursor_offsets(pScrn);
@ -1982,7 +1994,6 @@ i830_unbind_all_memory(ScrnInfoPtr pScrn)
{
i830_unbind_memory(pScrn, mem);
}
#ifdef XF86DRI_MM
for (mem = pI830->bo_list; mem != NULL; mem = mem->next) {
/* Don't unpin objects which require that their offsets never
* change.
@ -1990,7 +2001,6 @@ i830_unbind_all_memory(ScrnInfoPtr pScrn)
if (!mem->lifetime_fixed_offset)
i830_unbind_memory(pScrn, mem);
}
#endif
pI830->gtt_acquired = FALSE;

View File

@ -275,10 +275,9 @@ i830_texture_setup(PicturePtr pPict, PixmapPtr pPix, int unit)
ScrnInfoPtr pScrn = xf86Screens[pPict->pDrawable->pScreen->myNum];
I830Ptr pI830 = I830PTR(pScrn);
uint32_t format, offset, pitch, filter;
uint32_t format, pitch, filter;
uint32_t wrap_mode = TEXCOORDMODE_CLAMP_BORDER;
offset = intel_get_pixmap_offset(pPix);
pitch = intel_get_pixmap_pitch(pPix);
pI830->scale_units[unit][0] = pPix->drawable.width;
pI830->scale_units[unit][1] = pPix->drawable.height;
@ -314,7 +313,7 @@ i830_texture_setup(PicturePtr pPict, PixmapPtr pPix, int unit)
BEGIN_BATCH(10);
OUT_BATCH(_3DSTATE_LOAD_STATE_IMMEDIATE_2 | LOAD_TEXTURE_MAP(unit) | 4);
OUT_BATCH((offset & TM0S0_ADDRESS_MASK) | TM0S0_USE_FENCE);
OUT_RELOC_PIXMAP(pPix, I915_GEM_DOMAIN_SAMPLER, 0, TM0S0_USE_FENCE);
OUT_BATCH(((pPix->drawable.height - 1) << TM0S1_HEIGHT_SHIFT) |
((pPix->drawable.width - 1) << TM0S1_WIDTH_SHIFT) | format);
OUT_BATCH((pitch/4 - 1) << TM0S2_PITCH_SHIFT | TM0S2_MAP_2D);
@ -394,7 +393,7 @@ i830_prepare_composite(int op, PicturePtr pSrcPicture,
{
ScrnInfoPtr pScrn = xf86Screens[pSrcPicture->pDrawable->pScreen->myNum];
I830Ptr pI830 = I830PTR(pScrn);
uint32_t dst_format, dst_offset, dst_pitch;
uint32_t dst_format, dst_pitch;
Bool is_affine_src, is_affine_mask;
Bool is_nearest = FALSE;
@ -408,7 +407,6 @@ i830_prepare_composite(int op, PicturePtr pSrcPicture,
if (!i830_get_dest_format(pDstPicture, &dst_format))
return FALSE;
dst_offset = intel_get_pixmap_offset(pDst);
dst_pitch = intel_get_pixmap_pitch(pDst);
if (!i830_texture_setup(pSrcPicture, pSrc, 0))
@ -446,7 +444,7 @@ i830_prepare_composite(int op, PicturePtr pSrcPicture,
OUT_BATCH(_3DSTATE_BUF_INFO_CMD);
OUT_BATCH(BUF_3D_ID_COLOR_BACK| BUF_3D_USE_FENCE |
BUF_3D_PITCH(dst_pitch));
OUT_BATCH(BUF_3D_ADDR(dst_offset));
OUT_RELOC_PIXMAP(pDst, I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER, 0);
OUT_BATCH(MI_NOOP);
OUT_BATCH(_3DSTATE_DST_BUF_VARS_CMD);
@ -735,14 +733,3 @@ i830_composite(PixmapPtr pDst, int srcX, int srcY, int maskX, int maskY,
ADVANCE_BATCH();
}
/**
* Do any cleanup from the Composite operation.
*
* This is shared between i830 through i965.
*/
void
i830_done_composite(PixmapPtr pDst)
{
/* NO-OP */
}

View File

@ -42,11 +42,6 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
pI830->ring_next &= pI830->LpRing->tail_mask; \
} while (0)
union intfloat {
float f;
unsigned int ui;
};
#define OUT_RING_F(x) do { \
union intfloat tmp; \
tmp.f = (float)(x); \

View File

@ -2460,13 +2460,13 @@ I830PutImage(ScrnInfoPtr pScrn,
}
#ifdef I830_USE_EXA
if (pPriv->textured && pI830->useEXA) {
if (pPriv->textured && pI830->accel == ACCEL_EXA) {
/* Force the pixmap into framebuffer so we can draw to it. */
exaMoveInPixmap(pPixmap);
}
#endif
if (pPriv->textured && !pI830->useEXA &&
if (pPriv->textured && pI830->accel <= ACCEL_XAA &&
(((char *)pPixmap->devPrivate.ptr < (char *)pI830->FbBase) ||
((char *)pPixmap->devPrivate.ptr >= (char *)pI830->FbBase +
pI830->FbMapSize))) {

View File

@ -446,12 +446,12 @@ do { \
#define FS_END() \
do { \
int _i, _pad = (_cur_shader_commands & 0x1) ? 0 : 1; \
BEGIN_LP_RING(_cur_shader_commands * 3 + 1 + _pad); \
OUT_RING(_3DSTATE_PIXEL_SHADER_PROGRAM | \
BEGIN_BATCH(_cur_shader_commands * 3 + 1 + _pad); \
OUT_BATCH(_3DSTATE_PIXEL_SHADER_PROGRAM | \
(_cur_shader_commands * 3 - 1)); \
for (_i = 0; _i < _cur_shader_commands * 3; _i++) \
OUT_RING(_shader_buf[_i]); \
OUT_BATCH(_shader_buf[_i]); \
if (_pad != 0) \
OUT_RING(MI_NOOP); \
ADVANCE_LP_RING(); \
OUT_BATCH(MI_NOOP); \
ADVANCE_BATCH(); \
} while (0);

View File

@ -250,11 +250,10 @@ i915_texture_setup(PicturePtr pPict, PixmapPtr pPix, int unit)
{
ScrnInfoPtr pScrn = xf86Screens[pPict->pDrawable->pScreen->myNum];
I830Ptr pI830 = I830PTR(pScrn);
uint32_t format, offset, pitch, filter;
uint32_t format, pitch, filter;
int w, h, i;
uint32_t wrap_mode = TEXCOORDMODE_CLAMP_BORDER;
offset = intel_get_pixmap_offset(pPix);
pitch = intel_get_pixmap_pitch(pPix);
w = pPict->pDrawable->width;
h = pPict->pDrawable->height;
@ -288,7 +287,7 @@ i915_texture_setup(PicturePtr pPict, PixmapPtr pPix, int unit)
I830FALLBACK("Bad filter 0x%x\n", pPict->filter);
}
pI830->mapstate[unit * 3 + 0] = offset;
pI830->mapstate[unit * 3 + 0] = 0; /* offset filled in at emit time */
pI830->mapstate[unit * 3 + 1] = format |
MS3_USE_FENCE_REGS |
((pPix->drawable.height - 1) << MS3_HEIGHT_SHIFT) |
@ -316,7 +315,7 @@ i915_prepare_composite(int op, PicturePtr pSrcPicture,
{
ScrnInfoPtr pScrn = xf86Screens[pSrcPicture->pDrawable->pScreen->myNum];
I830Ptr pI830 = I830PTR(pScrn);
uint32_t dst_format, dst_offset, dst_pitch;
uint32_t dst_format, dst_pitch;
uint32_t blendctl;
int out_reg = FS_OC;
FS_LOCALS(20);
@ -333,7 +332,6 @@ i915_prepare_composite(int op, PicturePtr pSrcPicture,
if (!i915_get_dest_format(pDstPicture, &dst_format))
return FALSE;
dst_offset = intel_get_pixmap_offset(pDst);
dst_pitch = intel_get_pixmap_pitch(pDst);
if (!i915_texture_setup(pSrcPicture, pSrc, 0))
@ -362,7 +360,7 @@ i915_prepare_composite(int op, PicturePtr pSrcPicture,
BEGIN_BATCH(10);
OUT_BATCH(_3DSTATE_MAP_STATE | 3);
OUT_BATCH(0x00000001); /* map 0 */
OUT_BATCH(pI830->mapstate[0]);
OUT_RELOC_PIXMAP(pSrc, I915_GEM_DOMAIN_SAMPLER, 0, 0);
OUT_BATCH(pI830->mapstate[1]);
OUT_BATCH(pI830->mapstate[2]);
@ -376,10 +374,10 @@ i915_prepare_composite(int op, PicturePtr pSrcPicture,
BEGIN_BATCH(16);
OUT_BATCH(_3DSTATE_MAP_STATE | 6);
OUT_BATCH(0x00000003); /* map 0,1 */
OUT_BATCH(pI830->mapstate[0]);
OUT_RELOC_PIXMAP(pSrc, I915_GEM_DOMAIN_SAMPLER, 0, 0);
OUT_BATCH(pI830->mapstate[1]);
OUT_BATCH(pI830->mapstate[2]);
OUT_BATCH(pI830->mapstate[3]);
OUT_RELOC_PIXMAP(pMask, I915_GEM_DOMAIN_SAMPLER, 0, 0);
OUT_BATCH(pI830->mapstate[4]);
OUT_BATCH(pI830->mapstate[5]);
@ -400,7 +398,7 @@ i915_prepare_composite(int op, PicturePtr pSrcPicture,
OUT_BATCH(_3DSTATE_BUF_INFO_CMD);
OUT_BATCH(BUF_3D_ID_COLOR_BACK| BUF_3D_USE_FENCE|
BUF_3D_PITCH(dst_pitch));
OUT_BATCH(BUF_3D_ADDR(dst_offset));
OUT_RELOC_PIXMAP(pDst, I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER, 0);
OUT_BATCH(_3DSTATE_DST_BUF_VARS_CMD);
OUT_BATCH(dst_format);

View File

@ -130,7 +130,7 @@ I915DisplayVideoTextured(ScrnInfoPtr pScrn, I830PortPrivPtr pPriv, int id,
OUT_BATCH(_3DSTATE_BUF_INFO_CMD);
OUT_BATCH(BUF_3D_ID_COLOR_BACK | BUF_3D_USE_FENCE |
BUF_3D_PITCH(intel_get_pixmap_pitch(pPixmap)));
OUT_BATCH(BUF_3D_ADDR(intel_get_pixmap_offset(pPixmap)));
OUT_RELOC_PIXMAP(pPixmap, I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER, 0);
ADVANCE_BATCH();
if (!planar) {

View File

@ -1431,26 +1431,6 @@ i965_composite(PixmapPtr pDst, int srcX, int srcY, int maskX, int maskY,
ErrorF("sync after 3dprimitive\n");
I830Sync(pScrn);
#endif
/* we must be sure that the pipeline is flushed before next exa draw,
because that will be new state, binding state and instructions*/
{
BEGIN_BATCH(4);
OUT_BATCH(BRW_PIPE_CONTROL |
BRW_PIPE_CONTROL_NOWRITE |
BRW_PIPE_CONTROL_WC_FLUSH |
BRW_PIPE_CONTROL_IS_FLUSH |
(1 << 10) | /* XXX texture cache flush for BLC/CTG */
2);
OUT_BATCH(0); /* Destination address */
OUT_BATCH(0); /* Immediate data low DW */
OUT_BATCH(0); /* Immediate data high DW */
ADVANCE_BATCH();
}
/* Mark sync so we can wait for it before setting up the VB on the next
* rectangle.
*/
i830MarkSync(pScrn);
}
/**

View File

@ -2,3 +2,4 @@ intel_hotplug
intel_idle
intel_reg_dumper
intel_stepping
intel_statuspage

View File

@ -1,4 +1,4 @@
noinst_PROGRAMS = intel_reg_dumper intel_idle intel_stepping intel_hotplug
noinst_PROGRAMS = intel_reg_dumper intel_idle intel_stepping intel_statuspage intel_hotplug
intel_reg_dumper_SOURCES = \
main.c \
@ -21,10 +21,16 @@ intel_hotplug_SOURCES = \
intel_stepping_SOURCES = \
stepping.c
intel_statuspage_SOURCES = \
statuspage.c \
reg_dumper.h \
util.c
intel_hotplug_LDADD = $(PCIACCESS_LIBS)
intel_reg_dumper_LDADD = $(PCIACCESS_LIBS)
intel_idle_LDADD = $(PCIACCESS_LIBS)
intel_stepping_LDADD = $(PCIACCESS_LIBS)
intel_statuspage_LDADD = $(PCIACCESS_LIBS)
AM_CFLAGS = $(PCIACCESS_CFLAGS) $(WARN_CFLAGS) \
-I$(srcdir)/.. -DREG_DUMPER

View File

@ -43,11 +43,13 @@ struct idle_flags {
};
struct idle_flags i915_idle_flags[] = {
#if 0
{IDCT_DONE, "IDCT"},
{IQ_DONE, "IQ"},
{PR_DONE, "PR"},
{VLD_DONE, "VLD"},
{IP_DONE, "IP"},
#endif
{FBC_DONE, "FBC"},
{BINNER_DONE, "BINNER"},
{SF_DONE, "SF"},
@ -66,7 +68,9 @@ struct idle_flags i915_idle_flags[] = {
{PS_DONE, "PS"},
{CC_DONE, "CC"},
{MAP_FILTER_DONE, "map filter"},
#if 0
{MAP_L2_IDLE, "map L2"},
#endif
{0, "total"},
{0, "other"},
@ -105,8 +109,8 @@ setup_other_flags(I830Ptr pI830,
other_idle_flags &= ~idle_flags[i].instdone_flag;
total_idle_flags |= idle_flags[i].instdone_flag;
}
idle_flags[i - 1].instdone_flag = total_idle_flags;
idle_flags[i].instdone_flag = other_idle_flags;
idle_flags[idle_flag_count - 2].instdone_flag = total_idle_flags;
idle_flags[idle_flag_count - 1].instdone_flag = other_idle_flags;
}
int main(int argc, char **argv)

View File

@ -88,3 +88,4 @@ typedef struct _scrn {
char *XNFprintf(const char *format, ...);
void xf86DrvMsg(int scrnIndex, int severity, const char *format, ...);
void i830DumpRegs(ScrnInfoPtr pScrn);
void intel_i830rec_init(I830Ptr pI830);

View File

@ -0,0 +1,81 @@
/*
* 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>
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include <sys/types.h>
#include <sys/mman.h>
#include <pciaccess.h>
#include <err.h>
#include <unistd.h>
#include <fcntl.h>
#include "reg_dumper.h"
#include "../i810_reg.h"
int main(int argc, char **argv)
{
I830Rec i830;
I830Ptr pI830 = &i830;
int devmem;
uint32_t hws_offset;
volatile uint32_t *hws;
intel_i830rec_init(pI830);
if (HWS_NEED_GFX(pI830))
errx(1, "status page in graphics virtual unsupported.\n");
hws_offset = INREG(HWS_PGA);
devmem = open("/dev/mem", O_RDWR, 0);
if (devmem == -1)
err(1, "Couldn't open /dev/mem");
hws = mmap(NULL, 4096, PROT_READ, MAP_SHARED, devmem, hws_offset);
if (hws == MAP_FAILED)
err(1, "Couldn't map /dev/mem at 0x%08x", hws_offset);
close(devmem);
for (;;) {
int i;
printf("\n");
for (i = 0; i < 64; i += 4) {
printf("0x%04x: 0x%08x 0x%08x 0x%08x 0x%08x\n", i * 4,
hws[i], hws[i + 1], hws[i + 2], hws[i + 3]);
}
sleep(1);
}
return 0;
}

86
src/reg_dumper/util.c Normal file
View File

@ -0,0 +1,86 @@
/*
* 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 util.c
*
* Utility functions for the various tools in the reg_dumper directory.
*/
#include <err.h>
#include <pciaccess.h>
#include "reg_dumper.h"
/**
* Sets up the pI830 for use by common.h-style macros, particularly
* INREG/OUTERG.
*/
void intel_i830rec_init(I830Ptr pI830)
{
struct pci_device *dev;
int err, mmio_bar;
void *mmio;
err = pci_system_init();
if (err != 0) {
fprintf(stderr, "Couldn't initialize PCI system: %s\n", strerror(err));
exit(1);
}
/* Grab the graphics card */
dev = pci_device_find_by_slot(0, 0, 2, 0);
if (dev == NULL)
errx(1, "Couldn't find graphics card");
err = pci_device_probe(dev);
if (err != 0) {
fprintf(stderr, "Couldn't probe graphics card: %s\n", strerror(err));
exit(1);
}
if (dev->vendor_id != 0x8086)
errx(1, "Graphics card is non-intel");
pI830->PciInfo = &pI830->pci_info_rec;
pI830->PciInfo->chipType = dev->device_id;
pI830->pci_dev = dev;
mmio_bar = IS_I9XX(pI830) ? 0 : 1;
err = pci_device_map_range (dev,
dev->regions[mmio_bar].base_addr,
dev->regions[mmio_bar].size,
PCI_DEV_MAP_FLAG_WRITABLE,
&mmio);
if (err != 0) {
fprintf(stderr, "Couldn't map MMIO region: %s\n", strerror(err));
exit(1);
}
pI830->mmio = mmio;
}

View File

@ -4,7 +4,7 @@ lib_LTLIBRARIES=libI810XvMC.la libIntelXvMC.la
libI810XvMC_la_SOURCES = I810XvMC.c \
I810XvMC.h
libI810XvMC_la_CFLAGS = @WARN_CFLAGS@ @XORG_CFLAGS@ @DRI_CFLAGS@ \
libI810XvMC_la_CFLAGS = @WARN_CFLAGS@ @XORG_CFLAGS@ @DRM_CFLAGS@ @DRI_CFLAGS@ \
-I$(top_srcdir)/src -DTRUE=1 -DFALSE=0
libI810XvMC_la_LDFLAGS = -version-number 1:0:0
libI810XvMC_la_LIBADD = @DRI_LIBS@
@ -22,7 +22,8 @@ libIntelXvMC_la_SOURCES = intel_xvmc.c \
xf86dri.h \
xf86dristr.h
libIntelXvMC_la_CFLAGS = @XORG_CFLAGS@ @DRI_CFLAGS@ @XVMCLIB_CFLAGS@ -I$(top_srcdir)/src -DTRUE=1 -DFALSE=0
libIntelXvMC_la_CFLAGS = @XORG_CFLAGS@ @DRM_CFLAGS@ @DRI_CFLAGS@ \
@XVMCLIB_CFLAGS@ -I$(top_srcdir)/src -DTRUE=1 -DFALSE=0
libIntelXvMC_la_LDFLAGS = -version-number 1:0:0
libIntelXvMC_la_LIBADD = @DRI_LIBS@
endif

20
uxa/Makefile.am Normal file
View File

@ -0,0 +1,20 @@
noinst_LTLIBRARIES = libuxa.la
# Override these since UXA doesn't need them and the needed files aren't
# built (in hw/xfree86/os-support/solaris) until after UXA is built
SOLARIS_ASM_CFLAGS=""
INCLUDES = \
$(XORG_INCS)
AM_CFLAGS = $(WARN_CFLAGS) $(XORG_CFLAGS) $(DIX_CFLAGS)
libuxa_la_SOURCES = \
uxa.c \
uxa.h \
uxa-accel.c \
uxa-glyphs.c \
uxa-render.c \
uxa-priv.h \
uxa-unaccel.c

1032
uxa/uxa-accel.c Normal file

File diff suppressed because it is too large Load Diff

880
uxa/uxa-glyphs.c Normal file
View File

@ -0,0 +1,880 @@
/*
* Copyright © 2008 Red Hat, Inc.
* Partly based on code Copyright © 2000 SuSE, Inc.
*
* Permission to use, copy, modify, distribute, and sell this software and its
* documentation for any purpose is hereby granted without fee, provided that
* the above copyright notice appear in all copies and that both that
* copyright notice and this permission notice appear in supporting
* documentation, and that the name of Red Hat not be used in advertising or
* publicity pertaining to distribution of the software without specific,
* written prior permission. Red Hat makes no representations about the
* suitability of this software for any purpose. It is provided "as is"
* without express or implied warranty.
*
* Red Hat DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL Red Hat
* BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* Permission to use, copy, modify, distribute, and sell this software and its
* documentation for any purpose is hereby granted without fee, provided that
* the above copyright notice appear in all copies and that both that
* copyright notice and this permission notice appear in supporting
* documentation, and that the name of SuSE not be used in advertising or
* publicity pertaining to distribution of the software without specific,
* written prior permission. SuSE makes no representations about the
* suitability of this software for any purpose. It is provided "as is"
* without express or implied warranty.
*
* SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE
* BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* Author: Owen Taylor <otaylor@fishsoup.net>
* Based on code by: Keith Packard
*/
#ifdef HAVE_DIX_CONFIG_H
#include <dix-config.h>
#endif
#include <stdlib.h>
#include "uxa-priv.h"
#include "mipict.h"
#if DEBUG_GLYPH_CACHE
#define DBG_GLYPH_CACHE(a) ErrorF a
#else
#define DBG_GLYPH_CACHE(a)
#endif
/* Width of the pixmaps we use for the caches; this should be less than
* max texture size of the driver; this may need to actually come from
* the driver.
*/
#define CACHE_PICTURE_WIDTH 1024
/* Maximum number of glyphs we buffer on the stack before flushing
* rendering to the mask or destination surface.
*/
#define GLYPH_BUFFER_SIZE 256
typedef struct {
PicturePtr source;
uxa_composite_rect_t rects[GLYPH_BUFFER_SIZE];
int count;
} uxa_glyph_buffer_t;
typedef enum {
UXA_GLYPH_SUCCESS, /* Glyph added to render buffer */
UXA_GLYPH_FAIL, /* out of memory, etc */
UXA_GLYPH_NEED_FLUSH, /* would evict a glyph already in the buffer */
} uxa_glyph_cache_result_t;
void
uxa_glyphs_init(ScreenPtr pScreen)
{
uxa_screen_t *uxa_screen = uxa_get_screen(pScreen);
int i = 0;
memset(uxa_screen->glyphCaches, 0, sizeof(uxa_screen->glyphCaches));
uxa_screen->glyphCaches[i].format = PICT_a8;
uxa_screen->glyphCaches[i].glyphWidth = uxa_screen->glyphCaches[i].glyphHeight = 16;
i++;
uxa_screen->glyphCaches[i].format = PICT_a8;
uxa_screen->glyphCaches[i].glyphWidth = uxa_screen->glyphCaches[i].glyphHeight = 32;
i++;
uxa_screen->glyphCaches[i].format = PICT_a8r8g8b8;
uxa_screen->glyphCaches[i].glyphWidth = uxa_screen->glyphCaches[i].glyphHeight = 16;
i++;
uxa_screen->glyphCaches[i].format = PICT_a8r8g8b8;
uxa_screen->glyphCaches[i].glyphWidth = uxa_screen->glyphCaches[i].glyphHeight = 32;
i++;
assert(i == UXA_NUM_GLYPH_CACHES);
for (i = 0; i < UXA_NUM_GLYPH_CACHES; i++) {
uxa_screen->glyphCaches[i].columns = CACHE_PICTURE_WIDTH / uxa_screen->glyphCaches[i].glyphWidth;
uxa_screen->glyphCaches[i].size = 256;
uxa_screen->glyphCaches[i].hashSize = 557;
}
}
static void
uxa_unrealize_glyph_caches(ScreenPtr pScreen,
unsigned int format)
{
uxa_screen_t *uxa_screen = uxa_get_screen(pScreen);
int i;
for (i = 0; i < UXA_NUM_GLYPH_CACHES; i++) {
uxa_glyph_cache_t *cache = &uxa_screen->glyphCaches[i];
if (cache->format != format)
continue;
if (cache->picture) {
FreePicture ((pointer) cache->picture, (XID) 0);
cache->picture = NULL;
}
if (cache->hashEntries) {
xfree(cache->hashEntries);
cache->hashEntries = NULL;
}
if (cache->glyphs) {
xfree(cache->glyphs);
cache->glyphs = NULL;
}
cache->glyphCount = 0;
}
}
/* All caches for a single format share a single pixmap for glyph storage,
* allowing mixing glyphs of different sizes without paying a penalty
* for switching between source pixmaps. (Note that for a size of font
* right at the border between two sizes, we might be switching for almost
* every glyph.)
*
* This function allocates the storage pixmap, and then fills in the
* rest of the allocated structures for all caches with the given format.
*/
static Bool
uxa_realize_glyph_caches(ScreenPtr pScreen,
unsigned int format)
{
uxa_screen_t *uxa_screen = uxa_get_screen(pScreen);
int depth = PIXMAN_FORMAT_DEPTH(format);
PictFormatPtr pPictFormat;
PixmapPtr pPixmap;
PicturePtr pPicture;
int height;
int i;
int error;
pPictFormat = PictureMatchFormat(pScreen, depth, format);
if (!pPictFormat)
return FALSE;
/* Compute the total vertical size needed for the format */
height = 0;
for (i = 0; i < UXA_NUM_GLYPH_CACHES; i++) {
uxa_glyph_cache_t *cache = &uxa_screen->glyphCaches[i];
int rows;
if (cache->format != format)
continue;
cache->yOffset = height;
rows = (cache->size + cache->columns - 1) / cache->columns;
height += rows * cache->glyphHeight;
}
/* Now allocate the pixmap and picture */
pPixmap = (*pScreen->CreatePixmap) (pScreen,
CACHE_PICTURE_WIDTH,
height, depth, 0);
if (!pPixmap)
return FALSE;
pPicture = CreatePicture(0, &pPixmap->drawable, pPictFormat,
0, 0, serverClient, &error);
(*pScreen->DestroyPixmap) (pPixmap); /* picture holds a refcount */
if (!pPicture)
return FALSE;
/* And store the picture in all the caches for the format */
for (i = 0; i < UXA_NUM_GLYPH_CACHES; i++) {
uxa_glyph_cache_t *cache = &uxa_screen->glyphCaches[i];
int j;
if (cache->format != format)
continue;
cache->picture = pPicture;
cache->picture->refcnt++;
cache->hashEntries = xalloc(sizeof(int) * cache->hashSize);
cache->glyphs = xalloc(sizeof(uxa_cached_glyph_t) * cache->size);
cache->glyphCount = 0;
if (!cache->hashEntries || !cache->glyphs)
goto bail;
for (j = 0; j < cache->hashSize; j++)
cache->hashEntries[j] = -1;
cache->evictionPosition = rand() % cache->size;
}
/* Each cache references the picture individually */
FreePicture ((pointer) pPicture, (XID) 0);
return TRUE;
bail:
uxa_unrealize_glyph_caches(pScreen, format);
return FALSE;
}
void
uxa_glyphs_fini (ScreenPtr pScreen)
{
uxa_screen_t *uxa_screen = uxa_get_screen(pScreen);
int i;
for (i = 0; i < UXA_NUM_GLYPH_CACHES; i++) {
uxa_glyph_cache_t *cache = &uxa_screen->glyphCaches[i];
if (cache->picture)
uxa_unrealize_glyph_caches(pScreen, cache->format);
}
}
static int
uxa_glyph_cache_hash_lookup(uxa_glyph_cache_t *cache, GlyphPtr pGlyph)
{
int slot;
slot = (*(CARD32 *) pGlyph->sha1) % cache->hashSize;
while (TRUE) { /* hash table can never be full */
int entryPos = cache->hashEntries[slot];
if (entryPos == -1)
return -1;
if (memcmp(pGlyph->sha1, cache->glyphs[entryPos].sha1, sizeof(pGlyph->sha1)) == 0){
return entryPos;
}
slot--;
if (slot < 0)
slot = cache->hashSize - 1;
}
}
static void
uxa_glyph_cache_hash_insert(uxa_glyph_cache_t *cache,
GlyphPtr pGlyph,
int pos)
{
int slot;
memcpy(cache->glyphs[pos].sha1, pGlyph->sha1, sizeof(pGlyph->sha1));
slot = (*(CARD32 *) pGlyph->sha1) % cache->hashSize;
while (TRUE) { /* hash table can never be full */
if (cache->hashEntries[slot] == -1) {
cache->hashEntries[slot] = pos;
return;
}
slot--;
if (slot < 0)
slot = cache->hashSize - 1;
}
}
static void
uxa_glyph_cache_hash_remove(uxa_glyph_cache_t *cache,
int pos)
{
int slot;
int emptiedSlot = -1;
slot = (*(CARD32 *) cache->glyphs[pos].sha1) % cache->hashSize;
while (TRUE) { /* hash table can never be full */
int entryPos = cache->hashEntries[slot];
if (entryPos == -1)
return;
if (entryPos == pos) {
cache->hashEntries[slot] = -1;
emptiedSlot = slot;
} else if (emptiedSlot != -1) {
/* See if we can move this entry into the emptied slot, we can't
* do that if if entry would have hashed between the current position
* and the emptied slot. (taking wrapping into account). Bad positions
* are:
*
* | XXXXXXXXXX |
* i j
*
* |XXX XXXX|
* j i
*
* i - slot, j - emptiedSlot
*
* (Knuth 6.4R)
*/
int entrySlot = (*(CARD32 *) cache->glyphs[entryPos].sha1) % cache->hashSize;
if (!((entrySlot >= slot && entrySlot < emptiedSlot) ||
(emptiedSlot < slot && (entrySlot < emptiedSlot || entrySlot >= slot))))
{
cache->hashEntries[emptiedSlot] = entryPos;
cache->hashEntries[slot] = -1;
emptiedSlot = slot;
}
}
slot--;
if (slot < 0)
slot = cache->hashSize - 1;
}
}
#define CACHE_X(pos) (((pos) % cache->columns) * cache->glyphWidth)
#define CACHE_Y(pos) (cache->yOffset + ((pos) / cache->columns) * cache->glyphHeight)
/* The most efficient thing to way to upload the glyph to the screen
* is to use the UploadToScreen() driver hook; this allows us to
* pipeline glyph uploads and to avoid creating offscreen pixmaps for
* glyphs that we'll never use again.
*/
static Bool
uxa_glyph_cache_upload_glyph(ScreenPtr pScreen,
uxa_glyph_cache_t *cache,
int pos,
GlyphPtr pGlyph)
{
uxa_screen_t *uxa_screen = uxa_get_screen(pScreen);
PicturePtr pGlyphPicture = GlyphPicture(pGlyph)[pScreen->myNum];
PixmapPtr pGlyphPixmap = (PixmapPtr)pGlyphPicture->pDrawable;
PixmapPtr pCachePixmap = (PixmapPtr)cache->picture->pDrawable;
int cacheXoff, cacheYoff;
if (!uxa_screen->info->put_image || uxa_screen->swappedOut)
return FALSE;
/* If the glyph pixmap is already uploaded, no point in doing
* things this way */
if (uxa_pixmap_is_offscreen(pGlyphPixmap))
return FALSE;
/* UploadToScreen only works if bpp match */
if (pGlyphPixmap->drawable.bitsPerPixel != pCachePixmap->drawable.bitsPerPixel)
return FALSE;
pCachePixmap = uxa_get_offscreen_pixmap ((DrawablePtr)pCachePixmap, &cacheXoff, &cacheYoff);
if (!pCachePixmap)
return FALSE;
if (!uxa_screen->info->put_image(pCachePixmap,
CACHE_X(pos) + cacheXoff,
CACHE_Y(pos) + cacheYoff,
pGlyph->info.width,
pGlyph->info.height,
(char *)pGlyphPixmap->devPrivate.ptr,
pGlyphPixmap->devKind))
return FALSE;
return TRUE;
}
static uxa_glyph_cache_result_t
uxa_glyph_cache_buffer_glyph(ScreenPtr pScreen,
uxa_glyph_cache_t *cache,
uxa_glyph_buffer_t *buffer,
GlyphPtr pGlyph,
int xGlyph,
int yGlyph)
{
uxa_composite_rect_t *rect;
int pos;
if (buffer->source && buffer->source != cache->picture)
return UXA_GLYPH_NEED_FLUSH;
if (!cache->picture) {
if (!uxa_realize_glyph_caches(pScreen, cache->format))
return UXA_GLYPH_FAIL;
}
DBG_GLYPH_CACHE(("(%d,%d,%s): buffering glyph %lx\n",
cache->glyphWidth, cache->glyphHeight, cache->format == PICT_a8 ? "A" : "ARGB",
(long)*(CARD32 *) pGlyph->sha1));
pos = uxa_glyph_cache_hash_lookup(cache, pGlyph);
if (pos != -1) {
DBG_GLYPH_CACHE((" found existing glyph at %d\n", pos));
} else {
if (cache->glyphCount < cache->size) {
/* Space remaining; we fill from the start */
pos = cache->glyphCount;
cache->glyphCount++;
DBG_GLYPH_CACHE((" storing glyph in free space at %d\n", pos));
uxa_glyph_cache_hash_insert(cache, pGlyph, pos);
} else {
/* Need to evict an entry. We have to see if any glyphs
* already in the output buffer were at this position in
* the cache
*/
pos = cache->evictionPosition;
DBG_GLYPH_CACHE((" evicting glyph at %d\n", pos));
if (buffer->count) {
int x, y;
int i;
x = CACHE_X(pos);
y = CACHE_Y(pos);
for (i = 0; i < buffer->count; i++) {
if (buffer->rects[i].xSrc == x && buffer->rects[i].ySrc == y) {
DBG_GLYPH_CACHE((" must flush buffer\n"));
return UXA_GLYPH_NEED_FLUSH;
}
}
}
/* OK, we're all set, swap in the new glyph */
uxa_glyph_cache_hash_remove(cache, pos);
uxa_glyph_cache_hash_insert(cache, pGlyph, pos);
/* And pick a new eviction position */
cache->evictionPosition = rand() % cache->size;
}
/* Now actually upload the glyph into the cache picture; if
* we can't do it with UploadToScreen (because the glyph is
* offscreen, etc), we fall back to CompositePicture.
*/
if (!uxa_glyph_cache_upload_glyph(pScreen, cache, pos, pGlyph)) {
CompositePicture (PictOpSrc,
GlyphPicture(pGlyph)[pScreen->myNum],
None,
cache->picture,
0, 0,
0, 0,
CACHE_X(pos),
CACHE_Y(pos),
pGlyph->info.width,
pGlyph->info.height);
}
}
buffer->source = cache->picture;
rect = &buffer->rects[buffer->count];
rect->xSrc = CACHE_X(pos);
rect->ySrc = CACHE_Y(pos);
rect->xDst = xGlyph - pGlyph->info.x;
rect->yDst = yGlyph - pGlyph->info.y;
rect->width = pGlyph->info.width;
rect->height = pGlyph->info.height;
buffer->count++;
return UXA_GLYPH_SUCCESS;
}
#undef CACHE_X
#undef CACHE_Y
static uxa_glyph_cache_result_t
uxa_buffer_glyph(ScreenPtr pScreen,
uxa_glyph_buffer_t *buffer,
GlyphPtr pGlyph,
int xGlyph,
int yGlyph)
{
uxa_screen_t *uxa_screen = uxa_get_screen(pScreen);
unsigned int format = (GlyphPicture(pGlyph)[pScreen->myNum])->format;
int width = pGlyph->info.width;
int height = pGlyph->info.height;
uxa_composite_rect_t *rect;
PicturePtr source;
int i;
if (buffer->count == GLYPH_BUFFER_SIZE)
return UXA_GLYPH_NEED_FLUSH;
if (PICT_FORMAT_BPP(format) == 1)
format = PICT_a8;
for (i = 0; i < UXA_NUM_GLYPH_CACHES; i++) {
uxa_glyph_cache_t *cache = &uxa_screen->glyphCaches[i];
if (format == cache->format &&
width <= cache->glyphWidth &&
height <= cache->glyphHeight) {
uxa_glyph_cache_result_t result = uxa_glyph_cache_buffer_glyph(pScreen, &uxa_screen->glyphCaches[i],
buffer,
pGlyph, xGlyph, yGlyph);
switch (result) {
case UXA_GLYPH_FAIL:
break;
case UXA_GLYPH_SUCCESS:
case UXA_GLYPH_NEED_FLUSH:
return result;
}
}
}
/* Couldn't find the glyph in the cache, use the glyph picture directly */
source = GlyphPicture(pGlyph)[pScreen->myNum];
if (buffer->source && buffer->source != source)
return UXA_GLYPH_NEED_FLUSH;
buffer->source = source;
rect = &buffer->rects[buffer->count];
rect->xSrc = 0;
rect->ySrc = 0;
rect->xDst = xGlyph - pGlyph->info.x;
rect->yDst = yGlyph - pGlyph->info.y;
rect->width = pGlyph->info.width;
rect->height = pGlyph->info.height;
buffer->count++;
return UXA_GLYPH_SUCCESS;
}
static void
uxa_glyphs_to_mask(PicturePtr pMask,
uxa_glyph_buffer_t *buffer)
{
uxa_composite_rects(PictOpAdd, buffer->source, pMask,
buffer->count, buffer->rects);
buffer->count = 0;
buffer->source = NULL;
}
static void
uxa_glyphs_to_dst(CARD8 op,
PicturePtr pSrc,
PicturePtr pDst,
uxa_glyph_buffer_t *buffer,
INT16 xSrc,
INT16 ySrc,
INT16 xDst,
INT16 yDst)
{
int i;
for (i = 0; i < buffer->count; i++) {
uxa_composite_rect_t *rect = &buffer->rects[i];
CompositePicture (op,
pSrc,
buffer->source,
pDst,
xSrc + rect->xDst - xDst,
ySrc + rect->yDst - yDst,
rect->xSrc,
rect->ySrc,
rect->xDst,
rect->yDst,
rect->width,
rect->height);
}
buffer->count = 0;
buffer->source = NULL;
}
/* Cut and paste from render/glyph.c - probably should export it instead */
static void
uxa_glyph_extents (int nlist,
GlyphListPtr list,
GlyphPtr *glyphs,
BoxPtr extents)
{
int x1, x2, y1, y2;
int n;
GlyphPtr glyph;
int x, y;
x = 0;
y = 0;
extents->x1 = MAXSHORT;
extents->x2 = MINSHORT;
extents->y1 = MAXSHORT;
extents->y2 = MINSHORT;
while (nlist--)
{
x += list->xOff;
y += list->yOff;
n = list->len;
list++;
while (n--)
{
glyph = *glyphs++;
x1 = x - glyph->info.x;
if (x1 < MINSHORT)
x1 = MINSHORT;
y1 = y - glyph->info.y;
if (y1 < MINSHORT)
y1 = MINSHORT;
x2 = x1 + glyph->info.width;
if (x2 > MAXSHORT)
x2 = MAXSHORT;
y2 = y1 + glyph->info.height;
if (y2 > MAXSHORT)
y2 = MAXSHORT;
if (x1 < extents->x1)
extents->x1 = x1;
if (x2 > extents->x2)
extents->x2 = x2;
if (y1 < extents->y1)
extents->y1 = y1;
if (y2 > extents->y2)
extents->y2 = y2;
x += glyph->info.xOff;
y += glyph->info.yOff;
}
}
}
/**
* Returns TRUE if the glyphs in the lists intersect. Only checks based on
* bounding box, which appears to be good enough to catch most cases at least.
*/
static Bool
uxa_glyphs_intersect(int nlist, GlyphListPtr list, GlyphPtr *glyphs)
{
int x1, x2, y1, y2;
int n;
GlyphPtr glyph;
int x, y;
BoxRec extents;
Bool first = TRUE;
x = 0;
y = 0;
while (nlist--) {
x += list->xOff;
y += list->yOff;
n = list->len;
list++;
while (n--) {
glyph = *glyphs++;
if (glyph->info.width == 0 || glyph->info.height == 0) {
x += glyph->info.xOff;
y += glyph->info.yOff;
continue;
}
x1 = x - glyph->info.x;
if (x1 < MINSHORT)
x1 = MINSHORT;
y1 = y - glyph->info.y;
if (y1 < MINSHORT)
y1 = MINSHORT;
x2 = x1 + glyph->info.width;
if (x2 > MAXSHORT)
x2 = MAXSHORT;
y2 = y1 + glyph->info.height;
if (y2 > MAXSHORT)
y2 = MAXSHORT;
if (first) {
extents.x1 = x1;
extents.y1 = y1;
extents.x2 = x2;
extents.y2 = y2;
first = FALSE;
} else {
if (x1 < extents.x2 && x2 > extents.x1 &&
y1 < extents.y2 && y2 > extents.y1)
{
return TRUE;
}
if (x1 < extents.x1)
extents.x1 = x1;
if (x2 > extents.x2)
extents.x2 = x2;
if (y1 < extents.y1)
extents.y1 = y1;
if (y2 > extents.y2)
extents.y2 = y2;
}
x += glyph->info.xOff;
y += glyph->info.yOff;
}
}
return FALSE;
}
#define NeedsComponent(f) (PICT_FORMAT_A(f) != 0 && PICT_FORMAT_RGB(f) != 0)
void
uxa_glyphs (CARD8 op,
PicturePtr pSrc,
PicturePtr pDst,
PictFormatPtr maskFormat,
INT16 xSrc,
INT16 ySrc,
int nlist,
GlyphListPtr list,
GlyphPtr *glyphs)
{
PicturePtr pPicture;
PixmapPtr pMaskPixmap = 0;
PicturePtr pMask;
ScreenPtr pScreen = pDst->pDrawable->pScreen;
int width = 0, height = 0;
int x, y;
int xDst = list->xOff, yDst = list->yOff;
int n;
GlyphPtr glyph;
int error;
BoxRec extents = {0, 0, 0, 0};
CARD32 component_alpha;
uxa_glyph_buffer_t buffer;
/* If we don't have a mask format but all the glyphs have the same format
* and don't intersect, use the glyph format as mask format for the full
* benefits of the glyph cache.
*/
if (!maskFormat) {
Bool sameFormat = TRUE;
int i;
maskFormat = list[0].format;
for (i = 0; i < nlist; i++) {
if (maskFormat->format != list[i].format->format) {
sameFormat = FALSE;
break;
}
}
if (!sameFormat || (maskFormat->depth != 1 &&
uxa_glyphs_intersect(nlist, list, glyphs))) {
maskFormat = NULL;
}
}
if (maskFormat)
{
GCPtr pGC;
xRectangle rect;
uxa_glyph_extents (nlist, list, glyphs, &extents);
if (extents.x2 <= extents.x1 || extents.y2 <= extents.y1)
return;
width = extents.x2 - extents.x1;
height = extents.y2 - extents.y1;
if (maskFormat->depth == 1) {
PictFormatPtr a8Format = PictureMatchFormat (pScreen, 8, PICT_a8);
if (a8Format)
maskFormat = a8Format;
}
pMaskPixmap = (*pScreen->CreatePixmap) (pScreen, width, height,
maskFormat->depth,
CREATE_PIXMAP_USAGE_SCRATCH);
if (!pMaskPixmap)
return;
component_alpha = NeedsComponent(maskFormat->format);
pMask = CreatePicture (0, &pMaskPixmap->drawable,
maskFormat, CPComponentAlpha, &component_alpha,
serverClient, &error);
if (!pMask)
{
(*pScreen->DestroyPixmap) (pMaskPixmap);
return;
}
pGC = GetScratchGC (pMaskPixmap->drawable.depth, pScreen);
ValidateGC (&pMaskPixmap->drawable, pGC);
rect.x = 0;
rect.y = 0;
rect.width = width;
rect.height = height;
(*pGC->ops->PolyFillRect) (&pMaskPixmap->drawable, pGC, 1, &rect);
FreeScratchGC (pGC);
x = -extents.x1;
y = -extents.y1;
}
else
{
pMask = pDst;
x = 0;
y = 0;
}
buffer.count = 0;
buffer.source = NULL;
while (nlist--)
{
x += list->xOff;
y += list->yOff;
n = list->len;
while (n--)
{
glyph = *glyphs++;
pPicture = GlyphPicture (glyph)[pScreen->myNum];
if (glyph->info.width > 0 && glyph->info.height > 0 &&
uxa_buffer_glyph(pScreen, &buffer, glyph, x, y) == UXA_GLYPH_NEED_FLUSH)
{
if (maskFormat)
uxa_glyphs_to_mask(pMask, &buffer);
else
uxa_glyphs_to_dst(op, pSrc, pDst, &buffer,
xSrc, ySrc, xDst, yDst);
uxa_buffer_glyph(pScreen, &buffer, glyph, x, y);
}
x += glyph->info.xOff;
y += glyph->info.yOff;
}
list++;
}
if (maskFormat)
uxa_glyphs_to_mask(pMask, &buffer);
else
uxa_glyphs_to_dst(op, pSrc, pDst, &buffer,
xSrc, ySrc, xDst, yDst);
if (maskFormat)
{
x = extents.x1;
y = extents.y1;
CompositePicture (op,
pSrc,
pMask,
pDst,
xSrc + x - xDst,
ySrc + y - yDst,
0, 0,
x, y,
width, height);
FreePicture ((pointer) pMask, (XID) 0);
(*pScreen->DestroyPixmap) (pMaskPixmap);
}
}

443
uxa/uxa-priv.h Normal file
View File

@ -0,0 +1,443 @@
/*
*
* Copyright © 2000,2008 Keith Packard
* 2005 Zack Rusin, Trolltech
*
* Permission to use, copy, modify, distribute, and sell this software and its
* documentation for any purpose is hereby granted without fee, provided that
* the above copyright notice appear in all copies and that both that
* copyright notice and this permission notice appear in supporting
* documentation, and that the name of Keith Packard not be used in
* advertising or publicity pertaining to distribution of the software without
* specific, written prior permission. Keith Packard makes no
* representations about the suitability of this software for any purpose. It
* is provided "as is" without express or implied warranty.
*
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
* SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
* SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
* AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
* SOFTWARE.
*/
#ifndef UXAPRIV_H
#define UXAPRIV_H
#ifdef HAVE_DIX_CONFIG_H
#include <dix-config.h>
#else
#include <xorg-server.h>
#endif
#include "uxa.h"
#include <X11/X.h>
#define NEED_EVENTS
#include <X11/Xproto.h>
#ifdef MITSHM
#define _XSHM_SERVER_
#include <X11/extensions/shmstr.h>
#endif
#include "scrnintstr.h"
#include "pixmapstr.h"
#include "windowstr.h"
#include "servermd.h"
#include "mibstore.h"
#include "colormapst.h"
#include "gcstruct.h"
#include "input.h"
#include "mipointer.h"
#include "mi.h"
#include "dix.h"
#include "fb.h"
#include "fboverlay.h"
#ifdef RENDER
//#include "fbpict.h"
#include "glyphstr.h"
#endif
#include "damage.h"
#define DEBUG_TRACE_FALL 0
#define DEBUG_MIGRATE 0
#define DEBUG_PIXMAP 0
#define DEBUG_OFFSCREEN 0
#define DEBUG_GLYPH_CACHE 0
#if DEBUG_TRACE_FALL
#define UXA_FALLBACK(x) \
do { \
ErrorF("UXA fallback at %s: ", __FUNCTION__); \
ErrorF x; \
} while (0)
char
uxa_drawable_location(DrawablePtr pDrawable);
#else
#define UXA_FALLBACK(x)
#endif
#if DEBUG_PIXMAP
#define DBG_PIXMAP(a) ErrorF a
#else
#define DBG_PIXMAP(a)
#endif
typedef struct {
unsigned char sha1[20];
} uxa_cached_glyph_t;
typedef struct {
/* The identity of the cache, statically configured at initialization */
unsigned int format;
int glyphWidth;
int glyphHeight;
int size; /* Size of cache; eventually this should be dynamically determined */
/* Hash table mapping from glyph sha1 to position in the glyph; we use
* open addressing with a hash table size determined based on size and large
* enough so that we always have a good amount of free space, so we can
* use linear probing. (Linear probing is preferrable to double hashing
* here because it allows us to easily remove entries.)
*/
int *hashEntries;
int hashSize;
uxa_cached_glyph_t *glyphs;
int glyphCount; /* Current number of glyphs */
PicturePtr picture; /* Where the glyphs of the cache are stored */
int yOffset; /* y location within the picture where the cache starts */
int columns; /* Number of columns the glyphs are layed out in */
int evictionPosition; /* Next random position to evict a glyph */
} uxa_glyph_cache_t;
#define UXA_NUM_GLYPH_CACHES 4
typedef struct {
uxa_driver_t *info;
CreateGCProcPtr SavedCreateGC;
CloseScreenProcPtr SavedCloseScreen;
GetImageProcPtr SavedGetImage;
GetSpansProcPtr SavedGetSpans;
CreatePixmapProcPtr SavedCreatePixmap;
DestroyPixmapProcPtr SavedDestroyPixmap;
CopyWindowProcPtr SavedCopyWindow;
ChangeWindowAttributesProcPtr SavedChangeWindowAttributes;
BitmapToRegionProcPtr SavedBitmapToRegion;
#ifdef RENDER
CompositeProcPtr SavedComposite;
TrianglesProcPtr SavedTriangles;
GlyphsProcPtr SavedGlyphs;
TrapezoidsProcPtr SavedTrapezoids;
AddTrapsProcPtr SavedAddTraps;
#endif
Bool swappedOut;
unsigned disableFbCount;
unsigned offScreenCounter;
uxa_glyph_cache_t glyphCaches[UXA_NUM_GLYPH_CACHES];
} uxa_screen_t;
/*
* This is the only completely portable way to
* compute this info.
*/
#ifndef BitsPerPixel
#define BitsPerPixel(d) (\
PixmapWidthPaddingInfo[d].notPower2 ? \
(PixmapWidthPaddingInfo[d].bytesPerPixel * 8) : \
((1 << PixmapWidthPaddingInfo[d].padBytesLog2) * 8 / \
(PixmapWidthPaddingInfo[d].padRoundUp+1)))
#endif
extern DevPrivateKey uxa_screen_key;
#define uxa_get_screen(s) ((uxa_screen_t *)dixLookupPrivate(&(s)->devPrivates, uxa_screen_key))
/** Align an offset to an arbitrary alignment */
#define UXA_ALIGN(offset, align) (((offset) + (align) - 1) - \
(((offset) + (align) - 1) % (align)))
/** Align an offset to a power-of-two alignment */
#define UXA_ALIGN2(offset, align) (((offset) + (align) - 1) & ~((align) - 1))
typedef struct {
INT16 xSrc;
INT16 ySrc;
INT16 xDst;
INT16 yDst;
INT16 width;
INT16 height;
} uxa_composite_rect_t;
/**
* exaDDXDriverInit must be implemented by the DDX using EXA, and is the place
* to set EXA options or hook in screen functions to handle using EXA as the AA.
*/
void exaDDXDriverInit (ScreenPtr pScreen);
void
uxa_prepare_access_window(WindowPtr pWin);
void
uxa_finish_access_window(WindowPtr pWin);
/* uxa-unaccel.c */
void
uxa_prepare_access_gc(GCPtr pGC);
void
uxa_finish_access_gc(GCPtr pGC);
void
uxa_check_fill_spans (DrawablePtr pDrawable, GCPtr pGC, int nspans,
DDXPointPtr ppt, int *pwidth, int fSorted);
void
uxa_check_set_spans (DrawablePtr pDrawable, GCPtr pGC, char *psrc,
DDXPointPtr ppt, int *pwidth, int nspans, int fSorted);
void
uxa_check_put_image (DrawablePtr pDrawable, GCPtr pGC, int depth,
int x, int y, int w, int h, int leftPad, int format,
char *bits);
RegionPtr
uxa_check_copy_area (DrawablePtr pSrc, DrawablePtr pDst, GCPtr pGC,
int srcx, int srcy, int w, int h, int dstx, int dsty);
RegionPtr
uxa_check_copy_plane (DrawablePtr pSrc, DrawablePtr pDst, GCPtr pGC,
int srcx, int srcy, int w, int h, int dstx, int dsty,
unsigned long bitPlane);
void
uxa_check_poly_point (DrawablePtr pDrawable, GCPtr pGC, int mode, int npt,
DDXPointPtr pptInit);
void
uxa_check_poly_lines (DrawablePtr pDrawable, GCPtr pGC,
int mode, int npt, DDXPointPtr ppt);
void
uxa_check_poly_segment (DrawablePtr pDrawable, GCPtr pGC,
int nsegInit, xSegment *pSegInit);
void
uxa_check_poly_arc (DrawablePtr pDrawable, GCPtr pGC,
int narcs, xArc *pArcs);
void
uxa_check_poly_fill_rect (DrawablePtr pDrawable, GCPtr pGC,
int nrect, xRectangle *prect);
void
uxa_check_image_glyph_blt (DrawablePtr pDrawable, GCPtr pGC,
int x, int y, unsigned int nglyph,
CharInfoPtr *ppci, pointer pglyphBase);
void
uxa_check_poly_glyph_blt (DrawablePtr pDrawable, GCPtr pGC,
int x, int y, unsigned int nglyph,
CharInfoPtr *ppci, pointer pglyphBase);
void
uxa_check_push_pixels (GCPtr pGC, PixmapPtr pBitmap,
DrawablePtr pDrawable,
int w, int h, int x, int y);
void
uxa_check_get_spans (DrawablePtr pDrawable,
int wMax,
DDXPointPtr ppt,
int *pwidth,
int nspans,
char *pdstStart);
void
uxa_check_add_traps (PicturePtr pPicture,
INT16 x_off,
INT16 y_off,
int ntrap,
xTrap *traps);
/* uxa-accel.c */
static _X_INLINE Bool
uxa_gc_reads_destination(DrawablePtr pDrawable, unsigned long planemask,
unsigned int fillStyle, unsigned char alu)
{
return ((alu != GXcopy && alu != GXclear &&alu != GXset &&
alu != GXcopyInverted) || fillStyle == FillStippled ||
!UXA_PM_IS_SOLID(pDrawable, planemask));
}
void
uxa_copy_window(WindowPtr pWin, DDXPointRec ptOldOrg, RegionPtr prgnSrc);
Bool
uxa_fill_region_tiled (DrawablePtr pDrawable, RegionPtr pRegion, PixmapPtr pTile,
DDXPointPtr pPatOrg, CARD32 planemask, CARD32 alu);
void
uxa_shm_put_image(DrawablePtr pDrawable, GCPtr pGC, int depth, unsigned int format,
int w, int h, int sx, int sy, int sw, int sh, int dx, int dy,
char *data);
void
uxa_get_image (DrawablePtr pDrawable, int x, int y, int w, int h,
unsigned int format, unsigned long planeMask, char *d);
extern const GCOps uxa_ops;
#ifdef MITSHM
extern ShmFuncs uxa_shm_funcs;
/* XXX these come from shmint.h, which isn't exported by the server */
void
ShmRegisterFuncs(ScreenPtr pScreen, ShmFuncsPtr funcs);
void
ShmSetPixmapFormat(ScreenPtr pScreen, int format);
void
fbShmPutImage(XSHM_PUT_IMAGE_ARGS);
#endif
#ifdef RENDER
/* XXX these are in fbpict.h, which is not installed */
void
fbComposite (CARD8 op,
PicturePtr pSrc,
PicturePtr pMask,
PicturePtr pDst,
INT16 xSrc,
INT16 ySrc,
INT16 xMask,
INT16 yMask,
INT16 xDst,
INT16 yDst,
CARD16 width,
CARD16 height);
void
fbAddTraps (PicturePtr pPicture,
INT16 xOff,
INT16 yOff,
int ntrap,
xTrap *traps);
void
uxa_check_composite (CARD8 op,
PicturePtr pSrc,
PicturePtr pMask,
PicturePtr pDst,
INT16 xSrc,
INT16 ySrc,
INT16 xMask,
INT16 yMask,
INT16 xDst,
INT16 yDst,
CARD16 width,
CARD16 height);
#endif
/* uxa.c */
void
uxa_prepare_access(DrawablePtr pDrawable, uxa_access_t access);
void
uxa_finish_access(DrawablePtr pDrawable);
void
uxa_get_drawable_deltas (DrawablePtr pDrawable, PixmapPtr pPixmap,
int *xp, int *yp);
Bool
uxa_drawable_is_offscreen (DrawablePtr pDrawable);
Bool
uxa_pixmap_is_offscreen(PixmapPtr p);
PixmapPtr
uxa_get_offscreen_pixmap (DrawablePtr pDrawable, int *xp, int *yp);
PixmapPtr
uxa_get_drawable_pixmap(DrawablePtr pDrawable);
RegionPtr
uxa_copy_area(DrawablePtr pSrcDrawable, DrawablePtr pDstDrawable, GCPtr pGC,
int srcx, int srcy, int width, int height, int dstx, int dsty);
void
uxa_copy_n_to_n (DrawablePtr pSrcDrawable,
DrawablePtr pDstDrawable,
GCPtr pGC,
BoxPtr pbox,
int nbox,
int dx,
int dy,
Bool reverse,
Bool upsidedown,
Pixel bitplane,
void *closure);
/* uxa_render.c */
Bool
uxa_op_reads_destination (CARD8 op);
void
uxa_composite(CARD8 op,
PicturePtr pSrc,
PicturePtr pMask,
PicturePtr pDst,
INT16 xSrc,
INT16 ySrc,
INT16 xMask,
INT16 yMask,
INT16 xDst,
INT16 yDst,
CARD16 width,
CARD16 height);
void
uxa_composite_rects(CARD8 op,
PicturePtr pSrc,
PicturePtr pDst,
int nrect,
uxa_composite_rect_t *rects);
void
uxa_trapezoids (CARD8 op, PicturePtr pSrc, PicturePtr pDst,
PictFormatPtr maskFormat, INT16 xSrc, INT16 ySrc,
int ntrap, xTrapezoid *traps);
void
uxa_triangles (CARD8 op, PicturePtr pSrc, PicturePtr pDst,
PictFormatPtr maskFormat, INT16 xSrc, INT16 ySrc,
int ntri, xTriangle *tris);
/* uxa_glyph.c */
void
uxa_glyphs_init(ScreenPtr pScreen);
void
uxa_glyphs_fini (ScreenPtr pScreen);
void
uxa_glyphs (CARD8 op,
PicturePtr pSrc,
PicturePtr pDst,
PictFormatPtr maskFormat,
INT16 xSrc,
INT16 ySrc,
int nlist,
GlyphListPtr list,
GlyphPtr *glyphs);
#endif /* UXAPRIV_H */

1015
uxa/uxa-render.c Normal file

File diff suppressed because it is too large Load Diff

370
uxa/uxa-unaccel.c Normal file
View File

@ -0,0 +1,370 @@
/*
*
* Copyright © 1999 Keith Packard
*
* Permission to use, copy, modify, distribute, and sell this software and its
* documentation for any purpose is hereby granted without fee, provided that
* the above copyright notice appear in all copies and that both that
* copyright notice and this permission notice appear in supporting
* documentation, and that the name of Keith Packard not be used in
* advertising or publicity pertaining to distribution of the software without
* specific, written prior permission. Keith Packard makes no
* representations about the suitability of this software for any purpose. It
* is provided "as is" without express or implied warranty.
*
* KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
* EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THIS SOFTWARE.
*/
#include "uxa-priv.h"
#ifdef RENDER
#include "mipict.h"
#endif
/*
* These functions wrap the low-level fb rendering functions and
* synchronize framebuffer/accelerated drawing by stalling until
* the accelerator is idle
*/
/**
* Calls uxa_prepare_access with UXA_PREPARE_SRC for the tile, if that is the
* current fill style.
*
* Solid doesn't use an extra pixmap source, and Stippled/OpaqueStippled are
* 1bpp and never in fb, so we don't worry about them.
* We should worry about them for completeness sake and going forward.
*/
void
uxa_prepare_access_gc(GCPtr pGC)
{
if (pGC->stipple)
uxa_prepare_access(&pGC->stipple->drawable, UXA_ACCESS_RO);
if (pGC->fillStyle == FillTiled)
uxa_prepare_access(&pGC->tile.pixmap->drawable, UXA_ACCESS_RO);
}
/**
* Finishes access to the tile in the GC, if used.
*/
void
uxa_finish_access_gc(GCPtr pGC)
{
if (pGC->fillStyle == FillTiled)
uxa_finish_access(&pGC->tile.pixmap->drawable);
if (pGC->stipple)
uxa_finish_access(&pGC->stipple->drawable);
}
#if DEBUG_TRACE_FALL
char
uxa_drawable_location(DrawablePtr pDrawable)
{
return uxa_drawable_is_offscreen(pDrawable) ? 's' : 'm';
}
#endif /* DEBUG_TRACE_FALL */
void
uxa_check_fill_spans (DrawablePtr pDrawable, GCPtr pGC, int nspans,
DDXPointPtr ppt, int *pwidth, int fSorted)
{
UXA_FALLBACK(("to %p (%c)\n", pDrawable, uxa_drawable_location(pDrawable)));
uxa_prepare_access (pDrawable, UXA_ACCESS_RW);
uxa_prepare_access_gc (pGC);
fbFillSpans (pDrawable, pGC, nspans, ppt, pwidth, fSorted);
uxa_finish_access_gc (pGC);
uxa_finish_access (pDrawable);
}
void
uxa_check_set_spans (DrawablePtr pDrawable, GCPtr pGC, char *psrc,
DDXPointPtr ppt, int *pwidth, int nspans, int fSorted)
{
UXA_FALLBACK(("to %p (%c)\n", pDrawable, uxa_drawable_location(pDrawable)));
uxa_prepare_access (pDrawable, UXA_ACCESS_RW);
fbSetSpans (pDrawable, pGC, psrc, ppt, pwidth, nspans, fSorted);
uxa_finish_access (pDrawable);
}
void
uxa_check_put_image (DrawablePtr pDrawable, GCPtr pGC, int depth,
int x, int y, int w, int h, int leftPad, int format,
char *bits)
{
UXA_FALLBACK(("to %p (%c)\n", pDrawable, uxa_drawable_location(pDrawable)));
uxa_prepare_access (pDrawable, UXA_ACCESS_RW);
fbPutImage (pDrawable, pGC, depth, x, y, w, h, leftPad, format, bits);
uxa_finish_access (pDrawable);
}
RegionPtr
uxa_check_copy_area (DrawablePtr pSrc, DrawablePtr pDst, GCPtr pGC,
int srcx, int srcy, int w, int h, int dstx, int dsty)
{
RegionPtr ret;
UXA_FALLBACK(("from %p to %p (%c,%c)\n", pSrc, pDst,
uxa_drawable_location(pSrc), uxa_drawable_location(pDst)));
uxa_prepare_access (pDst, UXA_ACCESS_RW);
uxa_prepare_access (pSrc, UXA_ACCESS_RO);
ret = fbCopyArea (pSrc, pDst, pGC, srcx, srcy, w, h, dstx, dsty);
uxa_finish_access (pSrc);
uxa_finish_access (pDst);
return ret;
}
RegionPtr
uxa_check_copy_plane (DrawablePtr pSrc, DrawablePtr pDst, GCPtr pGC,
int srcx, int srcy, int w, int h, int dstx, int dsty,
unsigned long bitPlane)
{
RegionPtr ret;
UXA_FALLBACK(("from %p to %p (%c,%c)\n", pSrc, pDst,
uxa_drawable_location(pSrc), uxa_drawable_location(pDst)));
uxa_prepare_access (pDst, UXA_ACCESS_RW);
uxa_prepare_access (pSrc, UXA_ACCESS_RO);
ret = fbCopyPlane (pSrc, pDst, pGC, srcx, srcy, w, h, dstx, dsty,
bitPlane);
uxa_finish_access (pSrc);
uxa_finish_access (pDst);
return ret;
}
void
uxa_check_poly_point (DrawablePtr pDrawable, GCPtr pGC, int mode, int npt,
DDXPointPtr pptInit)
{
UXA_FALLBACK(("to %p (%c)\n", pDrawable, uxa_drawable_location(pDrawable)));
uxa_prepare_access (pDrawable, UXA_ACCESS_RW);
fbPolyPoint (pDrawable, pGC, mode, npt, pptInit);
uxa_finish_access (pDrawable);
}
void
uxa_check_poly_lines (DrawablePtr pDrawable, GCPtr pGC,
int mode, int npt, DDXPointPtr ppt)
{
UXA_FALLBACK(("to %p (%c), width %d, mode %d, count %d\n",
pDrawable, uxa_drawable_location(pDrawable),
pGC->lineWidth, mode, npt));
if (pGC->lineWidth == 0) {
uxa_prepare_access (pDrawable, UXA_ACCESS_RW);
uxa_prepare_access_gc (pGC);
fbPolyLine (pDrawable, pGC, mode, npt, ppt);
uxa_finish_access_gc (pGC);
uxa_finish_access (pDrawable);
return;
}
/* fb calls mi functions in the lineWidth != 0 case. */
fbPolyLine (pDrawable, pGC, mode, npt, ppt);
}
void
uxa_check_poly_segment (DrawablePtr pDrawable, GCPtr pGC,
int nsegInit, xSegment *pSegInit)
{
UXA_FALLBACK(("to %p (%c) width %d, count %d\n", pDrawable,
uxa_drawable_location(pDrawable), pGC->lineWidth, nsegInit));
if (pGC->lineWidth == 0) {
uxa_prepare_access (pDrawable, UXA_ACCESS_RW);
uxa_prepare_access_gc (pGC);
fbPolySegment (pDrawable, pGC, nsegInit, pSegInit);
uxa_finish_access_gc (pGC);
uxa_finish_access (pDrawable);
return;
}
/* fb calls mi functions in the lineWidth != 0 case. */
fbPolySegment (pDrawable, pGC, nsegInit, pSegInit);
}
void
uxa_check_poly_arc (DrawablePtr pDrawable, GCPtr pGC,
int narcs, xArc *pArcs)
{
UXA_FALLBACK(("to %p (%c)\n", pDrawable, uxa_drawable_location(pDrawable)));
/* Disable this as fbPolyArc can call miZeroPolyArc which in turn
* can call accelerated functions, that as yet, haven't been notified
* with uxa_finish_access().
*/
#if 0
if (pGC->lineWidth == 0)
{
uxa_prepare_access (pDrawable, UXA_ACCESS_RW);
uxa_prepare_access_gc (pGC);
fbPolyArc (pDrawable, pGC, narcs, pArcs);
uxa_finish_access_gc (pGC);
uxa_finish_access (pDrawable);
return;
}
#endif
miPolyArc (pDrawable, pGC, narcs, pArcs);
}
void
uxa_check_poly_fill_rect (DrawablePtr pDrawable, GCPtr pGC,
int nrect, xRectangle *prect)
{
UXA_FALLBACK(("to %p (%c)\n", pDrawable, uxa_drawable_location(pDrawable)));
uxa_prepare_access (pDrawable, UXA_ACCESS_RW);
uxa_prepare_access_gc (pGC);
fbPolyFillRect (pDrawable, pGC, nrect, prect);
uxa_finish_access_gc (pGC);
uxa_finish_access (pDrawable);
}
void
uxa_check_image_glyph_blt (DrawablePtr pDrawable, GCPtr pGC,
int x, int y, unsigned int nglyph,
CharInfoPtr *ppci, pointer pglyphBase)
{
UXA_FALLBACK(("to %p (%c)\n", pDrawable,
uxa_drawable_location(pDrawable)));
uxa_prepare_access (pDrawable, UXA_ACCESS_RW);
uxa_prepare_access_gc (pGC);
fbImageGlyphBlt (pDrawable, pGC, x, y, nglyph, ppci, pglyphBase);
uxa_finish_access_gc (pGC);
uxa_finish_access (pDrawable);
}
void
uxa_check_poly_glyph_blt (DrawablePtr pDrawable, GCPtr pGC,
int x, int y, unsigned int nglyph,
CharInfoPtr *ppci, pointer pglyphBase)
{
UXA_FALLBACK(("to %p (%c), style %d alu %d\n", pDrawable,
uxa_drawable_location(pDrawable), pGC->fillStyle, pGC->alu));
uxa_prepare_access (pDrawable, UXA_ACCESS_RW);
uxa_prepare_access_gc (pGC);
fbPolyGlyphBlt (pDrawable, pGC, x, y, nglyph, ppci, pglyphBase);
uxa_finish_access_gc (pGC);
uxa_finish_access (pDrawable);
}
void
uxa_check_push_pixels (GCPtr pGC, PixmapPtr pBitmap,
DrawablePtr pDrawable,
int w, int h, int x, int y)
{
UXA_FALLBACK(("from %p to %p (%c,%c)\n", pBitmap, pDrawable,
uxa_drawable_location(&pBitmap->drawable),
uxa_drawable_location(pDrawable)));
uxa_prepare_access (pDrawable, UXA_ACCESS_RW);
uxa_prepare_access (&pBitmap->drawable, UXA_ACCESS_RO);
uxa_prepare_access_gc (pGC);
fbPushPixels (pGC, pBitmap, pDrawable, w, h, x, y);
uxa_finish_access_gc (pGC);
uxa_finish_access (&pBitmap->drawable);
uxa_finish_access (pDrawable);
}
void
uxa_check_get_spans (DrawablePtr pDrawable,
int wMax,
DDXPointPtr ppt,
int *pwidth,
int nspans,
char *pdstStart)
{
UXA_FALLBACK(("from %p (%c)\n", pDrawable, uxa_drawable_location(pDrawable)));
uxa_prepare_access (pDrawable, UXA_ACCESS_RO);
fbGetSpans (pDrawable, wMax, ppt, pwidth, nspans, pdstStart);
uxa_finish_access (pDrawable);
}
void
uxa_check_composite (CARD8 op,
PicturePtr pSrc,
PicturePtr pMask,
PicturePtr pDst,
INT16 xSrc,
INT16 ySrc,
INT16 xMask,
INT16 yMask,
INT16 xDst,
INT16 yDst,
CARD16 width,
CARD16 height)
{
UXA_FALLBACK(("from picts %p/%p to pict %p\n",
pSrc, pMask, pDst));
uxa_prepare_access (pDst->pDrawable, UXA_ACCESS_RW);
if (pSrc->pDrawable != NULL)
uxa_prepare_access (pSrc->pDrawable, UXA_ACCESS_RO);
if (pMask && pMask->pDrawable != NULL)
uxa_prepare_access (pMask->pDrawable, UXA_ACCESS_RO);
fbComposite (op,
pSrc,
pMask,
pDst,
xSrc,
ySrc,
xMask,
yMask,
xDst,
yDst,
width,
height);
if (pMask && pMask->pDrawable != NULL)
uxa_finish_access (pMask->pDrawable);
if (pSrc->pDrawable != NULL)
uxa_finish_access (pSrc->pDrawable);
uxa_finish_access (pDst->pDrawable);
}
void
uxa_check_add_traps (PicturePtr pPicture,
INT16 x_off,
INT16 y_off,
int ntrap,
xTrap *traps)
{
UXA_FALLBACK(("to pict %p (%c)\n",
uxa_drawable_location(pPicture->pDrawable)));
uxa_prepare_access(pPicture->pDrawable, UXA_ACCESS_RW);
fbAddTraps (pPicture, x_off, y_off, ntrap, traps);
uxa_finish_access(pPicture->pDrawable);
}
/**
* Gets the 0,0 pixel of a pixmap. Used for doing solid fills of tiled pixmaps
* that happen to be 1x1. Pixmap must be at least 8bpp.
*
* XXX This really belongs in fb, so it can be aware of tiling and etc.
*/
CARD32
uxa_get_pixmap_first_pixel (PixmapPtr pPixmap)
{
CARD32 pixel;
void *fb;
uxa_prepare_access (&pPixmap->drawable, UXA_ACCESS_RO);
fb = pPixmap->devPrivate.ptr;
switch (pPixmap->drawable.bitsPerPixel) {
case 32:
pixel = *(CARD32 *)fb;
break;
case 16:
pixel = *(CARD16 *)fb;
break;
default:
pixel = *(CARD8 *)fb;
break;
}
uxa_finish_access(&pPixmap->drawable);
return pixel;
}

510
uxa/uxa.c Normal file
View File

@ -0,0 +1,510 @@
/*
* Copyright © 2001 Keith Packard
*
* Partly based on code that is Copyright © The XFree86 Project Inc.
*
* Permission to use, copy, modify, distribute, and sell this software and its
* documentation for any purpose is hereby granted without fee, provided that
* the above copyright notice appear in all copies and that both that
* copyright notice and this permission notice appear in supporting
* documentation, and that the name of Keith Packard not be used in
* advertising or publicity pertaining to distribution of the software without
* specific, written prior permission. Keith Packard makes no
* representations about the suitability of this software for any purpose. It
* is provided "as is" without express or implied warranty.
*
* KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
* EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THIS SOFTWARE.
*/
/** @file
* This file covers the initialization and teardown of UXA, and has various
* functions not responsible for performing rendering, pixmap migration, or
* memory management.
*/
#ifdef HAVE_DIX_CONFIG_H
#include <dix-config.h>
#endif
#include <stdlib.h>
#include "uxa-priv.h"
#include <X11/fonts/fontstruct.h>
#include "dixfontstr.h"
#include "uxa.h"
DevPrivateKey uxa_screen_key = &uxa_screen_key;
/**
* uxa_get_drawable_pixmap() returns a backing pixmap for a given drawable.
*
* @param pDrawable the drawable being requested.
*
* This function returns the backing pixmap for a drawable, whether it is a
* redirected window, unredirected window, or already a pixmap. Note that
* coordinate translation is needed when drawing to the backing pixmap of a
* redirected window, and the translation coordinates are provided by calling
* uxa_get_drawable_pixmap() on the drawable.
*/
PixmapPtr
uxa_get_drawable_pixmap(DrawablePtr pDrawable)
{
if (pDrawable->type == DRAWABLE_WINDOW)
return pDrawable->pScreen->GetWindowPixmap ((WindowPtr) pDrawable);
else
return (PixmapPtr) pDrawable;
}
/**
* Sets the offsets to add to coordinates to make them address the same bits in
* the backing drawable. These coordinates are nonzero only for redirected
* windows.
*/
void
uxa_get_drawable_deltas (DrawablePtr pDrawable, PixmapPtr pPixmap,
int *xp, int *yp)
{
#ifdef COMPOSITE
if (pDrawable->type == DRAWABLE_WINDOW) {
*xp = -pPixmap->screen_x;
*yp = -pPixmap->screen_y;
return;
}
#endif
*xp = 0;
*yp = 0;
}
/**
* uxa_pixmap_is_offscreen() is used to determine if a pixmap is in offscreen
* memory, meaning that acceleration could probably be done to it, and that it
* will need to be wrapped by PrepareAccess()/FinishAccess() when accessing it
* with the CPU.
*
* Note that except for UploadToScreen()/DownloadFromScreen() (which explicitly
* deal with moving pixmaps in and out of system memory), UXA will give drivers
* pixmaps as arguments for which uxa_pixmap_is_offscreen() is TRUE.
*
* @return TRUE if the given drawable is in framebuffer memory.
*/
Bool
uxa_pixmap_is_offscreen(PixmapPtr p)
{
ScreenPtr pScreen = p->drawable.pScreen;
uxa_screen_t *uxa_screen = uxa_get_screen(pScreen);
if (uxa_screen->info->pixmap_is_offscreen)
return uxa_screen->info->pixmap_is_offscreen(p);
return FALSE;
}
/**
* uxa_drawable_is_offscreen() is a convenience wrapper for uxa_pixmap_is_offscreen().
*/
Bool
uxa_drawable_is_offscreen (DrawablePtr pDrawable)
{
return uxa_pixmap_is_offscreen (uxa_get_drawable_pixmap (pDrawable));
}
/**
* Returns the pixmap which backs a drawable, and the offsets to add to
* coordinates to make them address the same bits in the backing drawable.
*/
PixmapPtr
uxa_get_offscreen_pixmap (DrawablePtr drawable, int *xp, int *yp)
{
PixmapPtr pixmap = uxa_get_drawable_pixmap (drawable);
uxa_get_drawable_deltas (drawable, pixmap, xp, yp);
if (uxa_pixmap_is_offscreen (pixmap))
return pixmap;
else
return NULL;
}
/**
* uxa_prepare_access() is UXA's wrapper for the driver's PrepareAccess() handler.
*
* It deals with waiting for synchronization with the card, determining if
* PrepareAccess() is necessary, and working around PrepareAccess() failure.
*/
void
uxa_prepare_access(DrawablePtr pDrawable, uxa_access_t access)
{
ScreenPtr pScreen = pDrawable->pScreen;
uxa_screen_t *uxa_screen = uxa_get_screen(pScreen);
PixmapPtr pPixmap = uxa_get_drawable_pixmap (pDrawable);
Bool offscreen = uxa_pixmap_is_offscreen(pPixmap);
if (!offscreen)
return;
if (uxa_screen->info->prepare_access)
(*uxa_screen->info->prepare_access) (pPixmap, access);
}
/**
* uxa_finish_access() is UXA's wrapper for the driver's finish_access() handler.
*
* It deals with calling the driver's finish_access() only if necessary.
*/
void
uxa_finish_access(DrawablePtr pDrawable)
{
ScreenPtr pScreen = pDrawable->pScreen;
uxa_screen_t *uxa_screen = uxa_get_screen(pScreen);
PixmapPtr pPixmap = uxa_get_drawable_pixmap (pDrawable);
if (uxa_screen->info->finish_access == NULL)
return;
if (!uxa_pixmap_is_offscreen (pPixmap))
return;
(*uxa_screen->info->finish_access) (pPixmap);
}
/**
* uxa_validate_gc() sets the ops to UXA's implementations, which may be
* accelerated or may sync the card and fall back to fb.
*/
static void
uxa_validate_gc (GCPtr pGC, unsigned long changes, DrawablePtr pDrawable)
{
/* fbValidateGC will do direct access to pixmaps if the tiling has changed.
* Preempt fbValidateGC by doing its work and masking the change out, so
* that we can do the Prepare/finish_access.
*/
#ifdef FB_24_32BIT
if ((changes & GCTile) && fbGetRotatedPixmap(pGC)) {
(*pGC->pScreen->DestroyPixmap) (fbGetRotatedPixmap(pGC));
fbGetRotatedPixmap(pGC) = 0;
}
if (pGC->fillStyle == FillTiled) {
PixmapPtr pOldTile, pNewTile;
pOldTile = pGC->tile.pixmap;
if (pOldTile->drawable.bitsPerPixel != pDrawable->bitsPerPixel)
{
pNewTile = fbGetRotatedPixmap(pGC);
if (!pNewTile ||
pNewTile ->drawable.bitsPerPixel != pDrawable->bitsPerPixel)
{
if (pNewTile)
(*pGC->pScreen->DestroyPixmap) (pNewTile);
/* fb24_32ReformatTile will do direct access of a newly-
* allocated pixmap. This isn't a problem yet, since we don't
* put pixmaps in FB until at least one accelerated UXA op.
*/
uxa_prepare_access(&pOldTile->drawable, UXA_ACCESS_RO);
pNewTile = fb24_32ReformatTile (pOldTile,
pDrawable->bitsPerPixel);
uxa_finish_access(&pOldTile->drawable);
}
if (pNewTile)
{
fbGetRotatedPixmap(pGC) = pOldTile;
pGC->tile.pixmap = pNewTile;
changes |= GCTile;
}
}
}
#endif
if (changes & GCTile) {
if (!pGC->tileIsPixel && FbEvenTile (pGC->tile.pixmap->drawable.width *
pDrawable->bitsPerPixel))
{
uxa_prepare_access(&pGC->tile.pixmap->drawable, UXA_ACCESS_RW);
fbPadPixmap (pGC->tile.pixmap);
uxa_finish_access(&pGC->tile.pixmap->drawable);
}
/* Mask out the GCTile change notification, now that we've done FB's
* job for it.
*/
changes &= ~GCTile;
}
uxa_prepare_access_gc(pGC);
fbValidateGC (pGC, changes, pDrawable);
uxa_finish_access_gc(pGC);
pGC->ops = (GCOps *) &uxa_ops;
}
static GCFuncs uxaGCFuncs = {
uxa_validate_gc,
miChangeGC,
miCopyGC,
miDestroyGC,
miChangeClip,
miDestroyClip,
miCopyClip
};
/**
* uxa_create_gc makes a new GC and hooks up its funcs handler, so that
* uxa_validate_gc() will get called.
*/
static int
uxa_create_gc (GCPtr pGC)
{
if (!fbCreateGC (pGC))
return FALSE;
pGC->funcs = &uxaGCFuncs;
return TRUE;
}
void
uxa_prepare_access_window(WindowPtr pWin)
{
if (pWin->backgroundState == BackgroundPixmap)
uxa_prepare_access(&pWin->background.pixmap->drawable, UXA_ACCESS_RO);
if (pWin->borderIsPixel == FALSE)
uxa_prepare_access(&pWin->border.pixmap->drawable, UXA_ACCESS_RO);
}
void
uxa_finish_access_window(WindowPtr pWin)
{
if (pWin->backgroundState == BackgroundPixmap)
uxa_finish_access(&pWin->background.pixmap->drawable);
if (pWin->borderIsPixel == FALSE)
uxa_finish_access(&pWin->border.pixmap->drawable);
}
static Bool
uxa_change_window_attributes(WindowPtr pWin, unsigned long mask)
{
Bool ret;
uxa_prepare_access_window(pWin);
ret = fbChangeWindowAttributes(pWin, mask);
uxa_finish_access_window(pWin);
return ret;
}
static RegionPtr
uxa_bitmap_to_region(PixmapPtr pPix)
{
RegionPtr ret;
uxa_prepare_access(&pPix->drawable, UXA_ACCESS_RO);
ret = fbPixmapToRegion(pPix);
uxa_finish_access(&pPix->drawable);
return ret;
}
/**
* uxa_close_screen() unwraps its wrapped screen functions and tears down UXA's
* screen private, before calling down to the next CloseSccreen.
*/
static Bool
uxa_close_screen(int i, ScreenPtr pScreen)
{
uxa_screen_t *uxa_screen = uxa_get_screen(pScreen);
#ifdef RENDER
PictureScreenPtr ps = GetPictureScreenIfSet(pScreen);
#endif
uxa_glyphs_fini(pScreen);
pScreen->CreateGC = uxa_screen->SavedCreateGC;
pScreen->CloseScreen = uxa_screen->SavedCloseScreen;
pScreen->GetImage = uxa_screen->SavedGetImage;
pScreen->GetSpans = uxa_screen->SavedGetSpans;
pScreen->CreatePixmap = uxa_screen->SavedCreatePixmap;
pScreen->DestroyPixmap = uxa_screen->SavedDestroyPixmap;
pScreen->CopyWindow = uxa_screen->SavedCopyWindow;
pScreen->ChangeWindowAttributes = uxa_screen->SavedChangeWindowAttributes;
pScreen->BitmapToRegion = uxa_screen->SavedBitmapToRegion;
#ifdef RENDER
if (ps) {
ps->Composite = uxa_screen->SavedComposite;
ps->Glyphs = uxa_screen->SavedGlyphs;
ps->Trapezoids = uxa_screen->SavedTrapezoids;
ps->AddTraps = uxa_screen->SavedAddTraps;
ps->Triangles = uxa_screen->SavedTriangles;
}
#endif
xfree (uxa_screen);
return (*pScreen->CloseScreen) (i, pScreen);
}
/**
* This function allocates a driver structure for UXA drivers to fill in. By
* having UXA allocate the structure, the driver structure can be extended
* without breaking ABI between UXA and the drivers. The driver's
* responsibility is to check beforehand that the UXA module has a matching
* major number and sufficient minor. Drivers are responsible for freeing the
* driver structure using xfree().
*
* @return a newly allocated, zero-filled driver structure
*/
uxa_driver_t *
uxa_driver_alloc(void)
{
return xcalloc(1, sizeof(uxa_driver_t));
}
/**
* @param pScreen screen being initialized
* @param pScreenInfo UXA driver record
*
* uxa_driver_init sets up UXA given a driver record filled in by the driver.
* pScreenInfo should have been allocated by uxa_driver_alloc(). See the
* comments in _UxaDriver for what must be filled in and what is optional.
*
* @return TRUE if UXA was successfully initialized.
*/
Bool
uxa_driver_init(ScreenPtr screen, uxa_driver_t *uxa_driver)
{
uxa_screen_t *uxa_screen;
#ifdef RENDER
PictureScreenPtr ps;
#endif
if (!uxa_driver)
return FALSE;
if (uxa_driver->uxa_major != UXA_VERSION_MAJOR ||
uxa_driver->uxa_minor > UXA_VERSION_MINOR)
{
LogMessage(X_ERROR, "UXA(%d): driver's UXA version requirements "
"(%d.%d) are incompatible with UXA version (%d.%d)\n",
screen->myNum,
uxa_driver->uxa_major, uxa_driver->uxa_minor,
UXA_VERSION_MAJOR, UXA_VERSION_MINOR);
return FALSE;
}
if (!uxa_driver->prepare_solid) {
LogMessage(X_ERROR, "UXA(%d): uxa_driver_t::prepare_solid must be "
"non-NULL\n", screen->myNum);
return FALSE;
}
if (!uxa_driver->prepare_copy) {
LogMessage(X_ERROR, "UXA(%d): uxa_driver_t::prepare_copy must be "
"non-NULL\n", screen->myNum);
return FALSE;
}
#ifdef RENDER
ps = GetPictureScreenIfSet(screen);
#endif
uxa_screen = xcalloc (sizeof (uxa_screen_t), 1);
if (!uxa_screen) {
LogMessage(X_WARNING, "UXA(%d): Failed to allocate screen private\n",
screen->myNum);
return FALSE;
}
uxa_screen->info = uxa_driver;
dixSetPrivate(&screen->devPrivates, uxa_screen_key, uxa_screen);
// exaDDXDriverInit(screen);
/*
* Replace various fb screen functions
*/
uxa_screen->SavedCloseScreen = screen->CloseScreen;
screen->CloseScreen = uxa_close_screen;
uxa_screen->SavedCreateGC = screen->CreateGC;
screen->CreateGC = uxa_create_gc;
uxa_screen->SavedGetImage = screen->GetImage;
screen->GetImage = uxa_get_image;
uxa_screen->SavedGetSpans = screen->GetSpans;
screen->GetSpans = uxa_check_get_spans;
uxa_screen->SavedCopyWindow = screen->CopyWindow;
screen->CopyWindow = uxa_copy_window;
uxa_screen->SavedChangeWindowAttributes = screen->ChangeWindowAttributes;
screen->ChangeWindowAttributes = uxa_change_window_attributes;
uxa_screen->SavedBitmapToRegion = screen->BitmapToRegion;
screen->BitmapToRegion = uxa_bitmap_to_region;
#ifdef RENDER
if (ps) {
uxa_screen->SavedComposite = ps->Composite;
ps->Composite = uxa_composite;
uxa_screen->SavedGlyphs = ps->Glyphs;
ps->Glyphs = uxa_glyphs;
uxa_screen->SavedTriangles = ps->Triangles;
ps->Triangles = uxa_triangles;
uxa_screen->SavedTrapezoids = ps->Trapezoids;
ps->Trapezoids = uxa_trapezoids;
uxa_screen->SavedAddTraps = ps->AddTraps;
ps->AddTraps = uxa_check_add_traps;
}
#endif
#ifdef MITSHM
/* Re-register with the MI funcs, which don't allow shared pixmaps.
* Shared pixmaps are almost always a performance loss for us, but this
* still allows for SHM PutImage.
*/
ShmRegisterFuncs(screen, &uxa_shm_funcs);
#endif
uxa_glyphs_init(screen);
LogMessage(X_INFO, "UXA(%d): Driver registered support for the following"
" operations:\n", screen->myNum);
assert(uxa_driver->prepare_solid != NULL);
LogMessage(X_INFO, " solid\n");
assert(uxa_driver->prepare_copy != NULL);
LogMessage(X_INFO, " copy\n");
if (uxa_driver->prepare_composite != NULL) {
LogMessage(X_INFO, " composite (RENDER acceleration)\n");
}
if (uxa_driver->put_image != NULL) {
LogMessage(X_INFO, " put_image\n");
}
if (uxa_driver->get_image != NULL) {
LogMessage(X_INFO, " get_image\n");
}
return TRUE;
}
/**
* uxa_driver_fini tears down UXA on a given screen.
*
* @param pScreen screen being torn down.
*/
void
uxa_driver_fini (ScreenPtr pScreen)
{
/*right now does nothing*/
}

528
uxa/uxa.h Normal file
View File

@ -0,0 +1,528 @@
/*
* Copyright © 2000, 2008 Keith Packard
* 2004 Eric Anholt
* 2005 Zack Rusin
*
* Permission to use, copy, modify, distribute, and sell this software and its
* documentation for any purpose is hereby granted without fee, provided that
* the above copyright notice appear in all copies and that both that
* copyright notice and this permission notice appear in supporting
* documentation, and that the name of copyright holders not be used in
* advertising or publicity pertaining to distribution of the software without
* specific, written prior permission. Copyright holders make no
* representations about the suitability of this software for any purpose. It
* is provided "as is" without express or implied warranty.
*
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
* SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
* SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
* AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
* SOFTWARE.
*/
/** @file
* UXA - the unified memory acceleration architecture.
*
* This is the header containing the public API of UXA for uxa drivers.
*/
#ifndef UXA_H
#define UXA_H
#include "scrnintstr.h"
#include "pixmapstr.h"
#include "windowstr.h"
#include "gcstruct.h"
#include "picturestr.h"
#include "fb.h"
#define UXA_VERSION_MAJOR 1
#define UXA_VERSION_MINOR 0
#define UXA_VERSION_RELEASE 0
typedef enum {
UXA_ACCESS_RO,
UXA_ACCESS_RW
} uxa_access_t;
/**
* The UxaDriver structure is allocated through uxa_driver_alloc(), and then
* fllled in by drivers.
*/
typedef struct _UxaDriver {
/**
* uxa_major and uxa_minor should be set by the driver to the version of
* UXA which the driver was compiled for (or configures itself at runtime
* to support). This allows UXA to extend the structure for new features
* without breaking ABI for drivers compiled against older versions.
*/
int uxa_major, uxa_minor;
/**
* The flags field is bitfield of boolean values controlling UXA's behavior.
*
* The flags include UXA_TWO_BITBLT_DIRECTIONS.
*/
int flags;
/** @name solid
* @{
*/
/**
* prepare_solid() sets up the driver for doing a solid fill.
* @param pPixmap Destination pixmap
* @param alu raster operation
* @param planemask write mask for the fill
* @param fg "foreground" color for the fill
*
* This call should set up the driver for doing a series of solid fills
* through the solid() call. The alu raster op is one of the GX*
* graphics functions listed in X.h, and typically maps to a similar
* single-byte "ROP" setting in all hardware. The planemask controls
* which bits of the destination should be affected, and will only represent
* the bits up to the depth of pPixmap. The fg is the pixel value of the
* foreground color referred to in ROP descriptions.
*
* Note that many drivers will need to store some of the data in the driver
* private record, for sending to the hardware with each drawing command.
*
* The prepare_solid() call is required of all drivers, but it may fail for any
* reason. Failure results in a fallback to software rendering.
*/
Bool (*prepare_solid) (PixmapPtr pPixmap,
int alu,
Pixel planemask,
Pixel fg);
/**
* solid() performs a solid fill set up in the last prepare_solid() call.
*
* @param pPixmap destination pixmap
* @param x1 left coordinate
* @param y1 top coordinate
* @param x2 right coordinate
* @param y2 bottom coordinate
*
* Performs the fill set up by the last prepare_solid() call, covering the
* area from (x1,y1) to (x2,y2) in pPixmap. Note that the coordinates are
* in the coordinate space of the destination pixmap, so the driver will
* need to set up the hardware's offset and pitch for the destination
* coordinates according to the pixmap's offset and pitch within
* framebuffer.
*
* This call is required if prepare_solid() ever succeeds.
*/
void (*solid) (PixmapPtr pPixmap, int x1, int y1, int x2, int y2);
/**
* done_solid() finishes a set of solid fills.
*
* @param pPixmap destination pixmap.
*
* The done_solid() call is called at the end of a series of consecutive
* solid() calls following a successful prepare_solid(). This allows drivers
* to finish up emitting drawing commands that were buffered, or clean up
* state from prepare_solid().
*
* This call is required if prepare_solid() ever succeeds.
*/
void (*done_solid) (PixmapPtr pPixmap);
/** @} */
/** @name copy
* @{
*/
/**
* prepare_copy() sets up the driver for doing a copy within video
* memory.
*
* @param pSrcPixmap source pixmap
* @param pDstPixmap destination pixmap
* @param dx X copy direction
* @param dy Y copy direction
* @param alu raster operation
* @param planemask write mask for the fill
*
* This call should set up the driver for doing a series of copies from the
* the pSrcPixmap to the pDstPixmap. The dx flag will be positive if the
* hardware should do the copy from the left to the right, and dy will be
* positive if the copy should be done from the top to the bottom. This
* is to deal with self-overlapping copies when pSrcPixmap == pDstPixmap.
* If your hardware can only support blits that are (left to right, top to
* bottom) or (right to left, bottom to top), then you should set
* #UXA_TWO_BITBLT_DIRECTIONS, and UXA will break down copy operations to
* ones that meet those requirements. The alu raster op is one of the GX*
* graphics functions listed in X.h, and typically maps to a similar
* single-byte "ROP" setting in all hardware. The planemask controls which
* bits of the destination should be affected, and will only represent the
* bits up to the depth of pPixmap.
*
* Note that many drivers will need to store some of the data in the driver
* private record, for sending to the hardware with each drawing command.
*
* The prepare_copy() call is required of all drivers, but it may fail for any
* reason. Failure results in a fallback to software rendering.
*/
Bool (*prepare_copy) (PixmapPtr pSrcPixmap,
PixmapPtr pDstPixmap,
int dx,
int dy,
int alu,
Pixel planemask);
/**
* copy() performs a copy set up in the last prepare_copy call.
*
* @param pDstPixmap destination pixmap
* @param srcX source X coordinate
* @param srcY source Y coordinate
* @param dstX destination X coordinate
* @param dstY destination Y coordinate
* @param width width of the rectangle to be copied
* @param height height of the rectangle to be copied.
*
* Performs the copy set up by the last prepare_copy() call, copying the
* rectangle from (srcX, srcY) to (srcX + width, srcY + width) in the source
* pixmap to the same-sized rectangle at (dstX, dstY) in the destination
* pixmap. Those rectangles may overlap in memory, if
* pSrcPixmap == pDstPixmap. Note that this call does not receive the
* pSrcPixmap as an argument -- if it's needed in this function, it should
* be stored in the driver private during prepare_copy(). As with solid(),
* the coordinates are in the coordinate space of each pixmap, so the driver
* will need to set up source and destination pitches and offsets from those
* pixmaps, probably using uxaGetPixmapOffset() and uxa_get_pixmap_pitch().
*
* This call is required if prepare_copy ever succeeds.
*/
void (*copy) (PixmapPtr pDstPixmap,
int srcX,
int srcY,
int dstX,
int dstY,
int width,
int height);
/**
* done_copy() finishes a set of copies.
*
* @param pPixmap destination pixmap.
*
* The done_copy() call is called at the end of a series of consecutive
* copy() calls following a successful prepare_copy(). This allows drivers
* to finish up emitting drawing commands that were buffered, or clean up
* state from prepare_copy().
*
* This call is required if prepare_copy() ever succeeds.
*/
void (*done_copy) (PixmapPtr pDstPixmap);
/** @} */
/** @name composite
* @{
*/
/**
* check_composite() checks to see if a composite operation could be
* accelerated.
*
* @param op Render operation
* @param pSrcPicture source Picture
* @param pMaskPicture mask picture
* @param pDstPicture destination Picture
*
* The check_composite() call checks if the driver could handle acceleration
* of op with the given source, mask, and destination pictures. This allows
* drivers to check source and destination formats, supported operations,
* transformations, and component alpha state, and send operations it can't
* support to software rendering early on.
*
* See prepare_composite() for more details on likely issues that drivers
* will have in accelerating composite operations.
*
* The check_composite() call is recommended if prepare_composite() is
* implemented, but is not required.
*/
Bool (*check_composite) (int op,
PicturePtr pSrcPicture,
PicturePtr pMaskPicture,
PicturePtr pDstPicture);
/**
* prepare_composite() sets up the driver for doing a composite operation
* described in the Render extension protocol spec.
*
* @param op Render operation
* @param pSrcPicture source Picture
* @param pMaskPicture mask picture
* @param pDstPicture destination Picture
* @param pSrc source pixmap
* @param pMask mask pixmap
* @param pDst destination pixmap
*
* This call should set up the driver for doing a series of composite
* operations, as described in the Render protocol spec, with the given
* pSrcPicture, pMaskPicture, and pDstPicture. The pSrc, pMask, and
* pDst are the pixmaps containing the pixel data, and should be used for
* setting the offset and pitch used for the coordinate spaces for each of
* the Pictures.
*
* Notes on interpreting Picture structures:
* - The Picture structures will always have a valid pDrawable.
* - The Picture structures will never have alphaMap set.
* - The mask Picture (and therefore pMask) may be NULL, in which case the
* operation is simply src OP dst instead of src IN mask OP dst, and
* mask coordinates should be ignored.
* - pMarkPicture may have componentAlpha set, which greatly changes
* the behavior of the composite operation. componentAlpha has no effect
* when set on pSrcPicture or pDstPicture.
* - The source and mask Pictures may have a transformation set
* (Picture->transform != NULL), which means that the source coordinates
* should be transformed by that transformation, resulting in scaling,
* rotation, etc. The PictureTransformPoint() call can transform
* coordinates for you. Transforms have no effect on Pictures when used
* as a destination.
* - The source and mask pictures may have a filter set. PictFilterNearest
* and PictFilterBilinear are defined in the Render protocol, but others
* may be encountered, and must be handled correctly (usually by
* prepare_composite failing, and falling back to software). Filters have
* no effect on Pictures when used as a destination.
* - The source and mask Pictures may have repeating set, which must be
* respected. Many chipsets will be unable to support repeating on
* pixmaps that have a width or height that is not a power of two.
*
* If your hardware can't support source pictures (textures) with
* non-power-of-two pitches, you should set #UXA_OFFSCREEN_ALIGN_POT.
*
* Note that many drivers will need to store some of the data in the driver
* private record, for sending to the hardware with each drawing command.
*
* The prepare_composite() call is not required. However, it is highly
* recommended for performance of antialiased font rendering and performance
* of cairo applications. Failure results in a fallback to software
* rendering.
*/
Bool (*prepare_composite) (int op,
PicturePtr pSrcPicture,
PicturePtr pMaskPicture,
PicturePtr pDstPicture,
PixmapPtr pSrc,
PixmapPtr pMask,
PixmapPtr pDst);
/**
* composite() performs a composite operation set up in the last
* prepare_composite() call.
*
* @param pDstPixmap destination pixmap
* @param srcX source X coordinate
* @param srcY source Y coordinate
* @param maskX source X coordinate
* @param maskY source Y coordinate
* @param dstX destination X coordinate
* @param dstY destination Y coordinate
* @param width destination rectangle width
* @param height destination rectangle height
*
* Performs the composite operation set up by the last prepare_composite()
* call, to the rectangle from (dstX, dstY) to (dstX + width, dstY + height)
* in the destination Pixmap. Note that if a transformation was set on
* the source or mask Pictures, the source rectangles may not be the same
* size as the destination rectangles and filtering. Getting the coordinate
* transformation right at the subpixel level can be tricky, and rendercheck
* can test this for you.
*
* This call is required if prepare_composite() ever succeeds.
*/
void (*composite) (PixmapPtr pDst,
int srcX,
int srcY,
int maskX,
int maskY,
int dstX,
int dstY,
int width,
int height);
/**
* done_composite() finishes a set of composite operations.
*
* @param pPixmap destination pixmap.
*
* The done_composite() call is called at the end of a series of consecutive
* composite() calls following a successful prepare_composite(). This allows
* drivers to finish up emitting drawing commands that were buffered, or
* clean up state from prepare_composite().
*
* This call is required if prepare_composite() ever succeeds.
*/
void (*done_composite) (PixmapPtr pDst);
/** @} */
/**
* put_image() loads a rectangle of data from src into pDst.
*
* @param pDst destination pixmap
* @param x destination X coordinate.
* @param y destination Y coordinate
* @param width width of the rectangle to be copied
* @param height height of the rectangle to be copied
* @param src pointer to the beginning of the source data
* @param src_pitch pitch (in bytes) of the lines of source data.
*
* put_image() copies data in system memory beginning at src (with
* pitch src_pitch) into the destination pixmap from (x, y) to
* (x + width, y + height). This is typically done with hostdata uploads,
* where the CPU sets up a blit command on the hardware with instructions
* that the blit data will be fed through some sort of aperture on the card.
*
* put_image() is most important for the performance of uxa_glyphs()
* (antialiased font drawing) by allowing pipelining of data uploads,
* avoiding a sync of the card after each glyph.
*
* @return TRUE if the driver successfully uploaded the data. FALSE
* indicates that UXA should fall back to doing the upload in software.
*
* put_image() is not required, but is recommended if composite
* acceleration is supported.
*/
Bool (*put_image) (PixmapPtr pDst,
int x,
int y,
int w,
int h,
char *src,
int src_pitch);
/**
* get_image() loads a rectangle of data from pSrc into dst
*
* @param pSrc source pixmap
* @param x source X coordinate.
* @param y source Y coordinate
* @param width width of the rectangle to be copied
* @param height height of the rectangle to be copied
* @param dst pointer to the beginning of the destination data
* @param dst_pitch pitch (in bytes) of the lines of destination data.
*
* get_image() copies data from offscreen memory in pSrc from
* (x, y) to (x + width, y + height), to system memory starting at
* dst (with pitch dst_pitch). This would usually be done
* using scatter-gather DMA, supported by a DRM call, or by blitting to AGP
* and then synchronously reading from AGP. Because the implementation
* might be synchronous, UXA leaves it up to the driver to call
* uxa_mark_sync() if get_image() was asynchronous. This is in
* contrast to most other acceleration calls in UXA.
*
* @return TRUE if the driver successfully downloaded the data. FALSE
* indicates that UXA should fall back to doing the download in software.
*
* get_image() is not required, but is highly recommended.
*/
Bool (*get_image)(PixmapPtr pSrc,
int x, int y,
int w, int h,
char *dst, int dst_pitch);
/** @{ */
/**
* prepare_access() is called before CPU access to an offscreen pixmap.
*
* @param pPix the pixmap being accessed
* @param index the index of the pixmap being accessed.
*
* prepare_access() will be called before CPU access to an offscreen pixmap.
* This can be used to set up hardware surfaces for byteswapping or
* untiling, or to adjust the pixmap's devPrivate.ptr for the purpose of
* making CPU access use a different aperture.
*
* The index is one of #UXA_PREPARE_DEST, #UXA_PREPARE_SRC, or
* #UXA_PREPARE_MASK, indicating which pixmap is in question. Since only up
* to three pixmaps will have prepare_access() called on them per operation,
* drivers can have a small, statically-allocated space to maintain state
* for prepare_access() and finish_access() in. Note that the same pixmap may
* have prepare_access() called on it more than once, for uxample when doing
* a copy within the same pixmap (so it gets prepare_access as()
* #UXA_PREPARE_DEST and then as #UXA_PREPARE_SRC).
*
* prepare_access() may fail. An uxample might be the case of hardware that
* can set up 1 or 2 surfaces for CPU access, but not 3. If prepare_access()
* fails, UXA will migrate the pixmap to system memory.
* get_image() must be implemented and must not fail if a driver
* wishes to fail in prepare_access(). prepare_access() must not fail when
* pPix is the visible screen, because the visible screen can not be
* migrated.
*
* @return TRUE if prepare_access() successfully prepared the pixmap for CPU
* drawing.
* @return FALSE if prepare_access() is unsuccessful and UXA should use
* get_image() to migate the pixmap out.
*/
Bool (*prepare_access)(PixmapPtr pPix, uxa_access_t access);
/**
* finish_access() is called after CPU access to an offscreen pixmap.
*
* @param pPix the pixmap being accessed
* @param index the index of the pixmap being accessed.
*
* finish_access() will be called after finishing CPU access of an offscreen
* pixmap set up by prepare_access(). Note that the finish_access() will not be
* called if prepare_access() failed.
*/
void (*finish_access)(PixmapPtr pPix);
/**
* PixmapIsOffscreen() is an optional driver replacement to
* uxa_pixmap_is_offscreen(). Set to NULL if you want the standard behaviour
* of uxa_pixmap_is_offscreen().
*
* @param pPix the pixmap
* @return TRUE if the given drawable is in framebuffer memory.
*
* uxa_pixmap_is_offscreen() is used to determine if a pixmap is in offscreen
* memory, meaning that acceleration could probably be done to it, and that it
* will need to be wrapped by prepare_access()/finish_access() when accessing it
* with the CPU.
*
*
*/
Bool (*pixmap_is_offscreen)(PixmapPtr pPix);
/** @} */
} uxa_driver_t;
/** @name UXA driver flags
* @{
*/
/**
* UXA_TWO_BITBLT_DIRECTIONS indicates to UXA that the driver can only
* support copies that are (left-to-right, top-to-bottom) or
* (right-to-left, bottom-to-top).
*/
#define UXA_TWO_BITBLT_DIRECTIONS (1 << 2)
/** @} */
uxa_driver_t *
uxa_driver_alloc(void);
Bool
uxa_driver_init(ScreenPtr screen, uxa_driver_t *uxa_driver);
void
uxa_driver_fini(ScreenPtr pScreen);
CARD32
uxa_get_pixmap_first_pixel (PixmapPtr pPixmap);
/**
* Returns TRUE if the given planemask covers all the significant bits in the
* pixel values for pDrawable.
*/
#define UXA_PM_IS_SOLID(_pDrawable, _pm) \
(((_pm) & FbFullMask((_pDrawable)->depth)) == \
FbFullMask((_pDrawable)->depth))
#endif /* UXA_H */