Mercurial > sdl-ios-xcode
view src/video/windx5/SDL_dx5yuv.c @ 1719:5b9f50c957ed SDL-1.3
You can now create multiple windows on Win32
author | Sam Lantinga <slouken@libsdl.org> |
---|---|
date | Wed, 28 Jun 2006 08:12:07 +0000 |
parents | 4da1ee79c9af |
children |
line wrap: on
line source
/* SDL - Simple DirectMedia Layer Copyright (C) 1997-2006 Sam Lantinga This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA Sam Lantinga slouken@libsdl.org */ #include "SDL_config.h" /* This is the DirectDraw implementation of YUV video overlays */ #include "SDL_video.h" #include "SDL_dx5yuv_c.h" #include "../SDL_yuvfuncs.h" //#define USE_DIRECTX_OVERLAY /* The functions used to manipulate software video overlays */ static struct private_yuvhwfuncs dx5_yuvfuncs = { DX5_LockYUVOverlay, DX5_UnlockYUVOverlay, DX5_DisplayYUVOverlay, DX5_FreeYUVOverlay }; struct private_yuvhwdata { LPDIRECTDRAWSURFACE3 surface; /* These are just so we don't have to allocate them separately */ Uint16 pitches[3]; Uint8 *planes[3]; }; static LPDIRECTDRAWSURFACE3 CreateYUVSurface(_THIS, int width, int height, Uint32 format) { HRESULT result; LPDIRECTDRAWSURFACE dd_surface1; LPDIRECTDRAWSURFACE3 dd_surface3; DDSURFACEDESC ddsd; /* Set up the surface description */ SDL_memset(&ddsd, 0, sizeof(ddsd)); ddsd.dwSize = sizeof(ddsd); ddsd.dwFlags = (DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_PIXELFORMAT); ddsd.dwWidth = width; ddsd.dwHeight = height; #ifdef USE_DIRECTX_OVERLAY ddsd.ddsCaps.dwCaps = (DDSCAPS_OVERLAY | DDSCAPS_VIDEOMEMORY); #else ddsd.ddsCaps.dwCaps = (DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY); #endif ddsd.ddpfPixelFormat.dwSize = sizeof(ddsd.ddpfPixelFormat); ddsd.ddpfPixelFormat.dwFlags = DDPF_FOURCC; ddsd.ddpfPixelFormat.dwFourCC = format; /* Create the DirectDraw video surface */ result = IDirectDraw2_CreateSurface(ddraw2, &ddsd, &dd_surface1, NULL); if (result != DD_OK) { SetDDerror("DirectDraw2::CreateSurface", result); return (NULL); } result = IDirectDrawSurface_QueryInterface(dd_surface1, &IID_IDirectDrawSurface3, (LPVOID *) & dd_surface3); IDirectDrawSurface_Release(dd_surface1); if (result != DD_OK) { SetDDerror("DirectDrawSurface::QueryInterface", result); return (NULL); } /* Make sure the surface format was set properly */ SDL_memset(&ddsd, 0, sizeof(ddsd)); ddsd.dwSize = sizeof(ddsd); result = IDirectDrawSurface3_Lock(dd_surface3, NULL, &ddsd, DDLOCK_NOSYSLOCK, NULL); if (result != DD_OK) { SetDDerror("DirectDrawSurface3::Lock", result); IDirectDrawSurface_Release(dd_surface3); return (NULL); } IDirectDrawSurface3_Unlock(dd_surface3, NULL); if (!(ddsd.ddpfPixelFormat.dwFlags & DDPF_FOURCC) || (ddsd.ddpfPixelFormat.dwFourCC != format)) { SDL_SetError("DDraw didn't use requested FourCC format"); IDirectDrawSurface_Release(dd_surface3); return (NULL); } /* We're ready to go! */ return (dd_surface3); } #ifdef DEBUG_YUV static char * PrintFOURCC(Uint32 code) { static char buf[5]; buf[3] = code >> 24; buf[2] = (code >> 16) & 0xFF; buf[1] = (code >> 8) & 0xFF; buf[0] = (code & 0xFF); return (buf); } #endif SDL_Overlay * DX5_CreateYUVOverlay(_THIS, int width, int height, Uint32 format, SDL_Surface * display) { SDL_Overlay *overlay; struct private_yuvhwdata *hwdata; #ifdef DEBUG_YUV DWORD numcodes; DWORD *codes; printf("FOURCC format requested: 0x%x\n", PrintFOURCC(format)); IDirectDraw2_GetFourCCCodes(ddraw2, &numcodes, NULL); if (numcodes) { DWORD i; codes = SDL_malloc(numcodes * sizeof(*codes)); if (codes) { IDirectDraw2_GetFourCCCodes(ddraw2, &numcodes, codes); for (i = 0; i < numcodes; ++i) { fprintf(stderr, "Code %d: 0x%x\n", i, PrintFOURCC(codes[i])); } SDL_free(codes); } } else { fprintf(stderr, "No FOURCC codes supported\n"); } #endif /* Create the overlay structure */ overlay = (SDL_Overlay *) SDL_malloc(sizeof *overlay); if (overlay == NULL) { SDL_OutOfMemory(); return (NULL); } SDL_memset(overlay, 0, (sizeof *overlay)); /* Fill in the basic members */ overlay->format = format; overlay->w = width; overlay->h = height; /* Set up the YUV surface function structure */ overlay->hwfuncs = &dx5_yuvfuncs; /* Create the pixel data and lookup tables */ hwdata = (struct private_yuvhwdata *) SDL_malloc(sizeof *hwdata); overlay->hwdata = hwdata; if (hwdata == NULL) { SDL_OutOfMemory(); SDL_FreeYUVOverlay(overlay); return (NULL); } hwdata->surface = CreateYUVSurface(this, width, height, format); if (hwdata->surface == NULL) { SDL_FreeYUVOverlay(overlay); return (NULL); } overlay->hw_overlay = 1; /* Set up the plane pointers */ overlay->pitches = hwdata->pitches; overlay->pixels = hwdata->planes; switch (format) { case SDL_YV12_OVERLAY: case SDL_IYUV_OVERLAY: overlay->planes = 3; break; default: overlay->planes = 1; break; } /* We're all done.. */ return (overlay); } int DX5_LockYUVOverlay(_THIS, SDL_Overlay * overlay) { HRESULT result; LPDIRECTDRAWSURFACE3 surface; DDSURFACEDESC ddsd; surface = overlay->hwdata->surface; SDL_memset(&ddsd, 0, sizeof(ddsd)); ddsd.dwSize = sizeof(ddsd); result = IDirectDrawSurface3_Lock(surface, NULL, &ddsd, DDLOCK_NOSYSLOCK, NULL); if (result == DDERR_SURFACELOST) { result = IDirectDrawSurface3_Restore(surface); result = IDirectDrawSurface3_Lock(surface, NULL, &ddsd, (DDLOCK_NOSYSLOCK | DDLOCK_WAIT), NULL); } if (result != DD_OK) { SetDDerror("DirectDrawSurface3::Lock", result); return (-1); } /* Find the pitch and offset values for the overlay */ #if defined(NONAMELESSUNION) overlay->pitches[0] = (Uint16) ddsd.u1.lPitch; #else overlay->pitches[0] = (Uint16) ddsd.lPitch; #endif overlay->pixels[0] = (Uint8 *) ddsd.lpSurface; switch (overlay->format) { case SDL_YV12_OVERLAY: case SDL_IYUV_OVERLAY: /* Add the two extra planes */ overlay->pitches[1] = overlay->pitches[0] / 2; overlay->pitches[2] = overlay->pitches[0] / 2; overlay->pixels[1] = overlay->pixels[0] + overlay->pitches[0] * overlay->h; overlay->pixels[2] = overlay->pixels[1] + overlay->pitches[1] * overlay->h / 2; break; default: /* Only one plane, no worries */ break; } return (0); } void DX5_UnlockYUVOverlay(_THIS, SDL_Overlay * overlay) { LPDIRECTDRAWSURFACE3 surface; surface = overlay->hwdata->surface; IDirectDrawSurface3_Unlock(surface, NULL); } int DX5_DisplayYUVOverlay(_THIS, SDL_Overlay * overlay, SDL_Rect * src, SDL_Rect * dst) { HRESULT result; LPDIRECTDRAWSURFACE3 surface; RECT srcrect, dstrect; surface = overlay->hwdata->surface; srcrect.top = src->y; srcrect.bottom = srcrect.top + src->h; srcrect.left = src->x; srcrect.right = srcrect.left + src->w; dstrect.top = SDL_bounds.top + dst->y; dstrect.left = SDL_bounds.left + dst->x; dstrect.bottom = dstrect.top + dst->h; dstrect.right = dstrect.left + dst->w; #ifdef USE_DIRECTX_OVERLAY result = IDirectDrawSurface3_UpdateOverlay(surface, &srcrect, SDL_primary, &dstrect, DDOVER_SHOW, NULL); if (result != DD_OK) { SetDDerror("DirectDrawSurface3::UpdateOverlay", result); return (-1); } #else result = IDirectDrawSurface3_Blt(SDL_primary, &dstrect, surface, &srcrect, DDBLT_WAIT, NULL); if (result != DD_OK) { SetDDerror("DirectDrawSurface3::Blt", result); return (-1); } #endif return (0); } void DX5_FreeYUVOverlay(_THIS, SDL_Overlay * overlay) { struct private_yuvhwdata *hwdata; hwdata = overlay->hwdata; if (hwdata) { if (hwdata->surface) { IDirectDrawSurface_Release(hwdata->surface); } SDL_free(hwdata); } } /* vi: set ts=4 sw=4 expandtab: */