Implement updating of current frame on GPU
This commit is contained in:
parent
4098f2d383
commit
b21850dd15
@ -780,8 +780,32 @@ grman_update_layers(GraphicsManager *self, unsigned int scrolled_by, float scree
|
|||||||
#define _gap z_index
|
#define _gap z_index
|
||||||
#define _animation_enabled data_width
|
#define _animation_enabled data_width
|
||||||
|
|
||||||
|
static inline Frame*
|
||||||
|
current_frame(Image *img) {
|
||||||
|
if (img->current_frame_index > img->extra_framecnt) return NULL;
|
||||||
|
return img->current_frame_index ? img->extra_frames + img->current_frame_index - 1 : &img->root_frame;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
update_current_frame(GraphicsManager *self, Image *img, void *data) {
|
||||||
|
bool needs_load = data == NULL;
|
||||||
|
Frame *f = current_frame(img);
|
||||||
|
if (f == NULL) return;
|
||||||
|
if (needs_load) {
|
||||||
|
size_t data_sz;
|
||||||
|
if (!read_from_cache(self, (const ImageAndFrame){.image_id=img->internal_id, .frame_id=f->id}, &data, &data_sz)) {
|
||||||
|
if (PyErr_Occurred()) PyErr_Print();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (send_to_gpu) {
|
||||||
|
send_image_to_gpu(&img->texture_id, data, img->width, img->height, img->is_opaque, img->is_4byte_aligned, false, REPEAT_CLAMP);
|
||||||
|
}
|
||||||
|
if (needs_load) free(data);
|
||||||
|
}
|
||||||
|
|
||||||
static Image*
|
static Image*
|
||||||
handle_animation_frame_load_command(GraphicsManager *self, GraphicsCommand *g, Image *img, const uint8_t *payload) {
|
handle_animation_frame_load_command(GraphicsManager *self, GraphicsCommand *g, Image *img, const uint8_t *payload, bool *is_dirty) {
|
||||||
uint32_t frame_number = g->_frame_number, fmt = g->format ? g->format : RGBA;
|
uint32_t frame_number = g->_frame_number, fmt = g->format ? g->format : RGBA;
|
||||||
if (!frame_number || frame_number > img->extra_framecnt + 2) frame_number = img->extra_framecnt + 2;
|
if (!frame_number || frame_number > img->extra_framecnt + 2) frame_number = img->extra_framecnt + 2;
|
||||||
bool is_new_frame = frame_number == img->extra_framecnt + 2;
|
bool is_new_frame = frame_number == img->extra_framecnt + 2;
|
||||||
@ -822,6 +846,7 @@ handle_animation_frame_load_command(GraphicsManager *self, GraphicsCommand *g, I
|
|||||||
|
|
||||||
void *base_data = NULL;
|
void *base_data = NULL;
|
||||||
size_t data_sz = 0;
|
size_t data_sz = 0;
|
||||||
|
bool needs_send_to_gpu = false;
|
||||||
ImageAndFrame key = { .image_id = img->internal_id };
|
ImageAndFrame key = { .image_id = img->internal_id };
|
||||||
if (is_new_frame) {
|
if (is_new_frame) {
|
||||||
key.frame_id = ++img->frame_id_counter;
|
key.frame_id = ++img->frame_id_counter;
|
||||||
@ -849,6 +874,8 @@ handle_animation_frame_load_command(GraphicsManager *self, GraphicsCommand *g, I
|
|||||||
if (!read_from_cache(self, key, &base_data, &data_sz)) {
|
if (!read_from_cache(self, key, &base_data, &data_sz)) {
|
||||||
FAIL("ENODATA", "No data for frame with number: %u found in image: %u", frame_number, img->client_id);
|
FAIL("ENODATA", "No data for frame with number: %u found in image: %u", frame_number, img->client_id);
|
||||||
}
|
}
|
||||||
|
Frame *f = current_frame(img);
|
||||||
|
if (f && f->id == key.frame_id) needs_send_to_gpu = true;
|
||||||
}
|
}
|
||||||
if (data_sz != expected_data_sz) {
|
if (data_sz != expected_data_sz) {
|
||||||
free(base_data);
|
free(base_data);
|
||||||
@ -871,6 +898,10 @@ handle_animation_frame_load_command(GraphicsManager *self, GraphicsCommand *g, I
|
|||||||
|
|
||||||
free_load_data(&img->load_data);
|
free_load_data(&img->load_data);
|
||||||
bool added = add_to_cache(self, key, base_data, data_sz);
|
bool added = add_to_cache(self, key, base_data, data_sz);
|
||||||
|
if (needs_send_to_gpu) {
|
||||||
|
update_current_frame(self, img, base_data);
|
||||||
|
*is_dirty = true;
|
||||||
|
}
|
||||||
free(base_data);
|
free(base_data);
|
||||||
if (!added) {
|
if (!added) {
|
||||||
PyErr_Print();
|
PyErr_Print();
|
||||||
@ -893,7 +924,7 @@ handle_animation_frame_load_command(GraphicsManager *self, GraphicsCommand *g, I
|
|||||||
#undef ABRT
|
#undef ABRT
|
||||||
|
|
||||||
static Image*
|
static Image*
|
||||||
handle_delete_frame_command(GraphicsManager *self, const GraphicsCommand *g, bool *is_dirty UNUSED) {
|
handle_delete_frame_command(GraphicsManager *self, const GraphicsCommand *g, bool *is_dirty) {
|
||||||
if (!g->id && !g->image_number) {
|
if (!g->id && !g->image_number) {
|
||||||
REPORT_ERROR("Delete frame data command without image id or number");
|
REPORT_ERROR("Delete frame data command without image id or number");
|
||||||
return NULL;
|
return NULL;
|
||||||
@ -906,6 +937,7 @@ handle_delete_frame_command(GraphicsManager *self, const GraphicsCommand *g, boo
|
|||||||
uint32_t frame_number = MIN(img->extra_framecnt + 1, g->_frame_number);
|
uint32_t frame_number = MIN(img->extra_framecnt + 1, g->_frame_number);
|
||||||
if (!frame_number) frame_number = 1;
|
if (!frame_number) frame_number = 1;
|
||||||
if (!img->extra_framecnt) return g->delete_action == 'F' ? img : NULL;
|
if (!img->extra_framecnt) return g->delete_action == 'F' ? img : NULL;
|
||||||
|
*is_dirty = true;
|
||||||
ImageAndFrame key = {.image_id=img->internal_id};
|
ImageAndFrame key = {.image_id=img->internal_id};
|
||||||
bool remove_root = frame_number == 1;
|
bool remove_root = frame_number == 1;
|
||||||
if (remove_root) {
|
if (remove_root) {
|
||||||
@ -914,19 +946,26 @@ handle_delete_frame_command(GraphicsManager *self, const GraphicsCommand *g, boo
|
|||||||
if (PyErr_Occurred()) PyErr_Print();
|
if (PyErr_Occurred()) PyErr_Print();
|
||||||
img->root_frame = img->extra_frames[0];
|
img->root_frame = img->extra_frames[0];
|
||||||
}
|
}
|
||||||
unsigned idx = remove_root ? 0 : frame_number - 2;
|
unsigned removed_idx = remove_root ? 0 : frame_number - 2;
|
||||||
if (!remove_root) {
|
if (!remove_root) {
|
||||||
key.frame_id = img->extra_frames[idx].id;
|
key.frame_id = img->extra_frames[removed_idx].id;
|
||||||
remove_from_cache(self, key);
|
remove_from_cache(self, key);
|
||||||
}
|
}
|
||||||
if (PyErr_Occurred()) PyErr_Print();
|
if (PyErr_Occurred()) PyErr_Print();
|
||||||
if (idx < img->extra_framecnt - 1) memmove(img->extra_frames + idx, img->extra_frames + idx + 1, sizeof(img->extra_frames[0]) * img->extra_framecnt - 1 - idx);
|
if (removed_idx < img->extra_framecnt - 1) memmove(img->extra_frames + removed_idx, img->extra_frames + removed_idx + 1, sizeof(img->extra_frames[0]) * img->extra_framecnt - 1 - removed_idx);
|
||||||
img->extra_framecnt--;
|
img->extra_framecnt--;
|
||||||
|
if (img->current_frame_index > img->extra_framecnt) {
|
||||||
|
img->current_frame_index = img->extra_framecnt;
|
||||||
|
update_current_frame(self, img, NULL);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
if (removed_idx == img->current_frame_index) update_current_frame(self, img, NULL);
|
||||||
|
else if (removed_idx < img->current_frame_index) img->current_frame_index--;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
handle_animation_control_command(bool *is_dirty, const GraphicsCommand *g, Image *img) {
|
handle_animation_control_command(GraphicsManager *self, bool *is_dirty, const GraphicsCommand *g, Image *img) {
|
||||||
if (g->_frame_number) {
|
if (g->_frame_number) {
|
||||||
uint32_t frame_idx = g->_frame_number - 1;
|
uint32_t frame_idx = g->_frame_number - 1;
|
||||||
if (frame_idx <= img->extra_framecnt) {
|
if (frame_idx <= img->extra_framecnt) {
|
||||||
@ -939,6 +978,7 @@ handle_animation_control_command(bool *is_dirty, const GraphicsCommand *g, Image
|
|||||||
if (frame_idx != img->current_frame_index && frame_idx <= img->extra_framecnt) {
|
if (frame_idx != img->current_frame_index && frame_idx <= img->extra_framecnt) {
|
||||||
img->current_frame_index = frame_idx;
|
img->current_frame_index = frame_idx;
|
||||||
*is_dirty = true;
|
*is_dirty = true;
|
||||||
|
update_current_frame(self, img, NULL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (g->_animation_enabled) {
|
if (g->_animation_enabled) {
|
||||||
@ -1201,10 +1241,10 @@ grman_handle_command(GraphicsManager *self, const GraphicsCommand *g, const uint
|
|||||||
} else {
|
} else {
|
||||||
GraphicsCommand ag = *g;
|
GraphicsCommand ag = *g;
|
||||||
if (ag.action == 'f') {
|
if (ag.action == 'f') {
|
||||||
img = handle_animation_frame_load_command(self, &ag, img, payload);
|
img = handle_animation_frame_load_command(self, &ag, img, payload, is_dirty);
|
||||||
ret = finish_command_response(&ag, img != NULL);
|
ret = finish_command_response(&ag, img != NULL);
|
||||||
} else if (ag.action == 'a') {
|
} else if (ag.action == 'a') {
|
||||||
handle_animation_control_command(is_dirty, &ag, img);
|
handle_animation_control_command(self, is_dirty, &ag, img);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|||||||
@ -663,21 +663,28 @@ class TestGraphics(BaseTest):
|
|||||||
{'gap': 101, 'id': 3, 'data': b'444444333333444444333333333333333333'},
|
{'gap': 101, 'id': 3, 'data': b'444444333333444444333333333333333333'},
|
||||||
{'gap': 40, 'id': 4, 'data': b'5' * 36},
|
{'gap': 40, 'id': 4, 'data': b'5' * 36},
|
||||||
))
|
))
|
||||||
|
self.assertEqual(img['current_frame_index'], 1)
|
||||||
self.assertIsNone(li(a='d', d='f', i=1, r=1))
|
self.assertIsNone(li(a='d', d='f', i=1, r=1))
|
||||||
img = g.image_for_client_id(1)
|
img = g.image_for_client_id(1)
|
||||||
|
self.assertEqual(img['current_frame_index'], 0)
|
||||||
self.assertEqual(img['data'], b'3' * 36)
|
self.assertEqual(img['data'], b'3' * 36)
|
||||||
self.assertEqual(img['extra_frames'], (
|
self.assertEqual(img['extra_frames'], (
|
||||||
{'gap': 101, 'id': 3, 'data': b'444444333333444444333333333333333333'},
|
{'gap': 101, 'id': 3, 'data': b'444444333333444444333333333333333333'},
|
||||||
{'gap': 40, 'id': 4, 'data': b'5' * 36},
|
{'gap': 40, 'id': 4, 'data': b'5' * 36},
|
||||||
))
|
))
|
||||||
|
self.assertIsNone(li(a='a', i=1, c=3))
|
||||||
|
img = g.image_for_client_id(1)
|
||||||
|
self.assertEqual(img['current_frame_index'], 2)
|
||||||
self.assertIsNone(li(a='d', d='f', i=1, r=2))
|
self.assertIsNone(li(a='d', d='f', i=1, r=2))
|
||||||
img = g.image_for_client_id(1)
|
img = g.image_for_client_id(1)
|
||||||
|
self.assertEqual(img['current_frame_index'], 1)
|
||||||
self.assertEqual(img['data'], b'3' * 36)
|
self.assertEqual(img['data'], b'3' * 36)
|
||||||
self.assertEqual(img['extra_frames'], (
|
self.assertEqual(img['extra_frames'], (
|
||||||
{'gap': 40, 'id': 4, 'data': b'5' * 36},
|
{'gap': 40, 'id': 4, 'data': b'5' * 36},
|
||||||
))
|
))
|
||||||
self.assertIsNone(li(a='d', d='f', i=1))
|
self.assertIsNone(li(a='d', d='f', i=1))
|
||||||
img = g.image_for_client_id(1)
|
img = g.image_for_client_id(1)
|
||||||
|
self.assertEqual(img['current_frame_index'], 0)
|
||||||
self.assertEqual(img['data'], b'5' * 36)
|
self.assertEqual(img['data'], b'5' * 36)
|
||||||
self.assertFalse(img['extra_frames'])
|
self.assertFalse(img['extra_frames'])
|
||||||
self.assertIsNone(li(a='d', d='f', i=1))
|
self.assertIsNone(li(a='d', d='f', i=1))
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user