From 7b8018c5a8127bbdc775bc8c42cdab0d4772aed3 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Mon, 9 Nov 2009 05:20:11 +0000 Subject: [PATCH] Work in progress on implementation of SDL_RenderReadPixels() and SDL_RenderWritePixels(), code untested. --- src/video/SDL_renderer_sw.c | 76 +++++++++++++++++++++++++++++++++ src/video/SDL_sysvideo.h | 4 ++ src/video/SDL_video.c | 76 +++++++++++++++++++++++++++++++++ src/video/win32/SDL_d3drender.c | 47 ++++++++++++++++++++ 4 files changed, 203 insertions(+) diff --git a/src/video/SDL_renderer_sw.c b/src/video/SDL_renderer_sw.c index 75b468652..1365645ad 100644 --- a/src/video/SDL_renderer_sw.c +++ b/src/video/SDL_renderer_sw.c @@ -65,6 +65,10 @@ static int SW_RenderLine(SDL_Renderer * renderer, int x1, int y1, int x2, static int SW_RenderFill(SDL_Renderer * renderer, const SDL_Rect * rect); static int SW_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture, const SDL_Rect * srcrect, const SDL_Rect * dstrect); +static int SW_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect, + void * pixels, int pitch); +static int SW_RenderWritePixels(SDL_Renderer * renderer, const SDL_Rect * rect, + const void * pixels, int pitch); static void SW_RenderPresent(SDL_Renderer * renderer); static void SW_DestroyTexture(SDL_Renderer * renderer, SDL_Texture * texture); static void SW_DestroyRenderer(SDL_Renderer * renderer); @@ -228,6 +232,8 @@ SW_CreateRenderer(SDL_Window * window, Uint32 flags) renderer->RenderLine = SW_RenderLine; renderer->RenderFill = SW_RenderFill; renderer->RenderCopy = SW_RenderCopy; + renderer->RenderReadPixels = SW_RenderReadPixels; + renderer->RenderWritePixels = SW_RenderWritePixels; renderer->RenderPresent = SW_RenderPresent; renderer->DestroyRenderer = SW_DestroyRenderer; renderer->info.name = SW_RenderDriver.info.name; @@ -728,6 +734,76 @@ SW_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture, return status; } +static int +SW_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect, + void * pixels, int pitch) +{ + SW_RenderData *data = (SW_RenderData *) renderer->driverdata; + const Uint8 *src; + Uint8 *dst; + int src_pitch, dst_pitch, w, h; + + if (data->renderer->LockTexture(data->renderer, + data->texture[data->current_texture], + rect, 0, &data->surface.pixels, + &data->surface.pitch) < 0) { + return -1; + } + + src = data->surface.pixels; + src_pitch = data->surface.pitch; + dst = pixels; + dst_pitch = pitch; + h = rect->h; + w = rect->w * data->surface.format->BytesPerPixel; + while (h--) { + SDL_memcpy(dst, src, w); + src += src_pitch; + dst += dst_pitch; + } + + data->renderer->UnlockTexture(data->renderer, + data->texture[data->current_texture]); + return 0; +} + +static int +SW_RenderWritePixels(SDL_Renderer * renderer, const SDL_Rect * rect, + const void * pixels, int pitch) +{ + SW_RenderData *data = (SW_RenderData *) renderer->driverdata; + const Uint8 *src; + Uint8 *dst; + int src_pitch, dst_pitch, w, h; + + if (data->renderer->info.flags & SDL_RENDERER_PRESENTCOPY) { + SDL_AddDirtyRect(&data->dirty, rect); + } + + if (data->renderer->LockTexture(data->renderer, + data->texture[data->current_texture], + rect, 1, &data->surface.pixels, + &data->surface.pitch) < 0) { + return -1; + } + + src = pixels; + src_pitch = pitch; + dst = data->surface.pixels; + dst_pitch = data->surface.pitch; + h = rect->h; + w = rect->w * data->surface.format->BytesPerPixel; + while (h--) { + SDL_memcpy(dst, src, w); + src += src_pitch; + dst += dst_pitch; + } + + data->renderer->UnlockTexture(data->renderer, + data->texture[data->current_texture]); + return 0; +} + static void SW_RenderPresent(SDL_Renderer * renderer) { diff --git a/src/video/SDL_sysvideo.h b/src/video/SDL_sysvideo.h index 1d32db268..65c2a96ce 100644 --- a/src/video/SDL_sysvideo.h +++ b/src/video/SDL_sysvideo.h @@ -96,6 +96,10 @@ struct SDL_Renderer int (*RenderFill) (SDL_Renderer * renderer, const SDL_Rect * rect); int (*RenderCopy) (SDL_Renderer * renderer, SDL_Texture * texture, const SDL_Rect * srcrect, const SDL_Rect * dstrect); + int (*RenderReadPixels) (SDL_Renderer * renderer, const SDL_Rect * rect, + void * pixels, int pitch); + int (*RenderWritePixels) (SDL_Renderer * renderer, const SDL_Rect * rect, + const void * pixels, int pitch); void (*RenderPresent) (SDL_Renderer * renderer); void (*DestroyTexture) (SDL_Renderer * renderer, SDL_Texture * texture); diff --git a/src/video/SDL_video.c b/src/video/SDL_video.c index 278594527..c22cddb16 100644 --- a/src/video/SDL_video.c +++ b/src/video/SDL_video.c @@ -2486,6 +2486,82 @@ SDL_RenderCopy(SDL_TextureID textureID, const SDL_Rect * srcrect, &real_dstrect); } +int +SDL_RenderReadPixels(const SDL_Rect * rect, void * pixels, int pitch) +{ + SDL_Renderer *renderer; + SDL_Window *window; + SDL_Rect real_rect; + + renderer = SDL_GetCurrentRenderer(); + if (!renderer) { + return -1; + } + if (!renderer->RenderReadPixels) { + SDL_Unsupported(); + return -1; + } + window = SDL_GetWindowFromID(renderer->window); + + real_rect.x = 0; + real_rect.y = 0; + real_rect.w = window->w; + real_rect.h = window->h; + if (rect) { + if (!SDL_IntersectRect(rect, &real_rect, &real_rect)) { + return 0; + } + if (real_rect.y > rect->y) { + pixels = (Uint8 *)pixels + pitch * (real_rect.y - rect->y); + } + if (real_rect.x > rect->x) { + Uint32 format = SDL_CurrentDisplay.current_mode.format; + int bpp = SDL_BYTESPERPIXEL(format); + pixels = (Uint8 *)pixels + bpp * (real_rect.x - rect->x); + } + } + + return renderer->RenderReadPixels(renderer, &real_rect, pixels, pitch); +} + +int +SDL_RenderWritePixels(const SDL_Rect * rect, const void * pixels, int pitch) +{ + SDL_Renderer *renderer; + SDL_Window *window; + SDL_Rect real_rect; + + renderer = SDL_GetCurrentRenderer(); + if (!renderer) { + return -1; + } + if (!renderer->RenderWritePixels) { + SDL_Unsupported(); + return -1; + } + window = SDL_GetWindowFromID(renderer->window); + + real_rect.x = 0; + real_rect.y = 0; + real_rect.w = window->w; + real_rect.h = window->h; + if (rect) { + if (!SDL_IntersectRect(rect, &real_rect, &real_rect)) { + return 0; + } + if (real_rect.y > rect->y) { + pixels = (const Uint8 *)pixels + pitch * (real_rect.y - rect->y); + } + if (real_rect.x > rect->x) { + Uint32 format = SDL_CurrentDisplay.current_mode.format; + int bpp = SDL_BYTESPERPIXEL(format); + pixels = (const Uint8 *)pixels + bpp * (real_rect.x - rect->x); + } + } + + return renderer->RenderWritePixels(renderer, &real_rect, pixels, pitch); +} + void SDL_RenderPresent(void) { diff --git a/src/video/win32/SDL_d3drender.c b/src/video/win32/SDL_d3drender.c index 2ea8cc21f..3692b829b 100644 --- a/src/video/win32/SDL_d3drender.c +++ b/src/video/win32/SDL_d3drender.c @@ -72,6 +72,8 @@ static int D3D_RenderLine(SDL_Renderer * renderer, int x1, int y1, int x2, static int D3D_RenderFill(SDL_Renderer * renderer, const SDL_Rect * rect); static int D3D_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture, const SDL_Rect * srcrect, const SDL_Rect * dstrect); +static int D3D_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect, + void * pixels, int pitch); static void D3D_RenderPresent(SDL_Renderer * renderer); static void D3D_DestroyTexture(SDL_Renderer * renderer, SDL_Texture * texture); @@ -367,6 +369,7 @@ D3D_CreateRenderer(SDL_Window * window, Uint32 flags) renderer->RenderLine = D3D_RenderLine; renderer->RenderFill = D3D_RenderFill; renderer->RenderCopy = D3D_RenderCopy; + renderer->RenderReadPixels = D3D_RenderReadPixels; renderer->RenderPresent = D3D_RenderPresent; renderer->DestroyTexture = D3D_DestroyTexture; renderer->DestroyRenderer = D3D_DestroyRenderer; @@ -1145,6 +1148,50 @@ D3D_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture, return 0; } +static int +D3D_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect, + void * pixels, int pitch) +{ + BYTE * pBytes; + D3DLOCKED_RECT lockedRect; + BYTE b, g, r, a; + unsigned long index; + int cur_mouse; + int x, y; + + LPDIRECT3DSURFACE9 backBuffer; + LPDIRECT3DSURFACE9 pickOffscreenSurface; + D3DSURFACE_DESC desc; + + D3D_RenderData * data = (D3D_RenderData *) renderer->driverdata; + + IDirect3DDevice9_GetBackBuffer(data->device, 0, 0, D3DBACKBUFFER_TYPE_MONO, &backBuffer); + + + IDirect3DSurface9_GetDesc(backBuffer, &desc); + + IDirect3DDevice9_CreateOffscreenPlainSurface(data->device, desc.Width, desc.Height, desc.Format, D3DPOOL_SYSTEMMEM, &pickOffscreenSurface, NULL); + + IDirect3DDevice9_GetRenderTargetData(data->device, backBuffer, pickOffscreenSurface); + + IDirect3DSurface9_LockRect(pickOffscreenSurface, &lockedRect, NULL, D3DLOCK_READONLY); + pBytes = (BYTE*)lockedRect.pBits; + IDirect3DSurface9_UnlockRect(pickOffscreenSurface); + + // just to debug --> + cur_mouse = SDL_SelectMouse(-1); + SDL_GetMouseState(cur_mouse, &x, &y); + index = (x * 4 + (y * lockedRect.Pitch)); + + b = pBytes[index]; + g = pBytes[index+1]; + r = pBytes[index+2]; + a = pBytes[index+3]; + // <-- + + return -1; +} + static void D3D_RenderPresent(SDL_Renderer * renderer) {