gfx_read_image_data()

This commit is contained in:
Charlie Malmqvist 2024-08-23 15:57:35 +02:00
parent 9de955c84e
commit 1b200bd162
6 changed files with 149 additions and 9 deletions

View file

@ -44,5 +44,7 @@ typedef struct Context_Extra {
// #include "oogabooga/examples/growing_array_example.c"
// #include "oogabooga/examples/input_example.c"
// #include "oogabooga/examples/sanity_tests.c"
// This is where you swap in your own project!
// #include "entry_yourepicgamename.c"

View file

@ -6,6 +6,8 @@
- Reworked window initialization
Window now starts of invisible and is made visible on first os_update().
This also gets rid of the weird window resize and reposition at startup.
- Renderer
- Added gfx_read_image_data() to read pixels from a Gfx_Image*
## v0.01.004 - Gamepad input, text wrapping, bug fixes

View file

@ -1,6 +1,11 @@
int entry(int argc, char **argv) {
// This is how we (optionally) configure the window.
// You can set this at any point in the runtime and it will
// be applied in os_update().
// If you don't care, you can ignore all of this as it all
// has reasonable default values.
window.title = STR("Minimal Game Example");
window.scaled_width = 1280; // We need to set the scaled size if we want to handle system scaling (DPI)
window.scaled_height = 720;
@ -8,6 +13,7 @@ int entry(int argc, char **argv) {
window.y = 90;
window.clear_color = hex_to_rgba(0x6495EDff);
window.allow_resize = true;
window.fullscreen = false;
float64 last_time = os_get_elapsed_seconds();
while (!window.should_close) {

View file

@ -0,0 +1,69 @@
int entry(int argc, char **argv) {
u32 w = 128;
u32 h = 128;
u32 tile_w = w/4;
u32 tile_h = w/4;
u8 *pixels = (u8*)alloc(get_heap_allocator(), w * h * 4);
for (u32 y = 0; y < h; y += 1) {
for (u32 x = 0; x < w; x += 1) {
u32 tile_x = x / tile_w;
u32 tile_y = y / tile_h;
bool is_black_tile = (tile_x % 2 == tile_y % 2);
for (u32 c = 0; c < 4; c += 1) {
if (is_black_tile) {
pixels[(y * w + x) * 4 + c] = 127;
} else {
pixels[(y * w + x) * 4 + c] = 255;
}
}
}
}
Gfx_Image *img = make_image(w, h, 4, pixels, get_heap_allocator());
u8 *read_pixels = (u8*)alloc(get_heap_allocator(), w*h*4);
gfx_read_image_data(img, 0, 0, w, h, read_pixels);
gfx_set_image_data(img, 0, 0, w, h, read_pixels);
assert(memcmp(read_pixels, pixels, w*h*4) == 0);
float64 last_time = os_get_elapsed_seconds();
while (!window.should_close) {
reset_temporary_storage();
float64 now = os_get_elapsed_seconds();
if ((int)now != (int)last_time) log("%.2f FPS\n%.2fms", 1.0/(now-last_time), (now-last_time)*1000);
last_time = now;
Matrix4 rect_xform = m4_scalar(1.0);
rect_xform = m4_rotate_z(rect_xform, (f32)now);
rect_xform = m4_translate(rect_xform, v3(-.25f, -.25f, 0));
draw_image_xform(img, rect_xform, v2(.5f, .5f), COLOR_GREEN);
draw_rect(v2(sin(now), -.8), v2(.5, .25), COLOR_RED);
float aspect = (f32)window.width/(f32)window.height;
float mx = (input_frame.mouse_x/(f32)window.width * 2.0 - 1.0)*aspect;
float my = input_frame.mouse_y/(f32)window.height * 2.0 - 1.0;
draw_line(v2(-.75, -.75), v2(mx, my), 0.005, COLOR_WHITE);
if (is_key_just_pressed('F')) {
window.fullscreen = !window.fullscreen;
}
os_update();
gfx_update();
}
return 0;
}

View file

@ -882,6 +882,7 @@ void gfx_init_image(Gfx_Image *image, void *initial_data) {
desc.Height = image->height;
desc.MipLevels = 1;
desc.ArraySize = 1;
// #Hdr
switch (image->channels) {
case 1: desc.Format = DXGI_FORMAT_R8_UNORM; break;
case 2: desc.Format = DXGI_FORMAT_R8G8_UNORM; break;
@ -897,7 +898,7 @@ void gfx_init_image(Gfx_Image *image, void *initial_data) {
D3D11_SUBRESOURCE_DATA data_desc = ZERO(D3D11_SUBRESOURCE_DATA);
data_desc.pSysMem = data;
data_desc.SysMemPitch = image->width * image->channels;
data_desc.SysMemPitch = image->width * image->channels; // #Hdr
ID3D11Texture2D* texture = 0;
HRESULT hr = ID3D11Device_CreateTexture2D(d3d11_device, &desc, &data_desc, &texture);
@ -927,16 +928,72 @@ void gfx_set_image_data(Gfx_Image *image, u32 x, u32 y, u32 w, u32 h, void *data
HRESULT hr = ID3D11Resource_QueryInterface(resource, &IID_ID3D11Texture2D, (void**)&texture);
assert(SUCCEEDED(hr), "Expected gfx resource to be a texture but it wasn't");
D3D11_BOX destBox;
destBox.left = x;
destBox.right = x + w;
destBox.top = y;
destBox.bottom = y + h;
destBox.front = 0;
destBox.back = 1;
D3D11_BOX region;
region.left = x;
region.right = x + w;
region.top = y;
region.bottom = y + h;
region.front = 0;
region.back = 1;
// #Hdr
// #Incomplete bit-width 8 assumed
ID3D11DeviceContext_UpdateSubresource(d3d11_context, (ID3D11Resource*)texture, 0, &destBox, data, w * image->channels, 0);
ID3D11DeviceContext_UpdateSubresource(d3d11_context, (ID3D11Resource*)texture, 0, &region, data, w * image->channels, 0);
ID3D11Resource_Release(resource);
}
void gfx_read_image_data(Gfx_Image *image, u32 x, u32 y, u32 w, u32 h, void *output) {
D3D11_BOX region;
region.left = x;
region.right = x + w;
region.top = y;
region.bottom = y + h;
region.front = 0;
region.back = 1;
ID3D11Resource *resource = 0;
ID3D11View_GetResource(image->gfx_handle, &resource);
ID3D11Texture2D *texture = 0;
HRESULT hr = ID3D11Resource_QueryInterface(resource, &IID_ID3D11Texture2D, (void**)&texture);
d3d11_check_hr(hr);
D3D11_TEXTURE2D_DESC desc;
texture->lpVtbl->GetDesc(texture, &desc);
D3D11_TEXTURE2D_DESC staging_desc = desc;
staging_desc.Usage = D3D11_USAGE_STAGING;
staging_desc.BindFlags = 0;
staging_desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
staging_desc.MiscFlags = 0;
ID3D11Texture2D *staging_texture = 0;
hr = ID3D11Device_CreateTexture2D(d3d11_device, &staging_desc, 0, &staging_texture);
d3d11_check_hr(hr);
ID3D11DeviceContext_CopySubresourceRegion(
d3d11_context,
(ID3D11Resource *)staging_texture,
0, 0, 0, 0,
(ID3D11Resource *)texture, 0,
&region
);
D3D11_MAPPED_SUBRESOURCE mapped_texture;
hr = ID3D11DeviceContext_Map(d3d11_context, (ID3D11Resource *)staging_texture, 0, D3D11_MAP_READ, 0, &mapped_texture);
d3d11_check_hr(hr);
// #Hdr
assert(mapped_texture.RowPitch == image->width * image->channels, "Unexpected row pitch in d3d11 texture");
// #Hdr
memcpy(output, mapped_texture.pData, image->width*image->height*image->channels);
ID3D11DeviceContext_Unmap(d3d11_context, (ID3D11Resource *)staging_texture, 0);
ID3D11Resource_Release(resource);
ID3D11Texture2D_Release(staging_texture);
}
void gfx_deinit_image(Gfx_Image *image) {
ID3D11ShaderResourceView *view = image->gfx_handle;
@ -952,6 +1009,8 @@ void gfx_deinit_image(Gfx_Image *image) {
} else {
panic("Unhandled D3D11 resource deletion");
}
ID3D11Resource_Release(resource);
}
bool

View file

@ -49,6 +49,8 @@ ogb_instance void
gfx_init_image(Gfx_Image *image, void *data);
ogb_instance void
gfx_set_image_data(Gfx_Image *image, u32 x, u32 y, u32 w, u32 h, void *data);
ogb_instance void
gfx_read_image_data(Gfx_Image *image, u32 x, u32 y, u32 w, u32 h, void *output);
ogb_instance void
gfx_deinit_image(Gfx_Image *image);