⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sdl_dx5video.c

📁 MPEG-4编解码的实现(包括MPEG4视音频编解码)
💻 C
📖 第 1 页 / 共 5 页
字号:
		goto error_end;
	}
	if ( (ddsd.dwWidth != (DWORD)surface->w) ||
		(ddsd.dwHeight != (DWORD)surface->h) ) {
		SDL_SetError("DDraw created surface with wrong size");
		goto error_end;
	}

	/* Set the surface private data */
	surface->flags |= flag;
	surface->hwdata->dd_surface = dd_surface3;
	if ( (surface->flags & SDL_DOUBLEBUF) == SDL_DOUBLEBUF ) {
		LPDIRECTDRAWSURFACE3 dd_writebuf;

		ddsd.ddsCaps.dwCaps = DDSCAPS_BACKBUFFER;
		result = IDirectDrawSurface3_GetAttachedSurface(dd_surface3,
						&ddsd.ddsCaps, &dd_writebuf);
		if ( result != DD_OK ) {
			SetDDerror("DirectDrawSurface3::GetAttachedSurface",
								result);
		} else {
			dd_surface3 = dd_writebuf;
		}
	}
	surface->hwdata->dd_writebuf = dd_surface3;

	/* We're ready to go! */
	return(0);

	/* Okay, so goto's are cheesy, but there are so many possible
	   errors in this function, and the cleanup is the same in 
	   every single case.  Is there a better way, other than deeply
	   nesting the code?
	*/
error_end:
	if ( (dd_surface3 != NULL) && (dd_surface3 != requested) ) {
		IDirectDrawSurface_Release(dd_surface3);
	}
	free(surface->hwdata);
	surface->hwdata = NULL;
	return(-1);
}

static int DX5_AllocHWSurface(_THIS, SDL_Surface *surface)
{
	/* DDraw limitation -- you need to set cooperative level first */
	if ( SDL_primary == NULL ) {
		SDL_SetError("You must set a non-GL video mode first");
		return(-1);
	}
	return(DX5_AllocDDSurface(this, surface, NULL, SDL_HWSURFACE));
}

#ifdef DDRAW_DEBUG
void PrintSurface(char *title, LPDIRECTDRAWSURFACE3 surface, Uint32 flags)
{
	DDSURFACEDESC ddsd;

	/* Lock and load! */
	memset(&ddsd, 0, sizeof(ddsd));
	ddsd.dwSize = sizeof(ddsd);
	if ( IDirectDrawSurface3_Lock(surface, NULL, &ddsd,
			(DDLOCK_NOSYSLOCK|DDLOCK_WAIT), NULL) != DD_OK ) {
		return;
	}
	IDirectDrawSurface3_Unlock(surface, NULL);
	
	fprintf(stderr, "%s:\n", title);
	fprintf(stderr, "\tSize: %dx%d in %s at %ld bpp (pitch = %ld)\n",
		ddsd.dwWidth, ddsd.dwHeight,
		(flags & SDL_HWSURFACE) ? "hardware" : "software",
#if defined(NONAMELESSUNION)
		ddsd.ddpfPixelFormat.u1.dwRGBBitCount, ddsd.u1.lPitch);
#else
		ddsd.ddpfPixelFormat.dwRGBBitCount, ddsd.lPitch);
#endif
	fprintf(stderr, "\tR = 0x%X, G = 0x%X, B = 0x%X\n", 
#if defined(NONAMELESSUNION)
	     		ddsd.ddpfPixelFormat.u2.dwRBitMask,
	     		ddsd.ddpfPixelFormat.u3.dwGBitMask,
	     		ddsd.ddpfPixelFormat.u4.dwBBitMask);
#else
	     		ddsd.ddpfPixelFormat.dwRBitMask,
	     		ddsd.ddpfPixelFormat.dwGBitMask,
	     		ddsd.ddpfPixelFormat.dwBBitMask);
#endif
}
#endif /* DDRAW_DEBUG */

