Merge branch 'drm-gem'
This commit is contained in:
commit
f9504eff31
|
|
@ -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
|
||||
|
|
|
|||
15
configure.ac
15
configure.ac
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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) \
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
76
src/i830.h
76
src/i830.h
|
|
@ -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];
|
||||
|
||||
|
|
|
|||
130
src/i830_accel.c
130
src/i830_accel.c
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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 */
|
||||
|
|
@ -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",
|
||||
|
|
|
|||
128
src/i830_dri.c
128
src/i830_dri.c
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -59,5 +59,4 @@ typedef struct {
|
|||
int dummy;
|
||||
} I830DRIContextRec, *I830DRIContextPtr;
|
||||
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
336
src/i830_exa.c
336
src/i830_exa.c
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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); \
|
||||
|
|
|
|||
|
|
@ -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))) {
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -2,3 +2,4 @@ intel_hotplug
|
|||
intel_idle
|
||||
intel_reg_dumper
|
||||
intel_stepping
|
||||
intel_statuspage
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
@ -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 */
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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*/
|
||||
}
|
||||
|
|
@ -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 */
|
||||
Loading…
Reference in New Issue