Skip to content
Permalink
Browse files

Generic Surface Transfer (#1722)

* Generalize sprite read/copy functions using texture abstractions.
* Fix D3D9 texture abstractions for render target textures using system memory copy.
* Fix GL texture subimage copy function to return contiguous array.
* Deduplicate GL1 and GL3 texture source to the general OpenGL/ folder.
* Expand draw CI test to cover surface draw/copy/read.
  • Loading branch information...
RobertBColton committed May 16, 2019
1 parent 27aa3ff commit 55fde1e930a7e8db5ba6e355f903cf49c1160e95
@@ -5,7 +5,7 @@
TEST(Regression, draw_test) {
if (!TestHarness::windowing_supported()) return;
TestConfig tc;
tc.extensions = "Paths,libpng";
tc.extensions = "Paths,libpng,GTest";
auto test_harness = LAUNCH_HARNESS_FOR_SOG(tc);
if (!test_harness) FAIL() << "Game could not be run.";

@@ -21,3 +21,31 @@ vertex_color(vb_diamond, c_red, 1);

vertex_end(vb_diamond);
vertex_freeze(vb_diamond);

surf_test = surface_create(32,32);
surf_dup = surface_create(32,32);

surface_set_target(surf_test);
draw_set_color(c_red);
draw_rectangle(0,0,16,16,false);
draw_set_color(c_green);
draw_rectangle(0,16,16,32,false);
draw_set_color(c_yellow);
draw_rectangle(16,0,32,32,false);
surface_reset_target();

surf_spr = sprite_create_from_surface(surf_test,0,0,32,32,false,false,false,0,0);
surf_back = background_create_from_surface(surf_test,0,0,32,32,false,false);

surface_copy_part(surf_dup,0,0,surf_test,8,8,16,16);
surface_copy_part(surf_dup,0,16,surf_test,8,8,16,16);
surface_copy_part(surf_dup,16,0,surf_test,8,8,16,16);
surface_copy_part(surf_dup,16,16,surf_test,8,8,16,16);
surface_set_target(surf_dup);
draw_set_color(c_blue);
draw_rectangle(8,8,24,24,false);
surface_reset_target();

gtest_expect_eq(surface_getpixel(surf_dup,2,2),c_red);
gtest_expect_eq(surface_getpixel(surf_dup,2,10),c_green);
gtest_expect_eq(surface_getpixel(surf_dup,16,16),c_blue);
@@ -54,3 +54,9 @@ draw_sprite_stretched_ext(spr,0,25,0,25,25,c_red,0.5);

// draw duplicate sprite
draw_sprite(spr2,0,0,25);

// surface tests
draw_surface(surf_test,0,room_height-32);
draw_sprite(surf_spr,0,32,room_height-32);
draw_background(surf_back,0,room_height-64);
draw_surface(surf_dup,32,room_height-64);
@@ -21,17 +21,6 @@
#include "Graphics_Systems/General/GSsurface.h"
#include "Graphics_Systems/General/GStextures_impl.h"
#include "Graphics_Systems/General/GSprimitives.h"
#include "Graphics_Systems/General/GScolor_macros.h"

#include "Universal_System/nlpo2.h"
#include "Universal_System/Resources/sprites_internal.h"
#include "Universal_System/Resources/background_internal.h"
#include "Collision_Systems/collision_types.h"

#include <iostream>
#include <cstddef>
#include <math.h>
#include <stdio.h> //for file writing (surface_save)

using namespace std;
using namespace enigma::dx11;
@@ -144,72 +133,4 @@ void surface_free(int id)
delete enigma::surfaces[id];
}

int surface_getpixel(int id, int x, int y)
{
return 0; //TODO: implement
}

int surface_getpixel_ext(int id, int x, int y)
{
return 0; //TODO: implement
}

int surface_getpixel_alpha(int id, int x, int y)
{
return 0; //TODO: implement
}

}

//////////////////////////////////////SAVE TO FILE AND CTEATE SPRITE FUNCTIONS/////////
//Fuck whoever did this to the spec
#ifndef DX_BGR
#define DX_BGR 0x80E0
#endif

#include "Universal_System/estring.h"

