📄 sdl_dx5video.c
字号:
(DDSCAPS_OFFSCREENPLAIN|DDSCAPS_VIDEOMEMORY); } else { ddsd.ddsCaps.dwCaps = (DDSCAPS_OFFSCREENPLAIN|DDSCAPS_SYSTEMMEMORY); } ddsd.ddpfPixelFormat.dwSize = sizeof(ddsd.ddpfPixelFormat); ddsd.ddpfPixelFormat.dwFlags = DDPF_RGB; if ( surface->format->palette ) { ddsd.ddpfPixelFormat.dwFlags |= DDPF_PALETTEINDEXED8; }#if defined(NONAMELESSUNION) ddsd.ddpfPixelFormat.u1.dwRGBBitCount = surface->format->BitsPerPixel; ddsd.ddpfPixelFormat.u2.dwRBitMask = surface->format->Rmask; ddsd.ddpfPixelFormat.u3.dwGBitMask = surface->format->Gmask; ddsd.ddpfPixelFormat.u4.dwBBitMask = surface->format->Bmask;#else ddsd.ddpfPixelFormat.dwRGBBitCount = surface->format->BitsPerPixel; ddsd.ddpfPixelFormat.dwRBitMask = surface->format->Rmask; ddsd.ddpfPixelFormat.dwGBitMask = surface->format->Gmask; ddsd.ddpfPixelFormat.dwBBitMask = surface->format->Bmask;#endif /* Create the DirectDraw video surface */ if ( requested != NULL ) { dd_surface3 = requested; } else { result = IDirectDraw2_CreateSurface(ddraw2, &ddsd, &dd_surface1, NULL); if ( result != DD_OK ) { SetDDerror("DirectDraw2::CreateSurface", result); goto error_end; } result = IDirectDrawSurface_QueryInterface(dd_surface1, &IID_IDirectDrawSurface3, (LPVOID *)&dd_surface3); IDirectDrawSurface_Release(dd_surface1); if ( result != DD_OK ) { SetDDerror("DirectDrawSurface::QueryInterface", result); goto error_end; } } if ( (flag & SDL_HWSURFACE) == SDL_HWSURFACE ) { /* Check to see whether the surface actually ended up in video memory, and fail if not. We expect the surfaces we create here to actually be in hardware! */ result = IDirectDrawSurface3_GetCaps(dd_surface3,&ddsd.ddsCaps); if ( result != DD_OK ) { SetDDerror("DirectDrawSurface3::GetCaps", result); goto error_end; } if ( (ddsd.ddsCaps.dwCaps&DDSCAPS_VIDEOMEMORY) != DDSCAPS_VIDEOMEMORY ) { SDL_SetError("No room in video memory"); goto error_end; } } else { /* Try to hook our surface memory */ ddsd.dwFlags = DDSD_LPSURFACE; ddsd.lpSurface = surface->pixels; result = IDirectDrawSurface3_SetSurfaceDesc(dd_surface3, &ddsd, 0); if ( result != DD_OK ) { SetDDerror("DirectDraw2::SetSurfaceDesc", result); goto error_end; } } /* 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|DDLOCK_WAIT), NULL); if ( result != DD_OK ) { SetDDerror("DirectDrawSurface3::Lock", result); goto error_end; } IDirectDrawSurface3_Unlock(dd_surface3, NULL); if ( (flag & SDL_HWSURFACE) == SDL_SWSURFACE ) { if ( ddsd.lpSurface != surface->pixels ) { SDL_SetError("DDraw didn't use SDL surface memory"); goto error_end; } if (#if defined(NONAMELESSUNION) ddsd.u1.lPitch#else ddsd.lPitch#endif != (LONG)surface->pitch ) { SDL_SetError("DDraw created surface with wrong pitch"); goto error_end; } } else {#if defined(NONAMELESSUNION) surface->pitch = (Uint16)ddsd.u1.lPitch;#else surface->pitch = (Uint16)ddsd.lPitch;#endif }#if defined(NONAMELESSUNION) if ( (ddsd.ddpfPixelFormat.u1.dwRGBBitCount != surface->format->BitsPerPixel) || (ddsd.ddpfPixelFormat.u2.dwRBitMask != surface->format->Rmask) || (ddsd.ddpfPixelFormat.u3.dwGBitMask != surface->format->Gmask) || (ddsd.ddpfPixelFormat.u4.dwBBitMask != surface->format->Bmask) ){#else if ( (ddsd.ddpfPixelFormat.dwRGBBitCount != surface->format->BitsPerPixel) || (ddsd.ddpfPixelFormat.dwRBitMask != surface->format->Rmask) || (ddsd.ddpfPixelFormat.dwGBitMask != surface->format->Gmask) || (ddsd.ddpfPixelFormat.dwBBitMask != surface->format->Bmask) ){#endif SDL_SetError("DDraw didn't use SDL surface description"); 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); } SDL_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_DEBUGvoid PrintSurface(char *title, LPDIRECTDRAWSURFACE3 surface, Uint32 flags){ DDSURFACEDESC ddsd; /* Lock and load! */ SDL_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 = (LONG)srcrect->y; rect.bottom = (LONG)srcrect->y+srcrect->h; rect.left = (LONG)srcrect->x; rect.right = (LONG)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 = (LONG)dstrect->y; area.bottom = (LONG)dstrect->y+dstrect->h; area.left = (LONG)dstrect->x; area.right = (LONG)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; SDL_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; /* to prevent big slowdown on fast computers, wait here instead of driver ring 0 code */ /* Dmitry Yakimov (ftech@tula.net) */ while(IDirectDrawSurface3_GetFlipStatus(dd_surface, DDGBS_ISBLTDONE) == DDERR_WASSTILLDRAWING); result = IDirectDrawSurface3_Flip(dd_surface, NULL, DDFLIP_WAIT); if ( result == DDERR_SURFACELOST ) { result = IDirectDrawSurface3_Restore( surface->hwdata->dd_surface); while(ID
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -