The attached patch implements IDirectFBScreen::SetSourceLocation() and
includes the relevant changes to mach64 (lightly tested) and matrox
(untested) drivers.
I made it use ints instead of floats. That means that the source
rectangle needs to be reset when surface size changes. Using floats would
allow it to be recalculated. I'm not sure which is better.
Also I'm not sure about the method name. Set<something> would be
consistent with the other names. SetSourceLocation() isn't maybe the best
choice with int arguments (wrt. DFBLocation). So maybe it should be
SetSourceRectangle()?
--
Ville Syrj�l�
[EMAIL PROTECTED]
http://www.sci.fi/~syrjala/
Index: gfxdrivers/mach64/mach64_overlay.c
===================================================================
RCS file: /cvs/directfb/DirectFB/gfxdrivers/mach64/mach64_overlay.c,v
retrieving revision 1.7
diff -u -r1.7 mach64_overlay.c
--- gfxdrivers/mach64/mach64_overlay.c 30 Mar 2004 19:13:42 -0000 1.7
+++ gfxdrivers/mach64/mach64_overlay.c 15 Jun 2004 22:47:37 -0000
@@ -349,15 +349,15 @@
dfb_region_intersect( &dst, 0, 0, mode->xres - 1, mode->yres - 1 );
- h_inc = ((__u64) surface->width << 12) / config->dest.w;
+ h_inc = ((__u64) config->source.w << 12) / config->dest.w;
lcd_gen_ctrl = mach64_in_lcd( mmio, LCD_GEN_CTRL );
lcd_vert_stretching = mach64_in_lcd( mmio, LCD_VERT_STRETCHING );
if ((lcd_gen_ctrl & LCD_ON) && (lcd_vert_stretching & VERT_STRETCH_EN))
- v_inc = ((__u64) surface->height << 2) * (lcd_vert_stretching &
VERT_STRETCH_RATIO0) / config->dest.h;
+ v_inc = ((__u64) config->source.h << 2) * (lcd_vert_stretching &
VERT_STRETCH_RATIO0) / config->dest.h;
else
- v_inc = ((__u64) surface->height << 12) / config->dest.h;
+ v_inc = ((__u64) config->source.h << 12) / config->dest.h;
switch (surface->format) {
case DSPF_ARGB1555:
@@ -442,7 +442,7 @@
mov->regs.overlay_KEY_CNTL = ovColorKey[(config->options >> 3) & 3];
- mov->regs.scaler_HEIGHT_WIDTH = (surface->width << 16) | surface->height;
+ mov->regs.scaler_HEIGHT_WIDTH = (config->source.w << 16) | config->source.h;
mov->regs.scaler_BUF_PITCH = front_buffer->video.pitch / DFB_BYTES_PER_PIXEL(
surface->format );
mov->regs.overlay_Y_X_START = (dst.x1 << 16) | dst.y1 | OVERLAY_LOCK_START;
@@ -463,13 +463,16 @@
{
__u32 offset, offset_u = 0, offset_v = 0;
SurfaceBuffer *front_buffer = surface->front_buffer;
- int cropleft = 0, croptop = 0;
+ int cropleft, croptop;
+
+ cropleft = config->source.x;
+ croptop = config->source.y;
if (config->dest.x < 0)
- cropleft = -config->dest.x * surface->width / config->dest.w;
+ cropleft += -config->dest.x * config->source.w / config->dest.w;
if (config->dest.y < 0)
- croptop = -config->dest.y * surface->height / config->dest.h;
+ croptop += -config->dest.y * config->source.h / config->dest.h;
switch (surface->format) {
case DSPF_I420:
Index: gfxdrivers/matrox/matrox_bes.c
===================================================================
RCS file: /cvs/directfb/DirectFB/gfxdrivers/matrox/matrox_bes.c,v
retrieving revision 1.48
diff -u -r1.48 matrox_bes.c
--- gfxdrivers/matrox/matrox_bes.c 30 Mar 2004 19:13:42 -0000 1.48
+++ gfxdrivers/matrox/matrox_bes.c 15 Jun 2004 22:47:37 -0000
@@ -247,7 +247,7 @@
/* set main configuration */
if (updated & (CLRCF_WIDTH | CLRCF_HEIGHT | CLRCF_FORMAT |
- CLRCF_OPTIONS | CLRCF_DEST | CLRCF_OPACITY))
+ CLRCF_OPTIONS | CLRCF_DEST | CLRCF_OPACITY | CLRCF_SOURCE))
{
bes_calc_regs( mdrv, mbes, config, surface );
bes_set_regs( mdrv, mbes, true );
@@ -430,8 +430,8 @@
{
MatroxDeviceData *mdev = mdrv->device_data;
int cropleft, cropright, croptop, cropbot, croptop_uv;
- int field_height, pitch, tmp, hzoom, intrep;
- DFBRectangle dest;
+ int pitch, tmp, hzoom, intrep;
+ DFBRectangle source, dest;
DFBRegion dstBox;
SurfaceBuffer *front_buffer = surface->front_buffer;
VideoMode *current_mode = dfb_system_current_mode();
@@ -440,17 +440,17 @@
if (!current_mode)
return;
- dest = config->dest;
+ source = config->source;
+ dest = config->dest;
if (!mdev->g450_matrox && surface->format == DSPF_RGB32)
- dest.w = surface->width;
+ dest.w = source.w;
- field_height = surface->height;
pitch = front_buffer->video.pitch;
if (config->options & DLOP_DEINTERLACING) {
- field_height /= 2;
- pitch *= 2;
+ source.h /= 2;
+ pitch *= 2;
} else
mbes->regs.besCTL_field = 0;
@@ -474,15 +474,19 @@
/* scale crop values to source dimensions */
if (cropleft)
- cropleft = ((__u64) (surface->width << 16) * cropleft / dest.w) & ~0x3;
+ cropleft = ((__u64) (source.w << 16) * cropleft / dest.w) & ~0x3;
if (croptop)
- croptop = ((__u64) (field_height << 16) * croptop / dest.h) & ~0x3;
+ croptop = ((__u64) (source.h << 16) * croptop / dest.h) & ~0x3;
if (cropright)
- cropright = ((__u64) (surface->width << 16) * cropright / dest.w) & ~0x3;
+ cropright = ((__u64) (source.w << 16) * cropright / dest.w) & ~0x3;
if (cropbot)
- cropbot = ((__u64) (field_height << 16) * cropbot / dest.h) & ~0x3;
+ cropbot = ((__u64) (source.h << 16) * cropbot / dest.h) & ~0x3;
if (croptop_uv)
- croptop_uv = ((__u64) ((field_height/2) << 16) * croptop_uv / dest.h) &
~0x3;
+ croptop_uv = ((__u64) ((source.h/2) << 16) * croptop_uv / dest.h) & ~0x3;
+
+ cropleft += config->source.x << 16;
+ croptop += config->source.y << 16;
+ croptop_uv += (config->source.y/2) << 16;
/* should horizontal zoom be used? */
if (mdev->g450_matrox)
@@ -575,8 +579,8 @@
mbes->regs.besVCOORD = (dstBox.y1 << 16) | dstBox.y2;
mbes->regs.besHSRCST = cropleft;
- mbes->regs.besHSRCEND = ((surface->width - 1) << 16) - cropright;
- mbes->regs.besHSRCLST = (surface->width - 1) << 16;
+ mbes->regs.besHSRCEND = ((source.w - 1) << 16) - cropright;
+ mbes->regs.besHSRCLST = (source.w - 1) << 16;
/* vertical starting weights */
tmp = croptop & 0xfffc;
@@ -597,7 +601,7 @@
mbes->regs.besV2WGHT = tmp;
mbes->regs.besV1SRCLST = mbes->regs.besV2SRCLST =
- field_height - 1 - (croptop >> 16) - (cropbot >> 16);
+ source.h - 1 - (croptop >> 16) - (cropbot >> 16);
/* horizontal scaling */
if (!mdev->g450_matrox && surface->format == DSPF_RGB32) {
@@ -607,20 +611,20 @@
mbes->regs.besHSRCLST *= 2;
mbes->regs.besPITCH *= 2;
} else {
- intrep = ((mbes->regs.besCTL & BESHFEN) || (surface->width > dest.w)) ? 1 :
0;
- if ((dest.w == surface->width) || (dest.w < 2))
+ intrep = ((mbes->regs.besCTL & BESHFEN) || (source.w > dest.w)) ? 1 : 0;
+ if ((dest.w == source.w) || (dest.w < 2))
intrep = 0;
- tmp = (((surface->width - intrep) << 16) / (dest.w - intrep)) << hzoom;
+ tmp = (((source.w - intrep) << 16) / (dest.w - intrep)) << hzoom;
if (tmp >= (32 << 16))
tmp = (32 << 16) - 1;
mbes->regs.besHISCAL = tmp & 0x001ffffc;
}
/* vertical scaling */
- intrep = ((mbes->regs.besCTL & BESVFEN) || (field_height > dest.h)) ? 1 : 0;
- if ((dest.h == field_height) || (dest.h < 2))
+ intrep = ((mbes->regs.besCTL & BESVFEN) || (source.h > dest.h)) ? 1 : 0;
+ if ((dest.h == source.h) || (dest.h < 2))
intrep = 0;
- tmp = ((field_height - intrep) << 16) / (dest.h - intrep);
+ tmp = ((source.h - intrep) << 16) / (dest.h - intrep);
if(tmp >= (32 << 16))
tmp = (32 << 16) - 1;
mbes->regs.besVISCAL = tmp & 0x001ffffc;
Index: include/directfb.h
===================================================================
RCS file: /cvs/directfb/DirectFB/include/directfb.h,v
retrieving revision 1.219
diff -u -r1.219 directfb.h
--- include/directfb.h 3 Jun 2004 04:32:19 -0000 1.219
+++ include/directfb.h 15 Jun 2004 22:47:40 -0000
@@ -2196,6 +2196,17 @@
);
/*
+ * Set source location within the surface.
+ */
+ DFBResult (*SetSourceLocation) (
+ IDirectFBDisplayLayer *thiz,
+ int x,
+ int y,
+ int width,
+ int height
+ );
+
+ /*
* Set the source color key.
*
* If a pixel of the layer matches this color the underlying
Index: src/core/layer_context.c
===================================================================
RCS file: /cvs/directfb/DirectFB/src/core/layer_context.c,v
retrieving revision 1.19
diff -u -r1.19 layer_context.c
--- src/core/layer_context.c 3 Jun 2004 04:32:20 -0000 1.19
+++ src/core/layer_context.c 15 Jun 2004 22:47:41 -0000
@@ -784,6 +784,49 @@
}
DFBResult
+dfb_layer_context_set_sourcelocation( CoreLayerContext *context,
+ DFBRectangle *source )
+{
+ DFBResult ret;
+ CoreLayerRegionConfig config;
+
+ D_ASSERT( context != NULL );
+ D_ASSERT( location != NULL );
+
+ /* Lock the context. */
+ if (dfb_layer_context_lock( context ))
+ return DFB_FUSION;
+
+ /* Take the current configuration. */
+ config = context->primary.config;
+
+ /* Do nothing if the source coordinates didn't change. */
+ if (DFB_RECTANGLE_EQUAL( config.source, *source )) {
+ dfb_layer_context_unlock( context );
+ return DFB_OK;
+ }
+
+ /* Check if the new source coordinates are valid. */
+ if (source->x < 0 || source->y < 0 ||
+ source->x + source->w > config.width ||
+ source->y + source->h > config.height) {
+ dfb_layer_context_unlock( context );
+ return DFB_INVAREA;
+ }
+
+ /* Change the source rectangle. */
+ config.source = *source;
+
+ /* Try to set the new configuration. */
+ ret = update_primary_region_config( context, &config, CLRCF_SOURCE );
+
+ /* Unlock the context. */
+ dfb_layer_context_unlock( context );
+
+ return ret;
+}
+
+DFBResult
dfb_layer_context_set_opacity (CoreLayerContext *context, __u8 opacity)
{
DFBResult ret;
@@ -1069,16 +1112,27 @@
/* Get the current region configuration. */
*ret_config = context->primary.config;
+ /* Reset source coordinates. */
+ if (update->flags & (DLCONF_WIDTH | DLCONF_HEIGHT)) {
+ flags |= CLRCF_SOURCE;
+ ret_config->source.x = 0;
+ ret_config->source.y = 0;
+ ret_config->source.w = ret_config->width;
+ ret_config->source.h = ret_config->height;
+ }
+
/* Change width. */
if (update->flags & DLCONF_WIDTH) {
flags |= CLRCF_WIDTH;
ret_config->width = update->width;
+ ret_config->source.w = update->width;
}
/* Change height. */
if (update->flags & DLCONF_HEIGHT) {
flags |= CLRCF_HEIGHT;
ret_config->height = update->height;
+ ret_config->source.h = update->height;
}
/* Change pixel format. */
Index: src/core/layer_context.h
===================================================================
RCS file: /cvs/directfb/DirectFB/src/core/layer_context.h,v
retrieving revision 1.7
diff -u -r1.7 layer_context.h
--- src/core/layer_context.h 30 Mar 2004 18:35:36 -0000 1.7
+++ src/core/layer_context.h 15 Jun 2004 22:47:41 -0000
@@ -90,6 +90,9 @@
DFBResult dfb_layer_context_set_screenlocation( CoreLayerContext *context,
DFBLocation *location );
+DFBResult dfb_layer_context_set_sourcelocation( CoreLayerContext *context,
+ DFBRectangle *source );
+
DFBResult dfb_layer_context_set_opacity (CoreLayerContext *context, __u8 opacity);
DFBResult dfb_layer_context_set_coloradjustment (CoreLayerContext *context,
Index: src/display/idirectfbdisplaylayer.c
===================================================================
RCS file: /cvs/directfb/DirectFB/src/display/idirectfbdisplaylayer.c,v
retrieving revision 1.69
diff -u -r1.69 idirectfbdisplaylayer.c
--- src/display/idirectfbdisplaylayer.c 3 May 2004 14:59:09 -0000 1.69
+++ src/display/idirectfbdisplaylayer.c 15 Jun 2004 22:47:41 -0000
@@ -318,6 +318,26 @@
}
static DFBResult
+IDirectFBDisplayLayer_SetSourceLocation( IDirectFBDisplayLayer *thiz,
+ int x,
+ int y,
+ int width,
+ int height )
+{
+ DFBRectangle source = { x, y, width, height };
+
+ DIRECT_INTERFACE_GET_DATA(IDirectFBDisplayLayer)
+
+ if (x < 0 || y < 0 || width <= 0 || height <= 0)
+ return DFB_INVARG;
+
+ if (data->level == DLSCL_SHARED)
+ return DFB_ACCESSDENIED;
+
+ return dfb_layer_context_set_sourcelocation( data->context, &source );
+}
+
+static DFBResult
IDirectFBDisplayLayer_SetSrcColorKey( IDirectFBDisplayLayer *thiz,
__u8 r,
__u8 g,
@@ -737,6 +757,7 @@
thiz->SetOpacity = IDirectFBDisplayLayer_SetOpacity;
thiz->GetCurrentOutputField = IDirectFBDisplayLayer_GetCurrentOutputField;
thiz->SetScreenLocation = IDirectFBDisplayLayer_SetScreenLocation;
+ thiz->SetSourceLocation = IDirectFBDisplayLayer_SetSourceLocation;
thiz->SetSrcColorKey = IDirectFBDisplayLayer_SetSrcColorKey;
thiz->SetDstColorKey = IDirectFBDisplayLayer_SetDstColorKey;
thiz->GetLevel = IDirectFBDisplayLayer_GetLevel;