GPU gif creation
This commit is contained in:
parent
b9316dbbe6
commit
1ac0c7693d
|
@ -1121,7 +1121,7 @@ JSValue duk_cmd(JSContext *js, JSValueConst this, int argc, JSValueConst *argv)
|
|||
break;
|
||||
|
||||
case 131:
|
||||
gif_rec_start();
|
||||
gif_rec_start(480, 320, 4, 8);
|
||||
break;
|
||||
case 132:
|
||||
str = JS_ToCString(js, argv[1]);
|
||||
|
|
|
@ -15,22 +15,65 @@
|
|||
#include "stb_ds.h"
|
||||
#include "stb_image_resize.h";
|
||||
#include "resources.h"
|
||||
#include "yugine.h"
|
||||
|
||||
#define SOKOL_GFX_IMPL
|
||||
#include "sokol/sokol_gfx.h"
|
||||
|
||||
#define SOKOL_GFX_EXT_IMPL
|
||||
#include "sokol/sokol_gfx_ext.h"
|
||||
|
||||
#define MSF_GIF_IMPL
|
||||
#include "msf_gif.h"
|
||||
|
||||
static int gif_w = 480, gif_h = 320, cpf = 1, bitDepth = 16;
|
||||
static struct {
|
||||
sg_pass pass;
|
||||
sg_pass_action pa;
|
||||
sg_pipeline pipe;
|
||||
sg_bindings bind;
|
||||
sg_shader shader;
|
||||
sg_image img;
|
||||
sg_image depth;
|
||||
} sg_gif;
|
||||
|
||||
|
||||
static int gif_w = 359, gif_h = 320, cpf = 4, gif_depth = 4;
|
||||
static int gif_rec = 0;
|
||||
static double gif_timer = 0, gif_spf;
|
||||
static char gif_buf[480*320*4];
|
||||
static char frame_buf[1920*1080*4];
|
||||
MsfGifState gif_state = {};
|
||||
void gif_rec_start()
|
||||
void gif_rec_start(int w, int h, int cpf, int bitdepth)
|
||||
{
|
||||
gif_w = w;
|
||||
gif_h = h;
|
||||
gif_depth = bitdepth;
|
||||
msf_gif_begin(&gif_state, gif_w, gif_h);
|
||||
gif_spf = cpf/100.0;
|
||||
gif_rec = 1;
|
||||
gif_timer = appTime;
|
||||
|
||||
sg_destroy_image(sg_gif.img);
|
||||
sg_destroy_image(sg_gif.depth);
|
||||
sg_destroy_pass(sg_gif.pass);
|
||||
|
||||
sg_gif.img = sg_make_image(&(sg_image_desc){
|
||||
.render_target = true,
|
||||
.width = gif_w,
|
||||
.height = gif_h,
|
||||
});
|
||||
|
||||
sg_gif.depth = sg_make_image(&(sg_image_desc){
|
||||
.render_target = true,
|
||||
.width = gif_w,
|
||||
.height = gif_h,
|
||||
.pixel_format = SG_PIXELFORMAT_DEPTH_STENCIL
|
||||
});
|
||||
|
||||
sg_gif.pass = sg_make_pass(&(sg_pass_desc){
|
||||
.color_attachments[0].image = sg_gif.img,
|
||||
.depth_stencil_attachment.image = sg_gif.depth
|
||||
});
|
||||
}
|
||||
|
||||
void gif_rec_end(char *path)
|
||||
|
@ -61,7 +104,6 @@ static void *read_texture_data(sg_image id, void *pixels)
|
|||
YughWarn("NO GL");
|
||||
return NULL;
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
#include "sokol/sokol_app.h"
|
||||
|
@ -143,6 +185,7 @@ static struct {
|
|||
sg_image depth_img;
|
||||
} crt_post;
|
||||
|
||||
|
||||
void trace_make_shader(sg_shader_desc *d, sg_shader result, void *data)
|
||||
{
|
||||
if (sg_query_shader_state(result) == SG_RESOURCESTATE_FAILED)
|
||||
|
@ -201,6 +244,24 @@ void render_init() {
|
|||
}
|
||||
});
|
||||
|
||||
sg_gif.shader = sg_compile_shader("shaders/postvert.glsl", "shaders/box.glsl", &(sg_shader_desc){
|
||||
.fs.images[0] = {
|
||||
.name = "diffuse_texture",
|
||||
.image_type = SG_IMAGETYPE_2D,
|
||||
.sampler_type = SG_SAMPLERTYPE_FLOAT
|
||||
}
|
||||
});
|
||||
|
||||
sg_gif.pipe = sg_make_pipeline(&(sg_pipeline_desc){
|
||||
.shader = sg_gif.shader,
|
||||
.layout = {
|
||||
.attrs = {
|
||||
[0].format = SG_VERTEXFORMAT_FLOAT2,
|
||||
[1].format = SG_VERTEXFORMAT_FLOAT2
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
crt_post.pipe = sg_make_pipeline(&(sg_pipeline_desc){
|
||||
.shader = crt_post.shader,
|
||||
.layout = {
|
||||
|
@ -229,6 +290,11 @@ void render_init() {
|
|||
.depth_stencil_attachment.image = crt_post.depth_img,
|
||||
});
|
||||
|
||||
sg_gif.pass = sg_make_pass(&(sg_pass_desc){
|
||||
.color_attachments[0].image = sg_gif.img,
|
||||
.depth_stencil_attachment.image = sg_gif.depth
|
||||
});
|
||||
|
||||
float crt_quad[] = {
|
||||
-1, 1, 0, 1,
|
||||
-1, -1, 0, 0,
|
||||
|
@ -244,7 +310,6 @@ void render_init() {
|
|||
});
|
||||
|
||||
crt_post.bind.fs_images[0] = crt_post.img;
|
||||
|
||||
/*
|
||||
sg_image_desc shadow_desc = {
|
||||
.render_target = true,
|
||||
|
@ -341,42 +406,8 @@ HMM_Mat4 hudproj = {0.f};
|
|||
|
||||
HMM_Vec3 dirl_pos = {4, 100, 20};
|
||||
|
||||
void openglRender(struct window *window) {
|
||||
/*
|
||||
HMM_Mat4 model = HMM_M4D(1.f);
|
||||
float scale = 0.08;
|
||||
model = HMM_MulM4(model, HMM_Scale((HMM_Vec3){scale,scale,scale}));
|
||||
|
||||
|
||||
// Shadow pass
|
||||
sg_begin_pass(sg_shadow.pass, &sg_shadow.pass_action);
|
||||
sg_apply_pipeline(sg_shadow.pipe);
|
||||
|
||||
HMM_Mat4 light_proj = HMM_Orthographic_RH_ZO(-100.f, 100.f, -100.f, 100.f, 1.f, 100.f);
|
||||
HMM_Mat4 light_view = HMM_LookAt_RH(dirl_pos, (HMM_Vec3){0,0,0}, (HMM_Vec3){0,1,0});
|
||||
|
||||
HMM_Mat4 lsm = HMM_MulM4(light_proj, light_view);
|
||||
|
||||
HMM_Mat4 subo[2];
|
||||
subo[0] = lsm;
|
||||
subo[1] = model;
|
||||
|
||||
sg_apply_uniforms(SG_SHADERSTAGE_VS, 0, SG_RANGE_REF(subo));
|
||||
|
||||
for (int i = 0; i < arrlen(duck->meshes); i++) {
|
||||
sg_bindings sbind = {0};
|
||||
sbind.vertex_buffers[0] = duck->meshes[i].bind.vertex_buffers[0];
|
||||
sbind.index_buffer = duck->meshes[i].bind.index_buffer;
|
||||
sg_apply_bindings(&sbind);
|
||||
sg_draw(0,duck->meshes[i].face_count,1);
|
||||
}
|
||||
sg_end_pass();
|
||||
|
||||
draw_model(duck,model, lsm);
|
||||
*/
|
||||
|
||||
sg_begin_pass(crt_post.pass, &pass_action);
|
||||
|
||||
void full_2d_pass(struct window *window)
|
||||
{
|
||||
//////////// 2D projection
|
||||
cpVect pos = cam_pos();
|
||||
|
||||
|
@ -410,21 +441,55 @@ void openglRender(struct window *window) {
|
|||
|
||||
call_nk_gui();
|
||||
nuke_end();
|
||||
}
|
||||
|
||||
void full_3d_pass(struct window *window)
|
||||
{
|
||||
HMM_Mat4 model = HMM_M4D(1.f);
|
||||
float scale = 0.08;
|
||||
model = HMM_MulM4(model, HMM_Scale((HMM_Vec3){scale,scale,scale}));
|
||||
|
||||
// Shadow pass
|
||||
sg_begin_pass(sg_shadow.pass, &sg_shadow.pass_action);
|
||||
sg_apply_pipeline(sg_shadow.pipe);
|
||||
|
||||
HMM_Mat4 light_proj = HMM_Orthographic_RH_ZO(-100.f, 100.f, -100.f, 100.f, 1.f, 100.f);
|
||||
HMM_Mat4 light_view = HMM_LookAt_RH(dirl_pos, (HMM_Vec3){0,0,0}, (HMM_Vec3){0,1,0});
|
||||
|
||||
HMM_Mat4 lsm = HMM_MulM4(light_proj, light_view);
|
||||
|
||||
HMM_Mat4 subo[2];
|
||||
subo[0] = lsm;
|
||||
subo[1] = model;
|
||||
|
||||
sg_apply_uniforms(SG_SHADERSTAGE_VS, 0, SG_RANGE_REF(subo));
|
||||
}
|
||||
|
||||
void openglRender(struct window *window) {
|
||||
sg_begin_pass(crt_post.pass, &pass_action);
|
||||
full_2d_pass(window);
|
||||
sg_end_pass();
|
||||
|
||||
|
||||
if (gif_rec && (appTime - gif_timer) > gif_spf) {
|
||||
sg_begin_pass(sg_gif.pass, &pass_action);
|
||||
sg_apply_pipeline(sg_gif.pipe);
|
||||
sg_apply_bindings(&crt_post.bind);
|
||||
sg_draw(0,6,1);
|
||||
sg_end_pass();
|
||||
|
||||
gif_timer = appTime;
|
||||
//read_texture_data(sg_gif.img, gif_buf);
|
||||
sg_query_image_pixels(sg_gif.img, gif_buf, gif_w*gif_h*4);
|
||||
msf_gif_frame(&gif_state, gif_buf, cpf, gif_depth, gif_w * -4);
|
||||
}
|
||||
|
||||
sg_begin_default_pass(&pass_action, window->width, window->height);
|
||||
sg_apply_pipeline(crt_post.pipe);
|
||||
sg_apply_bindings(&crt_post.bind);
|
||||
sg_draw(0,6,1);
|
||||
|
||||
if (gif_rec) {
|
||||
read_texture_data(crt_post.img, frame_buf);
|
||||
// stbir_resize_uint8(frame_buf, mainwin.width, mainwin.height, 0, gif_buf, gif_w, gif_h, 0, 4);
|
||||
msf_gif_frame(&gif_state, frame_buf, cpf, 16, gif_w * -4);
|
||||
}
|
||||
|
||||
sg_end_pass();
|
||||
sg_end_pass();
|
||||
|
||||
sg_commit();
|
||||
|
||||
|
|
|
@ -73,7 +73,7 @@ void add_zoom(float val);
|
|||
|
||||
sg_shader sg_compile_shader(const char *v, const char *f, sg_shader_desc *d);
|
||||
|
||||
void gif_rec_start();
|
||||
void gif_rec_start(int w, int h, int cpf, int bitdepth);
|
||||
void gif_rec_end(char *path);
|
||||
|
||||
struct uv_n {
|
||||
|
|
403
source/engine/thirdparty/sokol/sokol_gfx_ext.h
vendored
Normal file
403
source/engine/thirdparty/sokol/sokol_gfx_ext.h
vendored
Normal file
|
@ -0,0 +1,403 @@
|
|||
/*
|
||||
sokol_gfx_ext.h - extensions for sokol_gfx
|
||||
https://github.com/edubart/sokol_gp
|
||||
*/
|
||||
|
||||
#if defined(SOKOL_IMPL) && !defined(SOKOL_GFX_EXT_IMPL)
|
||||
#define SOKOL_GFX_EXT_IMPL
|
||||
#endif
|
||||
|
||||
#ifndef SOKOL_GFX_EXT_INCLUDED
|
||||
#define SOKOL_GFX_EXT_INCLUDED
|
||||
|
||||
#ifndef SOKOL_GFX_INCLUDED
|
||||
#error "Please include sokol_gfx.h before sokol_gfx_ext.h"
|
||||
#endif
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
SOKOL_GFX_API_DECL void sg_query_image_pixels(sg_image img_id, void* pixels, int size);
|
||||
SOKOL_GFX_API_DECL void sg_query_pixels(int x, int y, int w, int h, bool origin_top_left, void *pixels, int size);
|
||||
SOKOL_GFX_API_DECL void sg_update_texture_filter(sg_image img_id, sg_filter min_filter, sg_filter mag_filter);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
#endif // SOKOL_GFX_EXT_INCLUDED
|
||||
|
||||
#ifdef SOKOL_GFX_EXT_IMPL
|
||||
#ifndef SOKOL_GFX_EXT_IMPL_INCLUDED
|
||||
#define SOKOL_GFX_EXT_IMPL_INCLUDED
|
||||
|
||||
#ifndef SOKOL_GFX_IMPL_INCLUDED
|
||||
#error "Please include sokol_gfx.h implementation before sokol_gp.h implementation"
|
||||
#endif
|
||||
|
||||
#if defined(_SOKOL_ANY_GL)
|
||||
|
||||
static void _sg_gl_query_image_pixels(_sg_image_t* img, void* pixels) {
|
||||
SOKOL_ASSERT(img->gl.target == GL_TEXTURE_2D);
|
||||
SOKOL_ASSERT(0 != img->gl.tex[img->cmn.active_slot]);
|
||||
#if defined(SOKOL_GLCORE33)
|
||||
_sg_gl_cache_store_texture_binding(0);
|
||||
_sg_gl_cache_bind_texture(0, img->gl.target, img->gl.tex[img->cmn.active_slot]);
|
||||
glGetTexImage(img->gl.target, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
|
||||
_SG_GL_CHECK_ERROR();
|
||||
_sg_gl_cache_restore_texture_binding(0);
|
||||
#else
|
||||
static GLuint newFbo = 0;
|
||||
GLuint oldFbo = 0;
|
||||
if(newFbo == 0) {
|
||||
glGenFramebuffers(1, &newFbo);
|
||||
}
|
||||
glGetIntegerv(GL_FRAMEBUFFER_BINDING, (GLint*)&oldFbo);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, newFbo);
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, img->gl.tex[img->cmn.active_slot], 0);
|
||||
glReadPixels(0, 0, img->cmn.width, img->cmn.height, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, oldFbo);
|
||||
//glDeleteFramebuffers(1, &newFbo);
|
||||
_SG_GL_CHECK_ERROR();
|
||||
#endif
|
||||
}
|
||||
|
||||
static void _sg_gl_query_pixels(int x, int y, int w, int h, bool origin_top_left, void *pixels) {
|
||||
SOKOL_ASSERT(pixels);
|
||||
GLuint gl_fb;
|
||||
GLint dims[4];
|
||||
glGetIntegerv(GL_FRAMEBUFFER_BINDING, (GLint*)&gl_fb);
|
||||
_SG_GL_CHECK_ERROR();
|
||||
glGetIntegerv(GL_VIEWPORT, dims);
|
||||
int cur_height = dims[3];
|
||||
y = origin_top_left ? (cur_height - (y+h)) : y;
|
||||
_SG_GL_CHECK_ERROR();
|
||||
#if defined(SOKOL_GLES2) // use NV extension instead
|
||||
glReadBufferNV(gl_fb == 0 ? GL_BACK : GL_COLOR_ATTACHMENT0);
|
||||
#else
|
||||
glReadBuffer(gl_fb == 0 ? GL_BACK : GL_COLOR_ATTACHMENT0);
|
||||
#endif
|
||||
_SG_GL_CHECK_ERROR();
|
||||
glReadPixels(x, y, w, h, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
|
||||
_SG_GL_CHECK_ERROR();
|
||||
}
|
||||
|
||||
static void _sg_gl_update_texture_filter(_sg_image_t* img, sg_filter min_filter, sg_filter mag_filter) {
|
||||
_sg_gl_cache_store_texture_binding(0);
|
||||
_sg_gl_cache_bind_texture(0, img->gl.target, img->gl.tex[img->cmn.active_slot]);
|
||||
img->cmn.min_filter = min_filter;
|
||||
img->cmn.mag_filter = mag_filter;
|
||||
GLenum gl_min_filter = _sg_gl_filter(img->cmn.min_filter);
|
||||
GLenum gl_mag_filter = _sg_gl_filter(img->cmn.mag_filter);
|
||||
glTexParameteri(img->gl.target, GL_TEXTURE_MIN_FILTER, (GLint)gl_min_filter);
|
||||
glTexParameteri(img->gl.target, GL_TEXTURE_MAG_FILTER, (GLint)gl_mag_filter);
|
||||
_sg_gl_cache_restore_texture_binding(0);
|
||||
}
|
||||
|
||||
#elif defined(SOKOL_D3D11)
|
||||
|
||||
static inline void _sgext_d3d11_Texture2D_GetDesc(ID3D11Texture2D* self, D3D11_TEXTURE2D_DESC* pDesc) {
|
||||
#if defined(__cplusplus)
|
||||
self->GetDesc(pDesc);
|
||||
#else
|
||||
self->lpVtbl->GetDesc(self, pDesc);
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline void _sgext_d3d11_SamplerState_GetDesc(ID3D11SamplerState* self, D3D11_SAMPLER_DESC* pDesc) {
|
||||
#if defined(__cplusplus)
|
||||
self->GetDesc(pDesc);
|
||||
#else
|
||||
self->lpVtbl->GetDesc(self, pDesc);
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline void _sgext_d3d11_CopySubresourceRegion(ID3D11DeviceContext* self, ID3D11Resource *pDstResource, UINT DstSubresource, UINT DstX, UINT DstY, UINT DstZ, ID3D11Resource *pSrcResource, UINT SrcSubresource, const D3D11_BOX *pSrcBox) {
|
||||
#if defined(__cplusplus)
|
||||
self->CopySubresourceRegion(pDstResource, DstSubresource, DstX, DstY, DstZ, pSrcResource, SrcSubresource, pSrcBox);
|
||||
#else
|
||||
self->lpVtbl->CopySubresourceRegion(self, pDstResource, DstSubresource, DstX, DstY, DstZ, pSrcResource, SrcSubresource, pSrcBox);
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline void _sgext_d3d11_OMGetRenderTargets(ID3D11DeviceContext* self, UINT NumViews, ID3D11RenderTargetView **ppRenderTargetViews, ID3D11DepthStencilView **ppDepthStencilView) {
|
||||
#if defined(__cplusplus)
|
||||
self->OMGetRenderTargets(NumViews, ppRenderTargetViews, ppDepthStencilView);
|
||||
#else
|
||||
self->lpVtbl->OMGetRenderTargets(self, NumViews, ppRenderTargetViews, ppDepthStencilView);
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline void _sgext_d3d11_RenderTargetView_GetResource(ID3D11RenderTargetView* self, ID3D11Resource** ppResource) {
|
||||
#if defined(__cplusplus)
|
||||
self->GetResource(ppResource);
|
||||
#else
|
||||
self->lpVtbl->GetResource(self, ppResource);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void _sg_d3d11_query_image_pixels(_sg_image_t* img, void* pixels) {
|
||||
SOKOL_ASSERT(_sg.d3d11.ctx);
|
||||
SOKOL_ASSERT(img->d3d11.tex2d);
|
||||
HRESULT hr;
|
||||
_SOKOL_UNUSED(hr);
|
||||
|
||||
// create staging texture
|
||||
ID3D11Texture2D* staging_tex = NULL;
|
||||
D3D11_TEXTURE2D_DESC staging_desc = {
|
||||
.Width = (UINT)img->cmn.width,
|
||||
.Height = (UINT)img->cmn.height,
|
||||
.MipLevels = 1,
|
||||
.ArraySize = 1,
|
||||
.Format = img->d3d11.format,
|
||||
.SampleDesc = {
|
||||
.Count = 1,
|
||||
.Quality = 0,
|
||||
},
|
||||
.Usage = D3D11_USAGE_STAGING,
|
||||
.BindFlags = 0,
|
||||
.CPUAccessFlags = D3D11_CPU_ACCESS_READ,
|
||||
.MiscFlags = 0
|
||||
};
|
||||
hr = _sg_d3d11_CreateTexture2D(_sg.d3d11.dev, &staging_desc, NULL, &staging_tex);
|
||||
SOKOL_ASSERT(SUCCEEDED(hr));
|
||||
|
||||
// copy pixels to staging texture
|
||||
_sgext_d3d11_CopySubresourceRegion(_sg.d3d11.ctx,
|
||||
(ID3D11Resource*)staging_tex,
|
||||
0, 0, 0, 0,
|
||||
(ID3D11Resource*)img->d3d11.tex2d,
|
||||
0, NULL);
|
||||
|
||||
// map the staging texture's data to CPU-accessible memory
|
||||
D3D11_MAPPED_SUBRESOURCE msr = {.pData = NULL};
|
||||
hr = _sg_d3d11_Map(_sg.d3d11.ctx, (ID3D11Resource*)staging_tex, 0, D3D11_MAP_READ, 0, &msr);
|
||||
SOKOL_ASSERT(SUCCEEDED(hr));
|
||||
|
||||
// copy the data into the desired buffer, converting pixels to the desired format at the same time
|
||||
/* int res = SDL_ConvertPixels(
|
||||
img->cmn.width, img->cmn.height,
|
||||
_sg_d3d11_dxgi_format_to_sdl_pixel_format(staging_desc.Format),
|
||||
msr.pData, msr.RowPitch,
|
||||
SDL_PIXELFORMAT_RGBA32,
|
||||
pixels, img->cmn.width * 4);
|
||||
SOKOL_ASSERT(res == 0);
|
||||
_SOKOL_UNUSED(res);
|
||||
*/
|
||||
// unmap the texture
|
||||
_sg_d3d11_Unmap(_sg.d3d11.ctx, (ID3D11Resource*)staging_tex, 0);
|
||||
|
||||
if(staging_tex) _sg_d3d11_Release(staging_tex);
|
||||
}
|
||||
|
||||
static void _sg_d3d11_query_pixels(int x, int y, int w, int h, bool origin_top_left, void *pixels) {
|
||||
// get current render target
|
||||
ID3D11RenderTargetView* render_target_view = NULL;
|
||||
_sgext_d3d11_OMGetRenderTargets(_sg.d3d11.ctx, 1, &render_target_view, NULL);
|
||||
|
||||
// fallback to window render target
|
||||
if(!render_target_view)
|
||||
render_target_view = (ID3D11RenderTargetView*)_sg.d3d11.rtv_cb();
|
||||
SOKOL_ASSERT(render_target_view);
|
||||
|
||||
// get the back buffer texture
|
||||
ID3D11Texture2D *back_buffer = NULL;
|
||||
_sgext_d3d11_RenderTargetView_GetResource(render_target_view, (ID3D11Resource**)&back_buffer);
|
||||
SOKOL_ASSERT(back_buffer);
|
||||
|
||||
// create a staging texture to copy the screen's data to
|
||||
D3D11_TEXTURE2D_DESC staging_desc;
|
||||
_sgext_d3d11_Texture2D_GetDesc(back_buffer, &staging_desc);
|
||||
staging_desc.Width = w;
|
||||
staging_desc.Height = h;
|
||||
staging_desc.BindFlags = 0;
|
||||
staging_desc.MiscFlags = 0;
|
||||
staging_desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
|
||||
staging_desc.Usage = D3D11_USAGE_STAGING;
|
||||
ID3D11Texture2D *staging_tex = NULL;
|
||||
HRESULT hr = _sg_d3d11_CreateTexture2D(_sg.d3d11.dev, &staging_desc, NULL, &staging_tex);
|
||||
SOKOL_ASSERT(SUCCEEDED(hr));
|
||||
_SOKOL_UNUSED(hr);
|
||||
|
||||
// copy the desired portion of the back buffer to the staging texture
|
||||
y = (origin_top_left ? y : (_sg.d3d11.cur_height - (y + h)));
|
||||
D3D11_BOX src_box = {
|
||||
.left = (UINT)x,
|
||||
.top = (UINT)y,
|
||||
.front = 0,
|
||||
.right = (UINT)(x + w),
|
||||
.bottom = (UINT)(y + w),
|
||||
.back = 1,
|
||||
};
|
||||
_sgext_d3d11_CopySubresourceRegion(_sg.d3d11.ctx,
|
||||
(ID3D11Resource*)staging_tex,
|
||||
0, 0, 0, 0,
|
||||
(ID3D11Resource*)back_buffer,
|
||||
0, &src_box);
|
||||
|
||||
// map the staging texture's data to CPU-accessible memory
|
||||
D3D11_MAPPED_SUBRESOURCE msr = {.pData = NULL};
|
||||
hr = _sg_d3d11_Map(_sg.d3d11.ctx, (ID3D11Resource*)staging_tex, 0, D3D11_MAP_READ, 0, &msr);
|
||||
SOKOL_ASSERT(SUCCEEDED(hr));
|
||||
|
||||
// copy the data into the desired buffer, converting pixels to the desired format at the same time
|
||||
/* int res = SDL_ConvertPixels(
|
||||
w, h,
|
||||
_sg_d3d11_dxgi_format_to_sdl_pixel_format(staging_desc.Format),
|
||||
msr.pData, msr.RowPitch,
|
||||
SDL_PIXELFORMAT_RGBA32,
|
||||
pixels, w * 4);
|
||||
SOKOL_ASSERT(res == 0);
|
||||
_SOKOL_UNUSED(res);
|
||||
*/
|
||||
// unmap the texture
|
||||
_sg_d3d11_Unmap(_sg.d3d11.ctx, (ID3D11Resource*)staging_tex, 0);
|
||||
|
||||
if(back_buffer) _sg_d3d11_Release(back_buffer);
|
||||
if(staging_tex) _sg_d3d11_Release(staging_tex);
|
||||
}
|
||||
|
||||
static void _sg_d3d11_update_texture_filter(_sg_image_t* img, sg_filter min_filter, sg_filter mag_filter) {
|
||||
SOKOL_ASSERT(img->d3d11.tex2d || img->d3d11.tex3d);
|
||||
HRESULT hr;
|
||||
_SOKOL_UNUSED(hr);
|
||||
D3D11_SAMPLER_DESC d3d11_smp_desc;
|
||||
memset(&d3d11_smp_desc, 0, sizeof(d3d11_smp_desc));
|
||||
_sgext_d3d11_SamplerState_GetDesc(img->d3d11.smp, &d3d11_smp_desc);
|
||||
_sg_d3d11_Release(img->d3d11.smp);
|
||||
img->cmn.min_filter = min_filter;
|
||||
img->cmn.mag_filter = mag_filter;
|
||||
d3d11_smp_desc.Filter = _sg_d3d11_filter(img->cmn.min_filter, img->cmn.mag_filter, img->cmn.max_anisotropy);
|
||||
hr = _sg_d3d11_CreateSamplerState(_sg.d3d11.dev, &d3d11_smp_desc, &img->d3d11.smp);
|
||||
SOKOL_ASSERT(SUCCEEDED(hr) && img->d3d11.smp);
|
||||
}
|
||||
|
||||
#elif defined(SOKOL_METAL)
|
||||
|
||||
#import <Metal/Metal.h>
|
||||
#import <QuartzCore/CAMetalLayer.h>
|
||||
|
||||
|
||||
static void _sg_metal_commit_command_buffer() {
|
||||
SOKOL_ASSERT(!_sg.mtl.in_pass);
|
||||
if(_sg.mtl.cmd_buffer) {
|
||||
#if defined(_SG_TARGET_MACOS)
|
||||
[_sg.mtl.uniform_buffers[_sg.mtl.cur_frame_rotate_index] didModifyRange:NSMakeRange(0, _sg.mtl.cur_ub_offset)];
|
||||
#endif
|
||||
[_sg.mtl.cmd_buffer commit];
|
||||
[_sg.mtl.cmd_buffer waitUntilCompleted];
|
||||
_sg.mtl.cmd_buffer = [_sg.mtl.cmd_queue commandBufferWithUnretainedReferences];
|
||||
}
|
||||
}
|
||||
|
||||
static void _sg_metal_encode_texture_pixels(int x, int y, int w, int h, bool origin_top_left, id<MTLTexture> mtl_src_texture, void* pixels) {
|
||||
SOKOL_ASSERT(!_sg.mtl.in_pass);
|
||||
_sg_metal_commit_command_buffer();
|
||||
MTLTextureDescriptor* mtl_dst_texture_desc = [MTLTextureDescriptor texture2DDescriptorWithPixelFormat:mtl_src_texture.pixelFormat width:w height:h mipmapped:NO];
|
||||
mtl_dst_texture_desc.storageMode = MTLStorageModeManaged;
|
||||
mtl_dst_texture_desc.resourceOptions = MTLResourceStorageModeManaged;
|
||||
mtl_dst_texture_desc.usage = MTLTextureUsageShaderRead + MTLTextureUsageShaderWrite;
|
||||
id<MTLTexture> mtl_dst_texture = [mtl_src_texture.device newTextureWithDescriptor:mtl_dst_texture_desc];
|
||||
id<MTLCommandBuffer> cmd_buffer = [_sg.mtl.cmd_queue commandBuffer];
|
||||
id<MTLBlitCommandEncoder> blit_encoder = [cmd_buffer blitCommandEncoder];
|
||||
[blit_encoder copyFromTexture:mtl_src_texture
|
||||
sourceSlice:0
|
||||
sourceLevel:0
|
||||
sourceOrigin:MTLOriginMake(x,(origin_top_left ? y : (mtl_src_texture.height - (y + h))),0)
|
||||
sourceSize:MTLSizeMake(w,h,1)
|
||||
toTexture:mtl_dst_texture
|
||||
destinationSlice:0
|
||||
destinationLevel:0
|
||||
destinationOrigin:MTLOriginMake(0,0,0)
|
||||
];
|
||||
[blit_encoder synchronizeTexture:mtl_dst_texture slice:0 level:0];
|
||||
[blit_encoder endEncoding];
|
||||
[cmd_buffer commit];
|
||||
[cmd_buffer waitUntilCompleted];
|
||||
|
||||
MTLRegion mtl_region = MTLRegionMake2D(0, 0, w, h);
|
||||
void* temp_pixels = (void*)SOKOL_MALLOC(w * 4 * h);
|
||||
SOKOL_ASSERT(temp_pixels);
|
||||
[mtl_dst_texture getBytes:temp_pixels bytesPerRow:w * 4 fromRegion:mtl_region mipmapLevel:0];
|
||||
// int res = SDL_ConvertPixels(w, h, _sg_metal_texture_format_to_sdl_pixel_format(mtl_dst_texture_desc.pixelFormat), temp_pixels, w * 4, SDL_PIXELFORMAT_RGBA32, pixels, w * 4);
|
||||
SOKOL_FREE(temp_pixels);
|
||||
SOKOL_ASSERT(res == 0);
|
||||
_SOKOL_UNUSED(res);
|
||||
}
|
||||
|
||||
static void _sg_metal_query_image_pixels(_sg_image_t* img, void* pixels) {
|
||||
id<MTLTexture> mtl_src_texture = _sg.mtl.idpool.pool[img->mtl.tex[0]];
|
||||
_sg_metal_encode_texture_pixels(0, 0, mtl_src_texture.width, mtl_src_texture.height, true, mtl_src_texture, pixels);
|
||||
}
|
||||
|
||||
static void _sg_metal_query_pixels(int x, int y, int w, int h, bool origin_top_left, void *pixels) {
|
||||
id<CAMetalDrawable> mtl_drawable = (__bridge id<CAMetalDrawable>)_sg.mtl.drawable_cb();
|
||||
_sg_metal_encode_texture_pixels(x, y, w, h, origin_top_left, mtl_drawable.texture, pixels);
|
||||
}
|
||||
|
||||
static void _sg_metal_update_texture_filter(_sg_image_t* img, sg_filter min_filter, sg_filter mag_filter) {
|
||||
sg_image_desc image_desc = {
|
||||
.min_filter = min_filter,
|
||||
.mag_filter = mag_filter,
|
||||
.wrap_u = img->cmn.wrap_u,
|
||||
.wrap_v = img->cmn.wrap_v,
|
||||
.wrap_w = img->cmn.wrap_w,
|
||||
.max_anisotropy = img->cmn.max_anisotropy,
|
||||
.border_color = img->cmn.border_color,
|
||||
};
|
||||
sg_image_desc desc_def = _sg_image_desc_defaults(&image_desc);
|
||||
img->mtl.sampler_state = _sg_mtl_create_sampler(_sg.mtl.device, &desc_def);
|
||||
img->cmn.min_filter = min_filter;
|
||||
img->cmn.mag_filter = mag_filter;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
void sg_query_image_pixels(sg_image img_id, void* pixels, int size) {
|
||||
SOKOL_ASSERT(pixels);
|
||||
SOKOL_ASSERT(img_id.id != SG_INVALID_ID);
|
||||
_sg_image_t* img = _sg_lookup_image(&_sg.pools, img_id.id);
|
||||
SOKOL_ASSERT(img);
|
||||
SOKOL_ASSERT(size >= (img->cmn.width * img->cmn.height * 4));
|
||||
_SOKOL_UNUSED(size);
|
||||
#if defined(_SOKOL_ANY_GL)
|
||||
_sg_gl_query_image_pixels(img, pixels);
|
||||
#elif defined(SOKOL_D3D11)
|
||||
_sg_d3d11_query_image_pixels(img, pixels);
|
||||
#elif defined(SOKOL_METAL)
|
||||
_sg_metal_query_image_pixels(img, pixels);
|
||||
#endif
|
||||
}
|
||||
|
||||
void sg_query_pixels(int x, int y, int w, int h, bool origin_top_left, void *pixels, int size) {
|
||||
SOKOL_ASSERT(pixels);
|
||||
SOKOL_ASSERT(size >= w*h);
|
||||
_SOKOL_UNUSED(size);
|
||||
#if defined(_SOKOL_ANY_GL)
|
||||
_sg_gl_query_pixels(x, y, w, h, origin_top_left, pixels);
|
||||
#elif defined(SOKOL_D3D11)
|
||||
_sg_d3d11_query_pixels(x, y, w, h, origin_top_left, pixels);
|
||||
#elif defined(SOKOL_METAL)
|
||||
_sg_metal_query_pixels(x, y, w, h, origin_top_left, pixels);
|
||||
#endif
|
||||
}
|
||||
|
||||
void sg_update_texture_filter(sg_image img_id, sg_filter min_filter, sg_filter mag_filter) {
|
||||
SOKOL_ASSERT(img_id.id != SG_INVALID_ID);
|
||||
_sg_image_t* img = _sg_lookup_image(&_sg.pools, img_id.id);
|
||||
SOKOL_ASSERT(img);
|
||||
#if defined(_SOKOL_ANY_GL)
|
||||
_sg_gl_update_texture_filter(img, min_filter, mag_filter);
|
||||
#elif defined(SOKOL_D3D11)
|
||||
_sg_d3d11_update_texture_filter(img, min_filter, mag_filter);
|
||||
#elif defined(SOKOL_METAL)
|
||||
_sg_metal_update_texture_filter(img, min_filter, mag_filter);
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif // SOKOL_GFX_EXT_IMPL_INCLUDED
|
||||
#endif // SOKOL_GFX_EXT_IMPL
|
|
@ -56,6 +56,7 @@
|
|||
#include "stb_image.h"
|
||||
|
||||
#define STB_IMAGE_WRITE_IMPLEMENTATION
|
||||
#define STBIR_DEFAULT_FILTER_DOWNSAMPLE STBIR_FILTER_BOX
|
||||
#include "stb_image_write.h"
|
||||
|
||||
#define PL_MPEG_IMPLEMENTATION
|
||||
|
|
|
@ -100,6 +100,9 @@ var Debug = {
|
|||
GUI.text(x.fullpath(), world2screen(x.pos).add([0,32]), 1, [84,110,255]);
|
||||
});
|
||||
|
||||
if (Debug.Options.gif.rec)
|
||||
gui_text("REC", [0,40], 1);
|
||||
|
||||
gui_text(Game.playing() ? "PLAYING"
|
||||
: Game.stepping() ?
|
||||
"STEP" :
|
||||
|
@ -241,8 +244,25 @@ DebugControls.inputs.f4 = function() {
|
|||
Debug.draw_gizmos = !Debug.draw_gizmos;
|
||||
};
|
||||
DebugControls.inputs.f4.doc = "Toggle drawing gizmos and names of objects.";
|
||||
DebugControls.inputs.f8 = function() { cmd(131); };
|
||||
DebugControls.inputs.f9 = function() { cmd(132, "out.gif"); };
|
||||
|
||||
Debug.Options.gif = {
|
||||
w: 480,
|
||||
h: 320,
|
||||
cpf: 4,
|
||||
depth: 8,
|
||||
file: "out.gif",
|
||||
rec: false,
|
||||
};
|
||||
DebugControls.inputs.f8 = function() {
|
||||
var gif = Debug.Options.gif;
|
||||
cmd(131, gif.w, gif.h, gif.cpf, gif.depth);
|
||||
gif.rec = true;
|
||||
};
|
||||
DebugControls.inputs.f9 = function() {
|
||||
cmd(132, Debug.Options.gif.file);
|
||||
Debug.Options.gif.rec = false;
|
||||
};
|
||||
|
||||
DebugControls.inputs.f10 = function() { Time.timescale = 0.1; };
|
||||
DebugControls.inputs.f10.doc = "Toggle timescale to 1/10.";
|
||||
DebugControls.inputs.f10.released = function () { Time.timescale = 1.0; };
|
||||
|
|
Loading…
Reference in a new issue