static int DX5_HWAccelBlit(SDL_Surface *src, SDL_Rect *srcrect,
					SDL_Surface *dst, SDL_Rect *dstrect)
{
	LPDIRECTDRAWSURFACE3 src_surface;
	LPDIRECTDRAWSURFACE3 dst_surface;
	DWORD flags;
	RECT rect;
	HRESULT result;

	/* Set it up.. the desination must have a DDRAW surface */
	src_surface = src->hwdata->dd_writebuf;
	dst_surface = dst->hwdata->dd_writebuf;
	rect.top    = srcrect->y;
	rect.bottom = srcrect->y+srcrect->h;
	rect.left   = srcrect->x;
	rect.right  = srcrect->x+srcrect->w;
	if ( (src->flags & SDL_SRCCOLORKEY) == SDL_SRCCOLORKEY )
		flags = DDBLTFAST_SRCCOLORKEY;
	else
		flags = DDBLTFAST_NOCOLORKEY;
	/* FIXME:  We can remove this flag for _really_ fast blit queuing,
	           but it will affect the return values of locks and flips.
	 */
	flags |= DDBLTFAST_WAIT;

	/* Do the blit! */
	result = IDirectDrawSurface3_BltFast(dst_surface,
			dstrect->x, dstrect->y, src_surface, &rect, flags);
	if ( result != DD_OK ) {
		if ( result == DDERR_SURFACELOST ) {
			result = IDirectDrawSurface3_Restore(src_surface);
			result = IDirectDrawSurface3_Restore(dst_surface);
			/* The surfaces need to be reloaded with artwork */
			SDL_SetError("Blit surfaces were lost, reload them");
			return(-2);
		}
		SetDDerror("IDirectDrawSurface3::BltFast", result);
#ifdef DDRAW_DEBUG
 fprintf(stderr, "Original dest rect: %dx%d at %d,%d\n", dstrect->w, dstrect->h, dstrect->x, dstrect->y);
 fprintf(stderr, "HW accelerated %sblit to from 0x%p to 0x%p at (%d,%d)\n",
		(src->flags & SDL_SRCCOLORKEY) ? "colorkey " : "", src, dst,
					dstrect->x, dstrect->y);
  PrintSurface("SRC", src_surface, src->flags);
  PrintSurface("DST", dst_surface, dst->flags);
 fprintf(stderr, "Source rectangle: (%d,%d) - (%d,%d)\n",
		rect.left, rect.top, rect.right, rect.bottom);
#endif
		/* Unexpected error, fall back to software blit */
		return(src->map->sw_blit(src, srcrect, dst, dstrect));
	}
	return(0);
}

static int DX5_CheckHWBlit(_THIS, SDL_Surface *src, SDL_Surface *dst)
{
	int accelerated;

	/* We need to have a DDraw surface for HW blits */
	if ( (src->flags & SDL_HWSURFACE) == SDL_SWSURFACE ) {
		/* Allocate a DDraw surface for the blit */
		if ( src->hwdata == NULL ) {
			DX5_AllocDDSurface(this, src, NULL, SDL_SWSURFACE);
		}
	}
	if ( src->hwdata == NULL ) {
		return(0);
	}

	/* Set initial acceleration on */
	src->flags |= SDL_HWACCEL;

	/* Set the surface attributes */
	if ( (src->flags & SDL_SRCCOLORKEY) == SDL_SRCCOLORKEY ) {
		if ( DX5_SetHWColorKey(this, src, src->format->colorkey) < 0 ) {
			src->flags &= ~SDL_HWACCEL;
		}
	}
	if ( (src->flags & SDL_SRCALPHA) == SDL_SRCALPHA ) {
		if ( DX5_SetHWAlpha(this, src, src->format->alpha) < 0 ) {
			src->flags &= ~SDL_HWACCEL;
		}
	}

	/* Check to see if final surface blit is accelerated */
	accelerated = !!(src->flags & SDL_HWACCEL);
	if ( accelerated ) {
#ifdef DDRAW_DEBUG
  fprintf(stderr, "Setting accelerated blit on 0x%p\n", src);
#endif
		src->map->hw_blit = DX5_HWAccelBlit;
	}
	return(accelerated);
}

