[mythtv] Improved MythTV DirectFB output

Kristof Pelckmans kristof.pelckmans at antwerpen.be
Thu Apr 1 17:28:51 EST 2004


Messed up the patches somewhere along the way...

Quoting Kristof Pelckmans <kristof.pelckmans at antwerpen.be>:

> Hello,
>
> I improved the DirectFB output driver :
> - added support for hardware blitting (if the videocard supports this)
> - improved format handling : I420 -> YV12 and I420 -> I420 are now perfectly
> supported. The output driver looks for a video layer that supports I420, when
> it doesn't find it, it falls back to YV12 with software format conversion.
> - improved I420->YV12 software conversion, supporting different pitches (this
> was a bug, see http://www.gossamer-threads.com/perl/mailarc/gforum.cgi?
> post=113868) - in fact, DirectFB should handle this conversion, but it is not
> yet implemented :-(
> - improved buffering : all buffers are now DirectFB surfaces with the
> appropriate width, height and format - maybe this buffering should turn into
> a
> real DirectFBVideoProvider some day...
> - implemented aspect change, remind to set the FRAMEBUFFER environment
> variable
> when your framebuffer device is different from /dev/fb0. I need to access the
> framebuffer directly in order to determine the screen width and height.
> Hopefully DirectFB will offer some method to do determine this...
>
> Still to do :
> - support for zoom
> - support for osd : it would be nice to render the osd as a seperate surface
> and let DirectFB combine them using alpha blending : you would get a nice
> transparant osd display :-)
> - look at those pause and scratch frames
>
> Some questions :
> - When I look at the format of the vbuffers that I receive, they seem to be
> I420. However, I explicitely set vbuffers[i].codec = FMT_YV12 ? Can the input
> format change ?
> - Can someone take a look at the cleanup for my data struct ? I'm getting a
> warning from DirectFB that a few bytes are not freed. (You can see this when
> you compiled DirectFB with debug and tracing options) Don't worry : the video
> buffers are properly closed !
> - Is it necessary to have 31 buffers ? This was taken from the xv output...
> - I think I read somewhere that there is a DirectFB port of QT Embedded, it
> would be nice to run this for the ui stuff :-)
>
> I include patches against the latest cvs versions.
>
> Kind regards,
>
> Kristof
-------------- next part --------------
5d4
< 
12a12
> #include "mythcontext.h"
14a15,20
> #include <map>
> #include <linux/fb.h>
> #include <sys/ioctl.h>
> #include <fcntl.h>
> #include <unistd.h>
> 
19a26,47
> #define DFBCHECKFAIL(dfbcommand, returnstmt...)					\
> {																\
>     DFBResult err = dfbcommand;									\
> 																\
> 	if (err != DFB_OK)											\
> 	{															\
> 		fprintf( stderr, "%s <%d>:\n\t", __FILE__, __LINE__ );	\
> 		DirectFBError( #dfbcommand, err );						\
> 		return returnstmt;										\
> 	}															\
> }
> 
> #define DFBCHECK(x...)											\
> {																\
>     DFBResult err = x;											\
> 																\
> 	if (err != DFB_OK)											\
> 	{															\
> 		fprintf( stderr, "%s <%d>:\n\t", __FILE__, __LINE__ );	\
> 		DirectFBError( #x, err );								\
> 	}															\
> }
20a49,102
> 
> 
> /*static const int FORMATS[1][2] =
> {
>     //FMT_XVMC_IDCT_MPEG2,
>     //FMT_XVMC_MOCO_MPEG2,
>     //FMT_VIA_HWSLICE,
>     //FMT_IA44,
>     //FMT_AI44,
>     //FMT_YUV422P
> 
> 	{DSPF_UNKNOWN, FMT_NONE, "no format",
> 
> 	//16bit ARGB (2 bytes, alpha 1 at 15, red 5 at 10, green 5 at 5, blue 5 at 0) 
> 	{DSPF_ARGB1555, FMT_NONE, "16bit ARGB"},
> 
> 	//16bit RGB (2 bytes, red 5 at 11, green 6 at 5, blue 5 at 0) 
> 	{DSPF_RGB16, FMT_NONE, "16bit RGB"},
> 
> 	//24bit RGB (3 bytes, red 8 at 16, green 8 at 8, blue 8 at 0) 
> 	{DSPF_RGB24, FMT_RGB24, "24bit RGB"},
> 
> 	//24bit RGB (4 bytes, nothing at 24, red 8 at 16, green 8 at 8, blue 8 at 0)
> 	{DSPF_RGB32, FMT_NONE, "24bit RGB"},
> 
> 	//32bit ARGB (4 bytes, alpha 8 at 24, red 8 at 16, green 8 at 8, blue 8 at 0)
> 	{DSPF_ARGB, FMT_ARGB32, "32bit ARGB"},
> 
> 	//8bit alpha (1 byte, alpha 8 at 0 ), e.g. anti-aliased text glyphs 
> 	{DSPF_A8, FMT_NONE, "8bit alpha"},
> 
> 	//A macropixel (32bit / 2 pixel) contains YUYV (starting with the LOWEST byte on the LEFT) 
> 	{DSPF_YUY2, FMT_NONE, "A macropixel (32bit / 2 pixel) contains YUYV (starting with the LOWEST byte on the LEFT)"},
> 
> 	//8bit true color (1 byte, red 3 at 5, green 3 at 2, blue 2 at 0 
> 	{DSPF_RGB332, FMT_NONE, "8bit true color"},
> 
> 	//A macropixel (32bit / 2 pixel) contains UYVY (starting with the LOWEST byte on the LEFT) 
> 	{DSPF_UYVY, FMT_NONE, "UYVY"},
> 
> 	//8 bit Y plane followed by 8 bit 2x2 subsampled U and V planes 
> 	{DSPF_I420, FMT_NONE, "I420 : Yuv"},
> 
> 	//8 bit Y plane followed by 8 bit 2x2 subsampled V and U planes 
> 	{DSPF_YV12, FMT_YV12, "YV12 : Yvu"},
> 
> 	//8 bit lookup table (palette) 
> 	{DSPF_LUT8, FMT_NONE, "8 bit lookup table (palette)"},
> 
> 	//4 bit alpha + 4 bit lookup table 
> 	{DSPF_ALUT44, FMT_NONE, "ALUT44"}
> }
> */
> 
147,148d228
< 
< 
155,165d234
< struct DirectfbParams
< {
<     uint32_t format;
<     int scale;
<     int result;
<     unsigned int id;
<     unsigned int width;
<     unsigned int height;
<     int setsize;
< };
< 
167a237
> 	//DirectFB hook
168a239,243
> 	//video output
> 	DFBCardCapabilities cardCapabilities;
> 	IDirectFBDisplayLayer *layer;
> 	DFBDisplayLayerDescription layerDesc;
> 	DFBDisplayLayerConfig layerConfig;
170c245
<     struct DirectfbParams params;
---
> 	//input handling
172a248,251
> 	//buffers
> 	map<unsigned char *, IDirectFBSurface *> buffers;
> 	int screen_width;
> 	int screen_height;
174a254,255
> IDirectFBSurface *tempYV12Surface; 
> 
185,186d265
< 	DFBResult ret;
< 
188,204c267,268
<     ret = data->surface->Clear(data->surface, 0x00, 0x00, 0x00, 0x00);
<     if (ret)
<     {
<         DirectFBError("Couldn't clear the buffers", ret);
<     }
< 
<     ret = data->surface->Flip(data->surface, NULL, DSFLIP_ONSYNC);
<     if (ret)
<     {
<         DirectFBError("Couldn't flip the buffers", ret);
<     }
< 
<     ret = data->surface->Clear(data->surface, 0x00, 0x00, 0x00, 0x00);
<     if (ret)
<     {
<         DirectFBError("Couldn't clear the buffers", ret);
<     }
---
> 	ClearSurface(data->surface);
> 	DeleteDirectfbBuffers();
212a277,280
> 	if (tempYV12Surface)
> 		tempYV12Surface->Release(tempYV12Surface);
> 	if (data->layer)
> 		data->layer->Release(data->layer);
227d294
<         DeleteDirectfbBuffers();
241,244c308
<     DFBDisplayLayerConfig dlc;
<     IDirectFBDisplayLayer *layer;
<     IDirectFBSurface *primary;
< 
---
>     
247,261c311,314
<     VideoOutput::InitBuffers(kNumBuffers, true, kNeedFreeFrames,
<                              kPrebufferFrames, kKeepPrebuffer);
<     VideoOutput::Init(width, height, aspect, winid, winx, winy, winw, winh,
<                       embedid);
< 
<     ret = DirectFBInit(NULL,NULL);
< 
<     if (ret)
<     {
<         DirectFBError( "Couldn't initialize DirectFB", ret );
<         return false;
<     }
< 
<     DirectFBSetOption("bg-none",NULL);
<     DirectFBSetOption("no-cursor",NULL);
---
> 	//determine screen size
> 	char *fb_dev_name = NULL;
> 	int fb_dev_fd;
> 	struct fb_var_screeninfo fb_vinfo;
263c316,317
<     ret = DirectFBCreate( &(data->dfb) );
---
> 	if (!fb_dev_name && !(fb_dev_name = getenv("FRAMEBUFFER")))
> 			fb_dev_name = strdup("/dev/fb0");
265,329c319,327
<     if (ret)
<     {
<         DirectFBError( "Couldn't create DirectFB subsystem", ret );
<         return false;
<     }
< 
<     ret = data->dfb->GetDisplayLayer(data->dfb, DLID_PRIMARY, &layer);
< 
<     if (ret)
<     {
<         DirectFBError("No primary display layer - WTF?", ret);
<         return false;
<     }
< 
<     layer->SetOpacity(layer, 0);
<     ret = layer->GetSurface(layer, &primary);
< 
<     if (ret)
<     {
<         DirectFBError("Couldn't get primary display surface", ret);
<         return false;
<     }
< 
<     data->params.result = 0;
< 
<     ret = data->dfb->EnumDisplayLayers(data->dfb, LayerCallback, data);
< 
<     if (ret)
<     {
<         DirectFBError("Couldn't enumerate display layers", ret);
<         return false;
<     }
< 
<     ret = data->dfb->GetDisplayLayer(data->dfb, 1, &layer);
< 
<     if (ret)
<     {
<         DirectFBError("Couldn't get our display layer - this shouldn't happen", ret);
<         return false;
<     }
< 
<     ret = layer->SetCooperativeLevel(layer, DLSCL_EXCLUSIVE);
< 
<     if (ret)
<     {
<         DirectFBError("Couldn't get exclusive access", ret);
<         return false;
<     }
< 
<     //**FIXME set up size - should be based on width of video
<     dlc.flags = (DFBDisplayLayerConfigFlags)(DLCONF_WIDTH | DLCONF_HEIGHT);
<     dlc.width = width;
<     dlc.height = height;
< 
<     ret = layer->SetConfiguration(layer, &dlc);
< 
<     if (ret)
<     {
<         DirectFBError("Couldn't set display size", ret);
<         return false;
<     }
< 
<     //**FIXME set up pixelformat - should be based on video
<     dlc.flags = DLCONF_PIXELFORMAT;
<     dlc.pixelformat = DSPF_YV12;
---
> 	if ((fb_dev_fd = open(fb_dev_name, O_RDWR)) == -1) {
>         DirectFBError("Couldn't open framebuffer", ret);
> 	}
> 	if (ioctl(fb_dev_fd, FBIOGET_VSCREENINFO, &fb_vinfo)) {
>         DirectFBError("Couldn't get screeninfo", ret);
> 	}
> 	close(fb_dev_fd);
> 	fb_dev_fd = -1;
> 			
331c329,330
<     ret = layer->SetConfiguration(layer, &dlc);
---
> 	data->screen_width = (int)fb_vinfo.xres;
> 	data->screen_height = (int)fb_vinfo.yres;
333,337d331
<     if (ret)
<     {
<         DirectFBError("Couldn't set requested pixelformat", ret);
<         return false;
<     }
339,341c333,337
<     dlc.flags = DLCONF_BUFFERMODE;
<     dlc.buffermode = DLBM_TRIPLE;
<     ret = layer->SetConfiguration(layer, &dlc);
---
> 	//setup DirectFB
>     DFBCHECKFAIL(DirectFBInit(NULL,NULL), false);
> 	
>     DirectFBSetOption("bg-none",NULL);
>     DirectFBSetOption("no-cursor",NULL);
343,345c339,362
<     if (ret)
<     {
<         DirectFBError("Couldn't set up triple buffering, trying double", ret);
---
> 	DFBCHECKFAIL(DirectFBCreate( &(data->dfb) ), false);
> 	
> 	//determine output card capacities
> 	DFBCHECKFAIL(data->dfb->GetCardCapabilities(data->dfb, &(data->cardCapabilities)), false);
> 	VERBOSE(VB_GENERAL, QString("DirectFB output : card : %1")
> 						.arg((data->cardCapabilities.acceleration_mask & DFXL_BLIT) > 0 ?
> 						"hardware blit support" : "NO hardware blit support"));
> 
> 
> 	//look up an output layer that supports the right format, begin with the video format we have as input, fall back to others
>     data->layerConfig.flags = (DFBDisplayLayerConfigFlags)(DLCONF_WIDTH | DLCONF_HEIGHT | DLCONF_PIXELFORMAT);
>     data->layerConfig.width = width;
>     data->layerConfig.height = height;
>     data->layerConfig.pixelformat = DSPF_I420;
> 	
>     DFBCHECK(data->dfb->EnumDisplayLayers(data->dfb, LayerCallback, data));
> 
> 	if(data->layer == NULL) {
> 		data->layerConfig.pixelformat = DSPF_YV12;
> 		DFBCHECK(data->dfb->EnumDisplayLayers(data->dfb, LayerCallback, data));
> 		if(data->layer == NULL) {
> 			return false;
> 		}
> 	}
347,348c364,365
<         dlc.buffermode = DLBM_BACKVIDEO;
<         ret = layer->SetConfiguration(layer, &dlc);
---
> 	//setup output layer
>     DFBCHECKFAIL(data->layer->SetCooperativeLevel(data->layer, DLSCL_EXCLUSIVE), false);
350c367,374
<         if (ret)
---
> 	//determine buffering capacities
>     data->layerConfig.flags = (DFBDisplayLayerConfigFlags)(data->layerConfig.flags | DLCONF_BUFFERMODE);
>     data->layerConfig.buffermode = DLBM_TRIPLE;
>     if (data->layer->TestConfiguration(data->layer, &(data->layerConfig), NULL))
> 	{
> 		//try double buffering in video memory
>         data->layerConfig.buffermode = DLBM_BACKVIDEO;
>         if (data->layer->TestConfiguration(data->layer, &(data->layerConfig), NULL))
352,358c376,377
<             dlc.buffermode = DLBM_BACKSYSTEM;
<             ret = layer->SetConfiguration(layer, &dlc);
< 
<             if (ret)
<             {
<                 DirectFBError("Couldn't set up double buffering, falling back to single buffer", ret);
<             }
---
> 			//fall back to double buffering in system memory
>             data->layerConfig.buffermode = DLBM_BACKSYSTEM;
360a380,381
> 	
>     DFBCHECKFAIL(data->layer->SetConfiguration(data->layer, &(data->layerConfig)), false);
361a383,406
> 	VERBOSE(VB_GENERAL, QString("DirectFB output : layer : %1 : %2x%3, %4, %5 buffering")
> 									.arg(data->layerDesc.name)
> 									.arg(data->layerConfig.width)
> 									.arg(data->layerConfig.height)
> 									.arg(data->layerConfig.pixelformat == DSPF_I420 ? "I420 : Yuv" : "YV12 : Yvu")
> 									.arg(
> 									data->layerConfig.buffermode == DLBM_TRIPLE ? "triple" :
> 									data->layerConfig.buffermode == DLBM_BACKVIDEO ? "double" :
> 									"single")
> 									);
> 
> 	//setup output surface
>     DFBCHECKFAIL(data->layer->GetSurface(data->layer, &(data->surface)), false);
> 
>     DFBCHECKFAIL(data->surface->SetBlittingFlags(data->surface, DSBLIT_NOFX), false);
> 	
> 	DFBSurfaceCapabilities capabilities;
> 	DFBCHECKFAIL(data->surface->GetCapabilities(data->surface, &capabilities), false);
> 
> 	VERBOSE(VB_GENERAL, QString("DirectFB output : surface : %1, %2, %3")
> 									.arg((capabilities & DSCAPS_VIDEOONLY) > 0 ? "in video memory" : "in sytem memory")
> 									.arg((capabilities & DSCAPS_PRIMARY) > 0 ? "primary surface" : "no primary surface")
> 									.arg((capabilities & DSCAPS_INTERLACED) > 0 ? "interlaced" : "not interlaced")
> 								);
363,378c408,410
<     ret = layer->GetSurface(layer, &(data->surface));
< 
<     if (ret)
<     {
<         DirectFBError( "Couldn't get our layer's surface - this is bad", ret);
<         return false;
<     }
< 
<     ret = data->surface->SetBlittingFlags(data->surface, DSBLIT_NOFX);
< 
<     if (ret)
<     {
<         DirectFBError("Couldn't set up Blitting flags - continuing anyway", ret);
<     }
< 
<     //**FIXME set surface properties - should use video
---
> 	//setup input buffers
>     VideoOutput::InitBuffers(kNumBuffers, true, kNeedFreeFrames,
>                              kPrebufferFrames, kKeepPrebuffer);
382c414,415
<     desc.pixelformat = DSPF_YV12;
---
> 	//can this change ?
>     desc.pixelformat = DSPF_I420;
383a417,437
>     if (!CreateDirectfbBuffers(desc))
>         return false;
> 	
> 	VERBOSE(VB_GENERAL, QString("DirectFB input : %1 surface buffers : %1x%2, %3")
> 									.arg(kNumBuffers)
> 									.arg(desc.width)
> 									.arg(desc.height)
> 									.arg(desc.pixelformat == DSPF_I420 ? "I420 : Yuv" : "YV12 : Yvu")
> 									);
> 	//prepare to do a software conversion when the output format is Yvu
> 	//(DirectFB does not support software conversion from Yuv -> Yvu yet)
> 	if(data->layerConfig.pixelformat == DSPF_YV12)
> 	{
> 		desc.flags = (DFBSurfaceDescriptionFlags)(DSDESC_HEIGHT | DSDESC_WIDTH | DSDESC_PIXELFORMAT | DSDESC_CAPS);
> 		desc.width = width;
> 		desc.height = height;
> 		desc.pixelformat = DSPF_YV12;
> 		//allocate in system memory
> 		desc.caps=DSCAPS_SYSTEMONLY;
> 		DFBCHECKFAIL(data->dfb->CreateSurface(data->dfb, &desc, &tempYV12Surface), false);
> 	} 
385,411c439
< 	// clear the surface
<     ret = data->surface->Clear(data->surface, 0x00, 0x00, 0x00, 0x00);
<     if (ret)
<     {
<         DirectFBError("Couldn't clear the buffers", ret);
<     }
< 
<     ret = data->surface->Flip(data->surface, NULL, DSFLIP_ONSYNC);
<     if (ret)
<     {
<         DirectFBError("Couldn't flip the buffers", ret);
<     }
< 
<     ret = data->surface->Clear(data->surface, 0x00, 0x00, 0x00, 0x00);
<     if (ret)
<     {
<         DirectFBError("Couldn't clear the buffers", ret);
<     }
< 
<     //show the surface
<     ret = layer->SetOpacity(layer, 255);
< 
<     if (ret)
<     {
<         DirectFBError("Couldn't make our layer visible - nothing to see here, go home", ret);
<     }
< 
---
> 	//setup input handling
432,434d459
<     if (!CreateDirectfbBuffers())
<         return false;
< 
435a461
> 	//first frame of the buffers
444c470,477
<     XJ_started = true;
---
>     VideoOutput::Init(width, height, aspect, winid, winx, winy, data->screen_width, data->screen_height,
>                       embedid);
> 	
> 	VERBOSE(VB_GENERAL, QString("DirectFB output : screen size %1x%2").arg(data->screen_width).arg(data->screen_height));
> 	MoveResize();
> 
> 	//display output layer
>     DFBCHECK(data->layer->SetOpacity(data->layer, 0xff));
445a479
>     XJ_started = true;
449c483
< void VideoOutputDirectfb::PrepareFrame(VideoFrame *buffer)
---
> float VideoOutputDirectfb::GetDisplayAspect(void)
451,455c485,486
<     DFBResult ret;
< 
<     int width, height, ysize, uvsize;
<     unsigned char *framebuf, *src, *dst;
<     int pitch;
---
> 	return (float)data->screen_width/(float)data->screen_height;
> }
456a488,489
> void VideoOutputDirectfb::PrepareFrame(VideoFrame *buffer)
> {
460,481c493
<     width = buffer->width;
<     height = buffer->height;
<     ysize = width * height;
<     uvsize = ysize / 4;
< 
<     ret = data->surface->Lock(data->surface, DSLF_WRITE, (void**)(&framebuf), &pitch);
< 
<     if (ret)
<     {
<         DirectFBError("Couldn't get write access to our surface", ret);
<         return;
<     }
< 
<     //memcpy(framebuf, buffer->buf, ysize * 3 / 2);
<     //**FIXME copy the frame's planes onto the surface - should do different
<     //behaviour depending on video?
<     //y-plane
<     memcpy(framebuf, buffer->buf, ysize);
<     //u-plane
<     memcpy(framebuf + width * height, buffer->buf + uvsize * 5, uvsize);
<     //v-plane
<     memcpy(framebuf + uvsize * 5, buffer->buf + ysize, uvsize);
---
> 	IDirectFBSurface *bufferSurface = data->buffers[buffer->buf];
483,488c495,553
<     ret = data->surface->Unlock(data->surface);
< 
<     if (ret)
<     {
<       DirectFBError("Unlock() failed", ret);
<     }
---
> 	if(data->layerConfig.pixelformat == DSPF_YV12)
> 	{
> 		//do a software conversion in a temporary memory buffer, since DirectFB does not handle this (yet ?)
> 		int pitch;
> 		int width, height;
> 		unsigned char *src, *dst;
> 
> 		width = buffer->width;
> 		height = buffer->height;
> 		src = buffer->buf;
> 
> 		DFBCHECKFAIL(tempYV12Surface->Lock(tempYV12Surface, DSLF_WRITE, (void **)&dst, &pitch));
> 		//! pitch is not considered : since the surface is in memory, normally there is no pitch
> 		//src Yuv -> dst Yvu
> 		//src Y -> dst Y
> 		memcpy(dst, src, width * height);
> 		//src V -> dst V
> 		memcpy(dst + width * height, src + width * height * 5 / 4, width * height / 4);
> 		//src U -> dst U
> 		memcpy(dst + width * height * 5 / 4, src + width * height, width * height / 4);
> 
> 		DFBCHECK(tempYV12Surface->Unlock(tempYV12Surface));
> 		bufferSurface = tempYV12Surface;
> 	} 
> 	if(!bufferSurface)
> 		return;
> 	if((data->cardCapabilities.acceleration_mask & DFXL_BLIT) > 0)
> 	{
> 		DFBCHECK(data->surface->Blit(data->surface, bufferSurface, NULL, 0, 0));
> 	}
> 	else
> 	{
> 		//unaccelerated hardware - probably you do not want this !
> 		int pitchsrc;
> 		int pitchdst;
> 		int width, height;
> 		unsigned char *src, *dst;
> 
> 		width = buffer->width;
> 		height = buffer->height;
> 		DFBCHECKFAIL(bufferSurface->Lock(bufferSurface, DSLF_READ, (void **)&src, &pitchsrc));
> 		DFBCHECKFAIL(data->surface->Lock(data->surface, DSLF_WRITE, (void **)&dst, &pitchdst));
> 		//Y
> 		memcpy_pic(dst, src, width, height, pitchdst, pitchsrc);
> 		dst += pitchdst * height;
> 		src += pitchsrc * height;
> 		//u (I420) or v (YV12)
> 		width /= 2;
> 		height /= 2;
> 		pitchsrc /= 2;
> 		pitchdst /= 2;
> 		memcpy_pic(dst, src, width, height, pitchdst, pitchsrc);
> 		dst += pitchdst * height;
> 		src += pitchsrc * height;
> 		//v (I420) or y (YV12)
> 		memcpy_pic(dst, src, width, height, pitchdst, pitchsrc);
> 		DFBCHECK(bufferSurface->Unlock(bufferSurface));
> 		DFBCHECK(data->surface->Unlock(data->surface));
> 	}
493,495d557
<     DFBResult ret;
< 
<     ret = data->surface->Flip(data->surface, NULL, DSFLIP_ONSYNC);
497,500c559
<     if (ret)
<     {
<         DirectFBError("Couldn't flip the buffers", ret);
<     }
---
>     DFBCHECK(data->surface->Flip(data->surface, NULL, DSFLIP_ONSYNC));
518,519c577,601
<     //**FIXME - should do something here
<     cerr << "DrawUnusedRects()" << endl;
---
> /* DirectFB only draws what is needed :-)
> 	VERBOSE(VB_GENERAL, QString("drawUnusedRects : screen size %1x%2, proposed x : %3, y : %4, w : %5, h : %6")
> 								.arg(data->screen_width)
> 								.arg(data->screen_height)
> 								.arg(dispxoff)
> 								.arg(dispyoff)
> 								.arg(dispwoff)
> 								.arg(disphoff));
>     // Draw black in masked areas
>     if (dispxoff > dispx) // left
> 		DFBCHECK (data->surface->FillRectangle (data->surface, 
>                        dispx, dispy, dispxoff-dispx, disph));
>     if (dispxoff+dispwoff < dispx+dispw) // right
> 		DFBCHECK (data->surface->FillRectangle (data->surface, 
>                        dispxoff+dispwoff, dispy, 
>                        (dispx+dispw)-(dispxoff+dispwoff), disph));
>     if (dispyoff > dispy) // bottom
> 		DFBCHECK (data->surface->FillRectangle (data->surface, 
>                        dispx, dispy, dispw, dispyoff-dispy));
>     if (dispyoff+disphoff < dispy+disph) // top
> 		DFBCHECK (data->surface->FillRectangle (data->surface, 
>                        dispx, dispyoff+disphoff, 
>                        dispw, (dispy+disph)-(dispyoff+disphoff)));
> //	DFBCHECK (data->surface->Flip (data->surface, NULL, 0));
> */
552c634,638
<     //**FIXME - MoveResize()??
---
> 	DFBSurfaceDescription desc;
>     desc.flags = (DFBSurfaceDescriptionFlags)(DSDESC_HEIGHT | DSDESC_WIDTH);
>     desc.width = width;
>     desc.height = height;
> 	
556c642,643
<     CreateDirectfbBuffers();
---
>     CreateDirectfbBuffers(desc);
> 	MoveResize();
572,573c659,660
<     //**FIXME - -do something here
<     cerr << "AspectChanged()" << endl;
---
>     VideoOutput::AspectChanged(aspect);
>     MoveResize();
582c669
< bool VideoOutputDirectfb::CreateDirectfbBuffers(void)
---
> void VideoOutputDirectfb::MoveResize(void)
583a671,696
>     VideoOutput::MoveResize();
> 
> 	VERBOSE(VB_GENERAL, QString("DirectFB MoveResize : screen size %1x%2, proposed x : %3, y : %4, w : %5, h : %6")
> 								.arg(data->screen_width)
> 								.arg(data->screen_height)
> 								.arg(dispxoff)
> 								.arg(dispyoff)
> 								.arg(dispwoff)
> 								.arg(disphoff));
> 	//**FIXME support for zooming when dispwoff > screenwidth || disphoff > screenheight
> 	DFBCHECK(data->layer->SetScreenLocation(data->layer,
> 											(float)dispxoff/(float)data->screen_width,
> 											(float)dispyoff/(float)data->screen_height,
> 											(float)dispwoff/(float)data->screen_width,
> 											(float)disphoff/(float)data->screen_height));
> }
> 	
> 
> 
> bool VideoOutputDirectfb::CreateDirectfbBuffers(DFBSurfaceDescription desc)
> {
> 	int pitch;
> 	//allocate each surface in system memory
> 	desc.flags = (DFBSurfaceDescriptionFlags)(desc.flags | DSDESC_CAPS);
> 	desc.caps=DSCAPS_SYSTEMONLY;
> 
586,587c699,706
<         vbuffers[i].height = XJ_height;
<         vbuffers[i].width = XJ_width;
---
> 		IDirectFBSurface *bufferSurface;
> 		unsigned char *bufferSurfaceData;
> 		DFBCHECKFAIL(data->dfb->CreateSurface(data->dfb, &desc, &bufferSurface), false);
> 		DFBCHECKFAIL(bufferSurface->Lock(bufferSurface, DSLF_WRITE, (void **)&bufferSurfaceData, &pitch), false);
> 		data->buffers[bufferSurfaceData] = bufferSurface;
>         vbuffers[i].height = desc.height;
>         vbuffers[i].width = desc.width;
> 		//**FIXME set the three following parameters correctly
589c708,709
<         vbuffers[i].size = XJ_height * XJ_width * 3 / 2;
---
>         vbuffers[i].size = desc.height * desc.width * 3 / 2;
> 		//The format FMT_YV12 is a I420 ???? - Can the buffer format change ????
591c711
<         vbuffers[i].buf = new unsigned char[vbuffers[i].size];
---
>         vbuffers[i].buf = bufferSurfaceData;
599c719,720
<     for (int i = 0 ; i < numbuffers +1; i++)
---
> 	map<unsigned char *, IDirectFBSurface *>::iterator iter = data->buffers.begin();
>     for (int i = 0 ; iter != data->buffers.end() ; iter++, i++)
600a722,723
> 		DFBCHECK(iter->second->Unlock(iter->second));
> 		DFBCHECK(iter->second->Release(iter->second));
603a727
> 	data->buffers.clear();
606d729
< //**FIXME - is there a way to make this part of the class?
611,612d733
<     struct DirectfbParams *params = &(vodata->params);
<     IDirectFBDisplayLayer *layer;
613a735
> 	IDirectFBSurface *surface;
615,631c737
<     ret = vodata->dfb->GetDisplayLayer(vodata->dfb, id, &layer);
< 
<     if (ret)
<     {
<         DirectFBError("Couldn't open layer", ret);
<         return DFENUM_OK;
<     }
< 
<     DFBDisplayLayerConfig dlc;
< 
<     if (params->setsize)
<     {
<         dlc.flags = (DFBDisplayLayerConfigFlags)(DLCONF_WIDTH | DLCONF_HEIGHT);
<         dlc.width = params->width;
<         dlc.height = params->height;
< 
<         ret = layer->SetConfiguration(layer, &dlc);
---
>     DFBCHECKFAIL(vodata->dfb->GetDisplayLayer(vodata->dfb, id, &(vodata->layer)), DFENUM_OK);
633,642c739,741
<         if (ret)
<         {
<             DirectFBError("Couldn't set layer size", ret);
<         }
<     }
< 
<     dlc.flags = DLCONF_PIXELFORMAT;
<     dlc.pixelformat = DSPF_YV12;
< 
<     layer->SetOpacity(layer, 0);
---
> 	//clear every surface we discover
> 	DFBCHECK(vodata->layer->GetSurface(vodata->layer, &surface));
> 	ClearSurface(surface);
644,646c743
<     ret = layer->TestConfiguration(layer, &dlc, NULL);
< 
<     layer->Release(layer);
---
>     ret = vodata->layer->TestConfiguration(vodata->layer, &(vodata->layerConfig), NULL);
650,663c747,748
<         if (params->result)
<         {
<             if (!params->scale && 0)
<             {
<                 params->scale = 1;
<                 params->id = id;
<             }
<             else
<             {
<                 params->result = 1;
< 	        params->id = id;
<             }
<         }
< 
---
> 		vodata->layerDesc = desc;
> 		return DFENUM_CANCEL;
665c750,752
< 
---
> 	else {
> 		vodata->layer->Release(vodata->layer);
> 	}
-------------- next part --------------
28c28
<     void AspectChanged(float aspect);
---
> 	void AspectChanged(float aspect);
30a31,33
> 	float GetDisplayAspect(void);
> 	void VideoOutputDirectfb::MoveResize();
> 
55c58
<     bool CreateDirectfbBuffers(void);
---
>     bool CreateDirectfbBuffers(DFBSurfaceDescription);
61a65,93
> static inline void * memcpy_pic(unsigned char * dst, unsigned char * src, int bytesPerLine, int height, int dstStride, int srcStride)
> {
>         int i;
>         void *retval=dst;
> 
>         if(dstStride == srcStride) memcpy(dst, src, srcStride*height);
>         else
>         {
>                 for(i=0; i<height; i++)
>                 {
>                         memcpy(dst, src, bytesPerLine);
>                         src+= srcStride;
>                         dst+= dstStride;
>                 }
>         }
> 
>         return retval;
> }
> static inline void ClearSurface(IDirectFBSurface *surface)
> {
>     if (surface)
>     {
>         for(int i=0; i<3; i++)
>         {
>             surface->Clear(surface, 0x00, 0x00, 0x00, 0xff);
>             surface->Flip(surface, NULL, DSFLIP_ONSYNC);
>         }
>     }
> }


More information about the mythtv-dev mailing list