namespace enigma_user
{

int surface_save(int id, string filename)
{
return -1; //TODO: implement
}

int surface_save_part(int id, string filename, unsigned x, unsigned y, unsigned w, unsigned h)
{
return -1; //TODO: implement
}

int background_create_from_surface(int id, int x, int y, int w, int h, bool removeback, bool smooth, bool preload)
{
return -1; //TODO: implement
}

int sprite_create_from_surface(int id, int x, int y, int w, int h, bool removeback, bool smooth, bool preload, int xorig, int yorig)
{
return -1; //TODO: implement
}

int sprite_create_from_surface(int id, int x, int y, int w, int h, bool removeback, bool smooth, int xorig, int yorig)
{
return sprite_create_from_surface(id, x, y, w, h, removeback, smooth, true, xorig, yorig);
}

void sprite_add_from_surface(int ind, int id, int x, int y, int w, int h, bool removeback, bool smooth)
{

}

void surface_copy_part(int destination, gs_scalar x, gs_scalar y, int source, int xs, int ys, int ws, int hs)
{

}

void surface_copy(int destination, gs_scalar x, gs_scalar y, int source)
{

}

}
@@ -22,35 +22,10 @@
#include "Graphics_Systems/General/GStextures_impl.h"
#include "Graphics_Systems/General/GSprimitives.h"
#include "Graphics_Systems/General/GSmatrix.h"
#include "Graphics_Systems/General/GScolor_macros.h"

#include "Universal_System/nlpo2.h"
#include "Universal_System/Resources/sprites_internal.h"
#include "Universal_System/Resources/background_internal.h"
#include "Collision_Systems/collision_types.h"

#include <iostream>
#include <cstddef>
#include <math.h>
#include <stdio.h> //for file writing (surface_save)

using namespace std;
using namespace enigma::dx9;

namespace enigma {

//TODO Add caching of the surface's RAM copy to speed this shit up
//Maybe also investigate the use of CreateRenderTarget
void surface_copy_to_ram(IDirect3DSurface9 **src, IDirect3DSurface9 **dest) {
D3DSURFACE_DESC desc;
(*src)->GetDesc(&desc);

d3ddev->CreateOffscreenPlainSurface(desc.Width, desc.Height, desc.Format, D3DPOOL_SYSTEMMEM, dest, NULL);
d3ddev->GetRenderTargetData(*src, *dest);
}

} // namespace enigma

namespace enigma_user {

bool surface_is_supported()
@@ -65,6 +40,8 @@ int surface_create(int width, int height, bool depthbuffer, bool, bool)
d3ddev->CreateTexture(width, height, 1, D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &texture, NULL);
enigma::Surface* surface = new enigma::Surface();
enigma::DX9Texture* gmTexture = new enigma::DX9Texture(texture);
gmTexture->width = gmTexture->fullwidth = width;
gmTexture->height = gmTexture->fullheight = height;
const int texid = enigma::textures.size();
enigma::textures.push_back(gmTexture);
//d3ddev->CreateRenderTarget(width, height, D3DFMT_A8R8G8B8, D3DMULTISAMPLE_2_SAMPLES, 2, false, &surface->surf, NULL);
@@ -80,6 +57,8 @@ int surface_create_msaa(int width, int height, int levels)
d3ddev->CreateTexture(width, height, 1, D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &texture, NULL);
enigma::Surface* surface = new enigma::Surface();
enigma::DX9Texture* gmTexture = new enigma::DX9Texture(texture);
gmTexture->width = gmTexture->fullwidth = width;
gmTexture->height = gmTexture->fullheight = height;
const int texid = enigma::textures.size();
enigma::textures.push_back(gmTexture);
d3ddev->CreateRenderTarget(width, height, D3DFMT_A8R8G8B8, D3DMULTISAMPLE_2_SAMPLES, 2, false, &surface->surf, NULL);
@@ -118,152 +97,4 @@ void surface_free(int id)
delete enigma::surfaces[id];
}

int surface_getpixel(int id, int x, int y)
{
get_surfacev(surface,id,-1);
if (x < 0) x = 0;
if (y < 0) y = 0;
if (x > surface.width || y > surface.height) return 0;
draw_batch_flush(batch_flush_deferred);

LPDIRECT3DSURFACE9 pBuffer = surface.surf, pRamBuffer;
enigma::surface_copy_to_ram(&pBuffer, &pRamBuffer);

D3DLOCKED_RECT rect;

pRamBuffer->LockRect(&rect, NULL, D3DLOCK_READONLY);
unsigned char* bitmap = static_cast<unsigned char*>(rect.pBits);
unsigned offset = y * rect.Pitch + x * 4;
int ret = bitmap[offset + 2] | (bitmap[offset + 1] << 8) | (bitmap[offset + 0] << 16);
pRamBuffer->UnlockRect();

pRamBuffer->Release();

return ret;
}

int surface_getpixel_ext(int id, int x, int y)
{
get_surfacev(surface,id,-1);
if (x < 0) x = 0;
if (y < 0) y = 0;
if (x > surface.width || y > surface.height) return 0;
draw_batch_flush(batch_flush_deferred);

LPDIRECT3DSURFACE9 pBuffer = surface.surf, pRamBuffer;
enigma::surface_copy_to_ram(&pBuffer, &pRamBuffer);

D3DLOCKED_RECT rect;

pRamBuffer->LockRect(&rect, NULL, D3DLOCK_READONLY);
unsigned char* bitmap = static_cast<unsigned char*>(rect.pBits);
unsigned offset = y * rect.Pitch + x * 4;
int ret = bitmap[offset + 2] | (bitmap[offset + 1] << 8) | (bitmap[offset + 0] << 16) | (bitmap[offset + 3] << 24);
pRamBuffer->UnlockRect();

pRamBuffer->Release();

return ret;
}

int surface_getpixel_alpha(int id, int x, int y)
{
get_surfacev(surface,id,-1);
if (x < 0) x = 0;
if (y < 0) y = 0;
if (x > surface.width || y > surface.height) return 0;
draw_batch_flush(batch_flush_deferred);

LPDIRECT3DSURFACE9 pBuffer = surface.surf, pRamBuffer;
enigma::surface_copy_to_ram(&pBuffer, &pRamBuffer);

D3DLOCKED_RECT rect;

pRamBuffer->LockRect(&rect, NULL, D3DLOCK_READONLY);
unsigned char* bitmap = static_cast<unsigned char*>(rect.pBits);
unsigned offset = y * rect.Pitch + x * 4;
int ret = bitmap[offset + 3];
pRamBuffer->UnlockRect();

pRamBuffer->Release();

return ret;
}

}

//////////////////////////////////////SAVE TO FILE AND CTEATE SPRITE FUNCTIONS/////////
//Fuck whoever did this to the spec
#ifndef DX_BGR
#define DX_BGR 0x80E0
#endif

#include "Universal_System/estring.h"
#include "Universal_System/image_formats.h"

namespace enigma_user
{

int surface_save(int id, string filename)
{
draw_batch_flush(batch_flush_deferred);

get_surfacev(surface,id,-1);
string ext = enigma::image_get_format(filename);

LPDIRECT3DSURFACE9 pDestBuffer;
D3DSURFACE_DESC desc;
surface.surf->GetDesc(&desc);

d3ddev->CreateOffscreenPlainSurface( desc.Width, desc.Height, desc.Format, D3DPOOL_SYSTEMMEM, &pDestBuffer, NULL );
d3ddev->GetRenderTargetData(surface.surf, pDestBuffer);

D3DLOCKED_RECT rect;

pDestBuffer->LockRect(&rect, NULL, D3DLOCK_READONLY);
unsigned char* bitmap = static_cast<unsigned char*>(rect.pBits);
pDestBuffer->UnlockRect();

int ret = enigma::image_save(filename, bitmap, desc.Width, desc.Height, desc.Width, desc.Height, false);

pDestBuffer->Release();

return ret;
}

int surface_save_part(int id, string filename, unsigned x, unsigned y, unsigned w, unsigned h)
{
return 0; //TODO: implement
}

int background_create_from_surface(int id, int x, int y, int w, int h, bool removeback, bool smooth, bool preload)
{
return 0; //TODO: implement
}

int sprite_create_from_surface(int id, int x, int y, int w, int h, bool removeback, bool smooth, bool preload, int xorig, int yorig)
{
return 0; //TODO: implement
}

int sprite_create_from_surface(int id, int x, int y, int w, int h, bool removeback, bool smooth, int xorig, int yorig)
{
return sprite_create_from_surface(id, x, y, w, h, removeback, smooth, true, xorig, yorig);
}

void sprite_add_from_surface(int ind, int id, int x, int y, int w, int h, bool removeback, bool smooth)
{

}

void surface_copy_part(int destination, gs_scalar x, gs_scalar y, int source, int xs, int ys, int ws, int hs)
{

}

void surface_copy(int destination, gs_scalar x, gs_scalar y, int source)
{

}

}
Oops, something went wrong.

0 comments on commit 55fde1e

Please sign in to comment.
You can’t perform that action at this time.