static int DX5_FillHWRect(_THIS, SDL_Surface *dst, SDL_Rect *dstrect, Uint32 color)
{
	LPDIRECTDRAWSURFACE3 dst_surface;
	RECT area;
	DDBLTFX bltfx;
	HRESULT result;

#ifdef DDRAW_DEBUG
 fprintf(stderr, "HW accelerated fill at (%d,%d)\n", dstrect->x, dstrect->y);
#endif
	dst_surface = dst->hwdata->dd_writebuf;
	area.top = dstrect->y;
	area.bottom = dstrect->y+dstrect->h;
	area.left = dstrect->x;
	area.right = dstrect->x+dstrect->w;
	bltfx.dwSize = sizeof(bltfx);
#if defined(NONAMELESSUNION)
	bltfx.u5.dwFillColor = color;
#else
	bltfx.dwFillColor = color;
#endif
	result = IDirectDrawSurface3_Blt(dst_surface,
			&area, NULL, NULL, DDBLT_COLORFILL|DDBLT_WAIT, &bltfx);
	if ( result == DDERR_SURFACELOST ) {
		IDirectDrawSurface3_Restore(dst_surface);
		result = IDirectDrawSurface3_Blt(dst_surface,
			&area, NULL, NULL, DDBLT_COLORFILL|DDBLT_WAIT, &bltfx);
	}
	if ( result != DD_OK ) {
		SetDDerror("IDirectDrawSurface3::Blt", result);
		return(-1);
	}
	return(0);
}

static int DX5_SetHWColorKey(_THIS, SDL_Surface *surface, Uint32 key)
{
	DDCOLORKEY colorkey;
	HRESULT result;

	/* Set the surface colorkey */
	colorkey.dwColorSpaceLowValue = key;
	colorkey.dwColorSpaceHighValue = key;
	result = IDirectDrawSurface3_SetColorKey(
			surface->hwdata->dd_surface, DDCKEY_SRCBLT, &colorkey);
	if ( result != DD_OK ) {
		SetDDerror("IDirectDrawSurface3::SetColorKey", result);
		return(-1);
	}
	return(0);
}
static int DX5_SetHWAlpha(_THIS, SDL_Surface *surface, Uint8 alpha)
{
	return(-1);
}

static int DX5_LockHWSurface(_THIS, SDL_Surface *surface)
{
	HRESULT result;
	LPDIRECTDRAWSURFACE3 dd_surface;
	DDSURFACEDESC ddsd;

	/* Lock and load! */
	dd_surface = surface->hwdata->dd_writebuf;
	memset(&ddsd, 0, sizeof(ddsd));
	ddsd.dwSize = sizeof(ddsd);
	result = IDirectDrawSurface3_Lock(dd_surface, NULL, &ddsd,
					(DDLOCK_NOSYSLOCK|DDLOCK_WAIT), NULL);
	if ( result == DDERR_SURFACELOST ) {
		result = IDirectDrawSurface3_Restore(
						surface->hwdata->dd_surface);
		result = IDirectDrawSurface3_Lock(dd_surface, NULL, &ddsd, 
					(DDLOCK_NOSYSLOCK|DDLOCK_WAIT), NULL);
	}
	if ( result != DD_OK ) {
		SetDDerror("DirectDrawSurface3::Lock", result);
		return(-1);
	}
	/* Pitch might have changed -- recalculate pitch and offset */
#if defined(NONAMELESSUNION)
	if ( surface->pitch != ddsd.u1.lPitch ) {
		surface->pitch = ddsd.u1.lPitch;
#else
	if ( surface->pitch != ddsd.lPitch ) {
		surface->pitch = (Uint16)ddsd.lPitch;
#endif
		surface->offset =
			((ddsd.dwHeight-surface->h)/2)*surface->pitch +
			((ddsd.dwWidth-surface->w)/2)*
					surface->format->BytesPerPixel;
	}
	surface->pixels = ddsd.lpSurface;
	return(0);
}

static void DX5_UnlockHWSurface(_THIS, SDL_Surface *surface)
{
	IDirectDrawSurface3_Unlock(surface->hwdata->dd_writebuf, NULL);
	surface->pixels = NULL;
}

static int DX5_FlipHWSurface(_THIS, SDL_Surface *surface)
{
	HRESULT result;
	LPDIRECTDRAWSURFACE3 dd_surface;

	dd_surface = surface->hwdata->dd_surface;
	result = IDirectDrawSurface3_Flip(dd_surface, NULL, DDFLIP_WAIT);
	if ( result == DDERR_SURFACELOST ) {
		result = IDirectDrawSurface3_Restore(
						surface->hwdata->dd_surface);
		result = IDirectDrawSurface3_Flip(dd_surface,NULL,DDFLIP_WAIT);
	}
	if ( result != DD_OK ) {
		SetDDerror("DirectDrawSurface3::Flip", result);
		return(-1);
	}
	return(0);
}

static void DX5_FreeHWSurface(_THIS, SDL_Surface *surface)
{
	if ( surface->hwdata ) {
		if ( surface->hwdata->dd_surface != SDL_primary ) {
			IDirectDrawSurface3_Release(surface->hwdata->dd_surface);
		}
		free(surface->hwdata);
		surface->hwdata = NULL;
	}
}

void DX5_WindowUpdate(_THIS, int numrects, SDL_Rect *rects)
{
	HRESULT result;
	int i;
	RECT src, dst;

	for ( i=0; i<numrects; ++i ) {
		src.top = rects[i].y;
		src.bottom = rects[i].y+rects[i].h;
		src.left = rects[i].x;
		src.right = rects[i].x+rects[i].w;
		dst.top = SDL_bounds.top+src.top;
		dst.left = SDL_bounds.left+src.left;
		dst.bottom = SDL_bounds.top+src.bottom;
		dst.right = SDL_bounds.left+src.right;
		result = IDirectDrawSurface3_Blt(SDL_primary, &dst, 
					this->screen->hwdata->dd_surface, &src,
							DDBLT_WAIT, NULL);
		/* Doh!  Check for lost surface and restore it */
		if ( result == DDERR_SURFACELOST ) {
			IDirectDrawSurface3_Restore(SDL_primary);
			IDirectDrawSurface3_Blt(SDL_primary, &dst, 
					this->screen->hwdata->dd_surface, &src,
							DDBLT_WAIT, NULL);
		}
	}
}

void DX5_DirectUpdate(_THIS, int numrects, SDL_Rect *rects)
{
}

/* Compress a full palette into the limited number of colors given to us
   by windows.

   The "best" way to do this is to sort the colors by diversity and place
   the most diverse colors into the limited palette.  Unfortunately this
   results in widely varying colors being displayed in the interval during
   which the windows palette has been set, and the mapping of the shadow
   surface to the new palette.  This is especially noticeable during fades.

   To deal with this problem, we can copy a predetermined portion of the
   full palette, and use that as the limited palette.  This allows colors
   to fade smoothly as the remapping is very similar on each palette change.
   Unfortunately, this breaks applications which partition the palette into
   distinct and widely varying areas, expecting all colors to be available.

   I'm making them both available, chosen at compile time.
   If you want the chunk-o-palette algorithm, define SIMPLE_COMPRESSION,
   otherwise the sort-by-diversity algorithm will be used.
*/
#define SIMPLE_COMPRESSION
#define CS_CS_DIST(A, B) ({						\
	int r = (A.r - B.r);						\
	int g = (A.g - B.g);						\
	int b = (A.b - B.b);						\
	(r*r + g*g + b*b);						\
})
static void DX5_CompressPalette(_THIS, SDL_Color *colors, int ncolors, int maxcolors)
{
#ifdef SIMPLE_COMPRESSION
	int i, j;
#else
	static SDL_Color zero = { 0, 0, 0, 0 };
	int i, j;
	int max, dist;
	int prev, next;
	int *pool;
	int *seen, *order;
#endif

	/* Does this happen? */
	if ( maxcolors > ncolors ) {
		maxcolors = ncolors;
	}

#ifdef SIMPLE_COMPRESSION
	/* Just copy the first "maxcolors" colors */
	for ( j=10, i=0; i<maxcolors; ++i, ++j ) {
		SDL_colors[j].peRed = colors[i].r;
		SDL_colors[j].peGreen = colors[i].g;
		SDL_colors[j].peBlue = colors[i].b;
	}
#else
	/* Allocate memory for the arrays we use */
	pool = (int *)alloca(2*ncolors*sizeof(int));
	if ( pool == NULL ) {
		/* No worries, just return */;
		return;
	}
	seen = pool;
	memset(seen, 0,

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -