From f6e41197462baf451dd30225c856a6d7eebc52b4 Mon Sep 17 00:00:00 2001 From: "Alexander W. Schultz" Date: Mon, 21 Oct 2024 00:24:44 -0400 Subject: [PATCH 01/10] Adds CRC calculation to draw command buffer Adding a rolling CRC caluclation based off the commands going into the draw buffer allows for really quick and cheap difference detection. That is, for an application to know if it needs to nk_convert and paint the screen again. All that needs to be done now, is to store the previous CRC value and compare that to the latest value to determine if you should draw or not. --- nuklear.h | 119 ++++++++++++++++++++++++++++++++++++++--- src/nuklear.h | 25 ++++++--- src/nuklear_context.c | 1 + src/nuklear_crc.c | 89 ++++++++++++++++++++++++++++++ src/nuklear_draw.c | 1 + src/nuklear_internal.h | 2 + src/paq.bat | 2 +- src/paq.sh | 2 +- 8 files changed, 225 insertions(+), 16 deletions(-) create mode 100644 src/nuklear_crc.c diff --git a/nuklear.h b/nuklear.h index 5091695e1..014911f0a 100644 --- a/nuklear.h +++ b/nuklear.h @@ -1054,13 +1054,17 @@ NK_API void nk_input_end(struct nk_context*); /// The second probably more applicable trick is to only draw if anything changed. /// It is not really useful for applications with continuous draw loop but /// quite useful for desktop applications. To actually get nuklear to only -/// draw on changes you first have to define `NK_ZERO_COMMAND_MEMORY` and -/// allocate a memory buffer that will store each unique drawing output. -/// After each frame you compare the draw command memory inside the library -/// with your allocated buffer by memcmp. If memcmp detects differences -/// you have to copy the command buffer into the allocated buffer -/// and then draw like usual (this example uses fixed memory but you could -/// use dynamically allocated memory). +/// draw on changes you can do one of 2 things. First, nuklear generates a +/// checksum of the draw commands that clears on nk_clear. You can get this +/// checksum at the end of your gui updates by calling `nk_buffer_crc()`. If +/// this number is different from the previous frame; then you know something +/// different happened in the command tree. Secondly, you could define +/// `NK_ZERO_COMMAND_MEMORY` and allocate a memory buffer that will store each +/// unique drawing output. After each frame you compare the draw command memory +/// inside the library with your allocated buffer by memcmp. If memcmp detects +/// differences you have to copy the command buffer into the allocated buffer +/// and then draw like usual (this example uses fixed memory but you could use +/// dynamically allocated memory). /// /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c /// //[... other defines ...] @@ -1322,6 +1326,13 @@ NK_API const struct nk_draw_command* nk__draw_next(const struct nk_draw_command* /// __buf__ | Must point to an previously by `nk_convert` filled out vertex draw command buffer /// __ctx__ | Must point to an previously initialized `nk_context` struct at the end of a frame */ + + +/** + * \brief returns the crc of the command buffer. + */ +NK_API NK_UINT32 nk_buffer_crc(); + #define nk_draw_foreach(cmd,ctx, b) for((cmd)=nk__draw_begin(ctx, b); (cmd)!=0; (cmd)=nk__draw_next(cmd, b, ctx)) #endif /* ============================================================================= @@ -6010,6 +6021,8 @@ NK_LIB nk_bool nk_is_lower(int c); NK_LIB nk_bool nk_is_upper(int c); NK_LIB int nk_to_upper(int c); NK_LIB int nk_to_lower(int c); +NK_LIB void nk_crc_update(NK_UINT8 *data, NK_SIZE_TYPE len); +NK_LIB void nk_crc_clear(); #ifndef NK_MEMCPY NK_LIB void* nk_memcopy(void *dst, const void *src, nk_size n); @@ -6264,6 +6277,96 @@ nk_stbtt_free(void *ptr, void *user_data) { +NK_STORAGE NK_UINT32 crc32c_table[] = { + 0x00000000L, 0xF26B8303L, 0xE13B70F7L, 0x1350F3F4L, 0xC79A971FL, 0x35F1141CL, + 0x26A1E7E8L, 0xD4CA64EBL, 0x8AD958CFL, 0x78B2DBCCL, 0x6BE22838L, 0x9989AB3BL, + 0x4D43CFD0L, 0xBF284CD3L, 0xAC78BF27L, 0x5E133C24L, 0x105EC76FL, 0xE235446CL, + 0xF165B798L, 0x030E349BL, 0xD7C45070L, 0x25AFD373L, 0x36FF2087L, 0xC494A384L, + 0x9A879FA0L, 0x68EC1CA3L, 0x7BBCEF57L, 0x89D76C54L, 0x5D1D08BFL, 0xAF768BBCL, + 0xBC267848L, 0x4E4DFB4BL, 0x20BD8EDEL, 0xD2D60DDDL, 0xC186FE29L, 0x33ED7D2AL, + 0xE72719C1L, 0x154C9AC2L, 0x061C6936L, 0xF477EA35L, 0xAA64D611L, 0x580F5512L, + 0x4B5FA6E6L, 0xB93425E5L, 0x6DFE410EL, 0x9F95C20DL, 0x8CC531F9L, 0x7EAEB2FAL, + 0x30E349B1L, 0xC288CAB2L, 0xD1D83946L, 0x23B3BA45L, 0xF779DEAEL, 0x05125DADL, + 0x1642AE59L, 0xE4292D5AL, 0xBA3A117EL, 0x4851927DL, 0x5B016189L, 0xA96AE28AL, + 0x7DA08661L, 0x8FCB0562L, 0x9C9BF696L, 0x6EF07595L, 0x417B1DBCL, 0xB3109EBFL, + 0xA0406D4BL, 0x522BEE48L, 0x86E18AA3L, 0x748A09A0L, 0x67DAFA54L, 0x95B17957L, + 0xCBA24573L, 0x39C9C670L, 0x2A993584L, 0xD8F2B687L, 0x0C38D26CL, 0xFE53516FL, + 0xED03A29BL, 0x1F682198L, 0x5125DAD3L, 0xA34E59D0L, 0xB01EAA24L, 0x42752927L, + 0x96BF4DCCL, 0x64D4CECFL, 0x77843D3BL, 0x85EFBE38L, 0xDBFC821CL, 0x2997011FL, + 0x3AC7F2EBL, 0xC8AC71E8L, 0x1C661503L, 0xEE0D9600L, 0xFD5D65F4L, 0x0F36E6F7L, + 0x61C69362L, 0x93AD1061L, 0x80FDE395L, 0x72966096L, 0xA65C047DL, 0x5437877EL, + 0x4767748AL, 0xB50CF789L, 0xEB1FCBADL, 0x197448AEL, 0x0A24BB5AL, 0xF84F3859L, + 0x2C855CB2L, 0xDEEEDFB1L, 0xCDBE2C45L, 0x3FD5AF46L, 0x7198540DL, 0x83F3D70EL, + 0x90A324FAL, 0x62C8A7F9L, 0xB602C312L, 0x44694011L, 0x5739B3E5L, 0xA55230E6L, + 0xFB410CC2L, 0x092A8FC1L, 0x1A7A7C35L, 0xE811FF36L, 0x3CDB9BDDL, 0xCEB018DEL, + 0xDDE0EB2AL, 0x2F8B6829L, 0x82F63B78L, 0x709DB87BL, 0x63CD4B8FL, 0x91A6C88CL, + 0x456CAC67L, 0xB7072F64L, 0xA457DC90L, 0x563C5F93L, 0x082F63B7L, 0xFA44E0B4L, + 0xE9141340L, 0x1B7F9043L, 0xCFB5F4A8L, 0x3DDE77ABL, 0x2E8E845FL, 0xDCE5075CL, + 0x92A8FC17L, 0x60C37F14L, 0x73938CE0L, 0x81F80FE3L, 0x55326B08L, 0xA759E80BL, + 0xB4091BFFL, 0x466298FCL, 0x1871A4D8L, 0xEA1A27DBL, 0xF94AD42FL, 0x0B21572CL, + 0xDFEB33C7L, 0x2D80B0C4L, 0x3ED04330L, 0xCCBBC033L, 0xA24BB5A6L, 0x502036A5L, + 0x4370C551L, 0xB11B4652L, 0x65D122B9L, 0x97BAA1BAL, 0x84EA524EL, 0x7681D14DL, + 0x2892ED69L, 0xDAF96E6AL, 0xC9A99D9EL, 0x3BC21E9DL, 0xEF087A76L, 0x1D63F975L, + 0x0E330A81L, 0xFC588982L, 0xB21572C9L, 0x407EF1CAL, 0x532E023EL, 0xA145813DL, + 0x758FE5D6L, 0x87E466D5L, 0x94B49521L, 0x66DF1622L, 0x38CC2A06L, 0xCAA7A905L, + 0xD9F75AF1L, 0x2B9CD9F2L, 0xFF56BD19L, 0x0D3D3E1AL, 0x1E6DCDEEL, 0xEC064EEDL, + 0xC38D26C4L, 0x31E6A5C7L, 0x22B65633L, 0xD0DDD530L, 0x0417B1DBL, 0xF67C32D8L, + 0xE52CC12CL, 0x1747422FL, 0x49547E0BL, 0xBB3FFD08L, 0xA86F0EFCL, 0x5A048DFFL, + 0x8ECEE914L, 0x7CA56A17L, 0x6FF599E3L, 0x9D9E1AE0L, 0xD3D3E1ABL, 0x21B862A8L, + 0x32E8915CL, 0xC083125FL, 0x144976B4L, 0xE622F5B7L, 0xF5720643L, 0x07198540L, + 0x590AB964L, 0xAB613A67L, 0xB831C993L, 0x4A5A4A90L, 0x9E902E7BL, 0x6CFBAD78L, + 0x7FAB5E8CL, 0x8DC0DD8FL, 0xE330A81AL, 0x115B2B19L, 0x020BD8EDL, 0xF0605BEEL, + 0x24AA3F05L, 0xD6C1BC06L, 0xC5914FF2L, 0x37FACCF1L, 0x69E9F0D5L, 0x9B8273D6L, + 0x88D28022L, 0x7AB90321L, 0xAE7367CAL, 0x5C18E4C9L, 0x4F48173DL, 0xBD23943EL, + 0xF36E6F75L, 0x0105EC76L, 0x12551F82L, 0xE03E9C81L, 0x34F4F86AL, 0xC69F7B69L, + 0xD5CF889DL, 0x27A40B9EL, 0x79B737BAL, 0x8BDCB4B9L, 0x988C474DL, 0x6AE7C44EL, + 0xBE2DA0A5L, 0x4C4623A6L, 0x5F16D052L, 0xAD7D5351L +}; + + +#define NK_CRC_SEED 0xffffffff /**< seed value of the crc*/ +NK_GLOBAL NK_UINT32 NK_BUFFER_CRC = NK_CRC_SEED; /**< the CRC value of the command buffer.*/ + +/** + * \brief steps the crc value by the amount of new data. + * + * \details + * this function should only be called in the nk_command_buffer_push() function + * and should only be given the `type` enum of the command being pushed. As the + * buffer is getting filled, this function will roll and calculate the CRC + * value. Never clearing will result is a proper CRC at the end of the drawing + * updates. + * + * \param[in] data is a pointer to the data to run the CRC on. + * \param[in] len is the size in bytes of the data. + */ +NK_LIB void nk_crc_update(NK_UINT8 *data, NK_SIZE_TYPE len) +{ + while (len--) NK_BUFFER_CRC = (NK_BUFFER_CRC<<8) ^ crc32c_table[(NK_BUFFER_CRC >> 24) ^ *data++]; +} + +/** + * \brief re-initializes the command buffer crc. + * + * \details + * should be called on nk_clear such that the CRC can start over. + */ +NK_LIB void nk_crc_clear() +{ + NK_BUFFER_CRC = NK_CRC_SEED; +} + +/** + * \brief returns the crc of the command buffer. + */ +NK_API NK_UINT32 nk_buffer_crc() +{ + return NK_BUFFER_CRC; +} + + + + /* =============================================================== * * MATH @@ -9108,6 +9211,7 @@ nk_command_buffer_push(struct nk_command_buffer* b, cmd->userdata = b->userdata; #endif b->end = cmd->next; + nk_crc_update((NK_UINT8*)cmd,size); return cmd; } NK_API void @@ -19288,6 +19392,7 @@ nk_clear(struct nk_context *ctx) if (ctx->use_pool) nk_buffer_clear(&ctx->memory); else nk_buffer_reset(&ctx->memory, NK_BUFFER_FRONT); + nk_crc_clear(); /*clear the draw buffer crc*/ ctx->build = 0; ctx->memory.calls = 0; diff --git a/src/nuklear.h b/src/nuklear.h index 6a30b3947..e2b5d8a7f 100644 --- a/src/nuklear.h +++ b/src/nuklear.h @@ -832,13 +832,17 @@ NK_API void nk_input_end(struct nk_context*); /// The second probably more applicable trick is to only draw if anything changed. /// It is not really useful for applications with continuous draw loop but /// quite useful for desktop applications. To actually get nuklear to only -/// draw on changes you first have to define `NK_ZERO_COMMAND_MEMORY` and -/// allocate a memory buffer that will store each unique drawing output. -/// After each frame you compare the draw command memory inside the library -/// with your allocated buffer by memcmp. If memcmp detects differences -/// you have to copy the command buffer into the allocated buffer -/// and then draw like usual (this example uses fixed memory but you could -/// use dynamically allocated memory). +/// draw on changes you can do one of 2 things. First, nuklear generates a +/// checksum of the draw commands that clears on nk_clear. You can get this +/// checksum at the end of your gui updates by calling `nk_buffer_crc()`. If +/// this number is different from the previous frame; then you know something +/// different happened in the command tree. Secondly, you could define +/// `NK_ZERO_COMMAND_MEMORY` and allocate a memory buffer that will store each +/// unique drawing output. After each frame you compare the draw command memory +/// inside the library with your allocated buffer by memcmp. If memcmp detects +/// differences you have to copy the command buffer into the allocated buffer +/// and then draw like usual (this example uses fixed memory but you could use +/// dynamically allocated memory). /// /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c /// //[... other defines ...] @@ -1100,6 +1104,13 @@ NK_API const struct nk_draw_command* nk__draw_next(const struct nk_draw_command* /// __buf__ | Must point to an previously by `nk_convert` filled out vertex draw command buffer /// __ctx__ | Must point to an previously initialized `nk_context` struct at the end of a frame */ + + +/** + * \brief returns the crc of the command buffer. + */ +NK_API NK_UINT32 nk_buffer_crc(); + #define nk_draw_foreach(cmd,ctx, b) for((cmd)=nk__draw_begin(ctx, b); (cmd)!=0; (cmd)=nk__draw_next(cmd, b, ctx)) #endif /* ============================================================================= diff --git a/src/nuklear_context.c b/src/nuklear_context.c index 771449689..59d5d4f9b 100644 --- a/src/nuklear_context.c +++ b/src/nuklear_context.c @@ -117,6 +117,7 @@ nk_clear(struct nk_context *ctx) if (ctx->use_pool) nk_buffer_clear(&ctx->memory); else nk_buffer_reset(&ctx->memory, NK_BUFFER_FRONT); + nk_crc_clear(); /*clear the draw buffer crc*/ ctx->build = 0; ctx->memory.calls = 0; diff --git a/src/nuklear_crc.c b/src/nuklear_crc.c new file mode 100644 index 000000000..e55beee77 --- /dev/null +++ b/src/nuklear_crc.c @@ -0,0 +1,89 @@ +#include "nuklear.h" +#include "nuklear_internal.h" + +NK_STORAGE NK_UINT32 crc32c_table[] = { + 0x00000000L, 0xF26B8303L, 0xE13B70F7L, 0x1350F3F4L, 0xC79A971FL, 0x35F1141CL, + 0x26A1E7E8L, 0xD4CA64EBL, 0x8AD958CFL, 0x78B2DBCCL, 0x6BE22838L, 0x9989AB3BL, + 0x4D43CFD0L, 0xBF284CD3L, 0xAC78BF27L, 0x5E133C24L, 0x105EC76FL, 0xE235446CL, + 0xF165B798L, 0x030E349BL, 0xD7C45070L, 0x25AFD373L, 0x36FF2087L, 0xC494A384L, + 0x9A879FA0L, 0x68EC1CA3L, 0x7BBCEF57L, 0x89D76C54L, 0x5D1D08BFL, 0xAF768BBCL, + 0xBC267848L, 0x4E4DFB4BL, 0x20BD8EDEL, 0xD2D60DDDL, 0xC186FE29L, 0x33ED7D2AL, + 0xE72719C1L, 0x154C9AC2L, 0x061C6936L, 0xF477EA35L, 0xAA64D611L, 0x580F5512L, + 0x4B5FA6E6L, 0xB93425E5L, 0x6DFE410EL, 0x9F95C20DL, 0x8CC531F9L, 0x7EAEB2FAL, + 0x30E349B1L, 0xC288CAB2L, 0xD1D83946L, 0x23B3BA45L, 0xF779DEAEL, 0x05125DADL, + 0x1642AE59L, 0xE4292D5AL, 0xBA3A117EL, 0x4851927DL, 0x5B016189L, 0xA96AE28AL, + 0x7DA08661L, 0x8FCB0562L, 0x9C9BF696L, 0x6EF07595L, 0x417B1DBCL, 0xB3109EBFL, + 0xA0406D4BL, 0x522BEE48L, 0x86E18AA3L, 0x748A09A0L, 0x67DAFA54L, 0x95B17957L, + 0xCBA24573L, 0x39C9C670L, 0x2A993584L, 0xD8F2B687L, 0x0C38D26CL, 0xFE53516FL, + 0xED03A29BL, 0x1F682198L, 0x5125DAD3L, 0xA34E59D0L, 0xB01EAA24L, 0x42752927L, + 0x96BF4DCCL, 0x64D4CECFL, 0x77843D3BL, 0x85EFBE38L, 0xDBFC821CL, 0x2997011FL, + 0x3AC7F2EBL, 0xC8AC71E8L, 0x1C661503L, 0xEE0D9600L, 0xFD5D65F4L, 0x0F36E6F7L, + 0x61C69362L, 0x93AD1061L, 0x80FDE395L, 0x72966096L, 0xA65C047DL, 0x5437877EL, + 0x4767748AL, 0xB50CF789L, 0xEB1FCBADL, 0x197448AEL, 0x0A24BB5AL, 0xF84F3859L, + 0x2C855CB2L, 0xDEEEDFB1L, 0xCDBE2C45L, 0x3FD5AF46L, 0x7198540DL, 0x83F3D70EL, + 0x90A324FAL, 0x62C8A7F9L, 0xB602C312L, 0x44694011L, 0x5739B3E5L, 0xA55230E6L, + 0xFB410CC2L, 0x092A8FC1L, 0x1A7A7C35L, 0xE811FF36L, 0x3CDB9BDDL, 0xCEB018DEL, + 0xDDE0EB2AL, 0x2F8B6829L, 0x82F63B78L, 0x709DB87BL, 0x63CD4B8FL, 0x91A6C88CL, + 0x456CAC67L, 0xB7072F64L, 0xA457DC90L, 0x563C5F93L, 0x082F63B7L, 0xFA44E0B4L, + 0xE9141340L, 0x1B7F9043L, 0xCFB5F4A8L, 0x3DDE77ABL, 0x2E8E845FL, 0xDCE5075CL, + 0x92A8FC17L, 0x60C37F14L, 0x73938CE0L, 0x81F80FE3L, 0x55326B08L, 0xA759E80BL, + 0xB4091BFFL, 0x466298FCL, 0x1871A4D8L, 0xEA1A27DBL, 0xF94AD42FL, 0x0B21572CL, + 0xDFEB33C7L, 0x2D80B0C4L, 0x3ED04330L, 0xCCBBC033L, 0xA24BB5A6L, 0x502036A5L, + 0x4370C551L, 0xB11B4652L, 0x65D122B9L, 0x97BAA1BAL, 0x84EA524EL, 0x7681D14DL, + 0x2892ED69L, 0xDAF96E6AL, 0xC9A99D9EL, 0x3BC21E9DL, 0xEF087A76L, 0x1D63F975L, + 0x0E330A81L, 0xFC588982L, 0xB21572C9L, 0x407EF1CAL, 0x532E023EL, 0xA145813DL, + 0x758FE5D6L, 0x87E466D5L, 0x94B49521L, 0x66DF1622L, 0x38CC2A06L, 0xCAA7A905L, + 0xD9F75AF1L, 0x2B9CD9F2L, 0xFF56BD19L, 0x0D3D3E1AL, 0x1E6DCDEEL, 0xEC064EEDL, + 0xC38D26C4L, 0x31E6A5C7L, 0x22B65633L, 0xD0DDD530L, 0x0417B1DBL, 0xF67C32D8L, + 0xE52CC12CL, 0x1747422FL, 0x49547E0BL, 0xBB3FFD08L, 0xA86F0EFCL, 0x5A048DFFL, + 0x8ECEE914L, 0x7CA56A17L, 0x6FF599E3L, 0x9D9E1AE0L, 0xD3D3E1ABL, 0x21B862A8L, + 0x32E8915CL, 0xC083125FL, 0x144976B4L, 0xE622F5B7L, 0xF5720643L, 0x07198540L, + 0x590AB964L, 0xAB613A67L, 0xB831C993L, 0x4A5A4A90L, 0x9E902E7BL, 0x6CFBAD78L, + 0x7FAB5E8CL, 0x8DC0DD8FL, 0xE330A81AL, 0x115B2B19L, 0x020BD8EDL, 0xF0605BEEL, + 0x24AA3F05L, 0xD6C1BC06L, 0xC5914FF2L, 0x37FACCF1L, 0x69E9F0D5L, 0x9B8273D6L, + 0x88D28022L, 0x7AB90321L, 0xAE7367CAL, 0x5C18E4C9L, 0x4F48173DL, 0xBD23943EL, + 0xF36E6F75L, 0x0105EC76L, 0x12551F82L, 0xE03E9C81L, 0x34F4F86AL, 0xC69F7B69L, + 0xD5CF889DL, 0x27A40B9EL, 0x79B737BAL, 0x8BDCB4B9L, 0x988C474DL, 0x6AE7C44EL, + 0xBE2DA0A5L, 0x4C4623A6L, 0x5F16D052L, 0xAD7D5351L +}; + + +#define NK_CRC_SEED 0xffffffff /**< seed value of the crc*/ +NK_GLOBAL NK_UINT32 NK_BUFFER_CRC = NK_CRC_SEED; /**< the CRC value of the command buffer.*/ + +/** + * \brief steps the crc value by the amount of new data. + * + * \details + * this function should only be called in the nk_command_buffer_push() function + * and should only be given the `type` enum of the command being pushed. As the + * buffer is getting filled, this function will roll and calculate the CRC + * value. Never clearing will result is a proper CRC at the end of the drawing + * updates. + * + * \param[in] data is a pointer to the data to run the CRC on. + * \param[in] len is the size in bytes of the data. + */ +NK_LIB void nk_crc_update(NK_UINT8 *data, NK_SIZE_TYPE len) +{ + while (len--) NK_BUFFER_CRC = (NK_BUFFER_CRC<<8) ^ crc32c_table[(NK_BUFFER_CRC >> 24) ^ *data++]; +} + +/** + * \brief re-initializes the command buffer crc. + * + * \details + * should be called on nk_clear such that the CRC can start over. + */ +NK_LIB void nk_crc_clear() +{ + NK_BUFFER_CRC = NK_CRC_SEED; +} + +/** + * \brief returns the crc of the command buffer. + */ +NK_API NK_UINT32 nk_buffer_crc() +{ + return NK_BUFFER_CRC; +} diff --git a/src/nuklear_draw.c b/src/nuklear_draw.c index efdf9c59b..3c4962498 100644 --- a/src/nuklear_draw.c +++ b/src/nuklear_draw.c @@ -63,6 +63,7 @@ nk_command_buffer_push(struct nk_command_buffer* b, cmd->userdata = b->userdata; #endif b->end = cmd->next; + nk_crc_update((NK_UINT8*)cmd,size); return cmd; } NK_API void diff --git a/src/nuklear_internal.h b/src/nuklear_internal.h index 51eef471e..e2f4a9c00 100644 --- a/src/nuklear_internal.h +++ b/src/nuklear_internal.h @@ -126,6 +126,8 @@ NK_LIB nk_bool nk_is_lower(int c); NK_LIB nk_bool nk_is_upper(int c); NK_LIB int nk_to_upper(int c); NK_LIB int nk_to_lower(int c); +NK_LIB void nk_crc_update(NK_UINT8 *data, NK_SIZE_TYPE len); +NK_LIB void nk_crc_clear(); #ifndef NK_MEMCPY NK_LIB void* nk_memcopy(void *dst, const void *src, nk_size n); diff --git a/src/paq.bat b/src/paq.bat index f42a16837..86407cd79 100644 --- a/src/paq.bat +++ b/src/paq.bat @@ -1 +1 @@ -build.py --macro NK --intro HEADER --pub nuklear.h --priv1 nuklear_internal.h,nuklear_math.c,nuklear_util.c,nuklear_color.c,nuklear_utf8.c,nuklear_buffer.c,nuklear_string.c,nuklear_draw.c,nuklear_vertex.c --extern stb_rect_pack.h,stb_truetype.h --priv2 nuklear_font.c,nuklear_input.c,nuklear_style.c,nuklear_context.c,nuklear_pool.c,nuklear_page_element.c,nuklear_table.c,nuklear_panel.c,nuklear_window.c,nuklear_popup.c,nuklear_contextual.c,nuklear_menu.c,nuklear_layout.c,nuklear_tree.c,nuklear_group.c,nuklear_list_view.c,nuklear_widget.c,nuklear_text.c,nuklear_image.c,nuklear_9slice.c,nuklear_button.c,nuklear_toggle.c,nuklear_selectable.c,nuklear_slider.c,nuklear_knob.c,nuklear_progress.c,nuklear_scrollbar.c,nuklear_text_editor.c,nuklear_edit.c,nuklear_property.c,nuklear_chart.c,nuklear_color_picker.c,nuklear_combo.c,nuklear_tooltip.c --outro LICENSE,CHANGELOG,CREDITS > ..\nuklear.h +build.py --macro NK --intro HEADER --pub nuklear.h --priv1 nuklear_internal.h,nuklear_crc.c,nuklear_math.c,nuklear_util.c,nuklear_color.c,nuklear_utf8.c,nuklear_buffer.c,nuklear_string.c,nuklear_draw.c,nuklear_vertex.c --extern stb_rect_pack.h,stb_truetype.h --priv2 nuklear_font.c,nuklear_input.c,nuklear_style.c,nuklear_context.c,nuklear_pool.c,nuklear_page_element.c,nuklear_table.c,nuklear_panel.c,nuklear_window.c,nuklear_popup.c,nuklear_contextual.c,nuklear_menu.c,nuklear_layout.c,nuklear_tree.c,nuklear_group.c,nuklear_list_view.c,nuklear_widget.c,nuklear_text.c,nuklear_image.c,nuklear_9slice.c,nuklear_button.c,nuklear_toggle.c,nuklear_selectable.c,nuklear_slider.c,nuklear_knob.c,nuklear_progress.c,nuklear_scrollbar.c,nuklear_text_editor.c,nuklear_edit.c,nuklear_property.c,nuklear_chart.c,nuklear_color_picker.c,nuklear_combo.c,nuklear_tooltip.c --outro LICENSE,CHANGELOG,CREDITS > ..\nuklear.h diff --git a/src/paq.sh b/src/paq.sh index 7effee7cf..64c07ac56 100755 --- a/src/paq.sh +++ b/src/paq.sh @@ -1,2 +1,2 @@ #!/bin/sh -python build.py --macro NK --intro HEADER --pub nuklear.h --priv1 nuklear_internal.h,nuklear_math.c,nuklear_util.c,nuklear_color.c,nuklear_utf8.c,nuklear_buffer.c,nuklear_string.c,nuklear_draw.c,nuklear_vertex.c --extern stb_rect_pack.h,stb_truetype.h --priv2 nuklear_font.c,nuklear_input.c,nuklear_style.c,nuklear_context.c,nuklear_pool.c,nuklear_page_element.c,nuklear_table.c,nuklear_panel.c,nuklear_window.c,nuklear_popup.c,nuklear_contextual.c,nuklear_menu.c,nuklear_layout.c,nuklear_tree.c,nuklear_group.c,nuklear_list_view.c,nuklear_widget.c,nuklear_text.c,nuklear_image.c,nuklear_9slice.c,nuklear_button.c,nuklear_toggle.c,nuklear_selectable.c,nuklear_slider.c,nuklear_knob.c,nuklear_progress.c,nuklear_scrollbar.c,nuklear_text_editor.c,nuklear_edit.c,nuklear_property.c,nuklear_chart.c,nuklear_color_picker.c,nuklear_combo.c,nuklear_tooltip.c --outro LICENSE,CHANGELOG,CREDITS > ../nuklear.h +python3 build.py --macro NK --intro HEADER --pub nuklear.h --priv1 nuklear_internal.h,nuklear_crc.c,nuklear_math.c,nuklear_util.c,nuklear_color.c,nuklear_utf8.c,nuklear_buffer.c,nuklear_string.c,nuklear_draw.c,nuklear_vertex.c --extern stb_rect_pack.h,stb_truetype.h --priv2 nuklear_font.c,nuklear_input.c,nuklear_style.c,nuklear_context.c,nuklear_pool.c,nuklear_page_element.c,nuklear_table.c,nuklear_panel.c,nuklear_window.c,nuklear_popup.c,nuklear_contextual.c,nuklear_menu.c,nuklear_layout.c,nuklear_tree.c,nuklear_group.c,nuklear_list_view.c,nuklear_widget.c,nuklear_text.c,nuklear_image.c,nuklear_9slice.c,nuklear_button.c,nuklear_toggle.c,nuklear_selectable.c,nuklear_slider.c,nuklear_knob.c,nuklear_progress.c,nuklear_scrollbar.c,nuklear_text_editor.c,nuklear_edit.c,nuklear_property.c,nuklear_chart.c,nuklear_color_picker.c,nuklear_combo.c,nuklear_tooltip.c --outro LICENSE,CHANGELOG,CREDITS > ../nuklear.h From 3e169be6fe12528711f49f261988875fae6da375 Mon Sep 17 00:00:00 2001 From: "Alexander W. Schultz" Date: Thu, 14 Nov 2024 08:28:19 -0500 Subject: [PATCH 02/10] feature: build.py now allows for space separated lists of files. this is a stepping stone to going to a full Makefile build system. All src files can be provided in the make and sent to build.py with minimal issues now that we don't have to build a comma separated list. --- src/build.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/build.py b/src/build.py index ba29fef8b..ff5c455d8 100644 --- a/src/build.py +++ b/src/build.py @@ -9,6 +9,7 @@ def print_help(): """usage: python single_header_packer.py --macro [--intro ] --extern --pub --priv1 --priv2 [--outro ] where can be a comma-separated list of files. e.g. --priv *.c,inc/*.h + or a space separated list encapsulated in quotes. e.g. --priv1 "file.c file2.c file3.c" The 'extern' files are placed between 'priv1' and 'priv2'. @@ -33,7 +34,8 @@ def print_help(): def parse_files(arg): files = [] - paths = arg.split(",") + paths = re.split(r'[,\s]', arg) + for path in paths: if "*" in path: # Wildcard From 2db7bd2745776878c36140b18bb08e980f3ed1ee Mon Sep 17 00:00:00 2001 From: "Alexander W. Schultz" Date: Fri, 15 Nov 2024 14:35:35 -0500 Subject: [PATCH 03/10] updates nuklear.h after merging --- nuklear.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/nuklear.h b/nuklear.h index 44e29655f..831577c39 100644 --- a/nuklear.h +++ b/nuklear.h @@ -6175,6 +6175,8 @@ NK_LIB nk_bool nk_is_lower(int c); NK_LIB nk_bool nk_is_upper(int c); NK_LIB int nk_to_upper(int c); NK_LIB int nk_to_lower(int c); +NK_LIB void nk_crc_update(NK_UINT8 *data, NK_SIZE_TYPE len); +NK_LIB void nk_crc_clear(); #ifndef NK_MEMCPY NK_LIB void* nk_memcopy(void *dst, const void *src, nk_size n); @@ -9269,6 +9271,7 @@ nk_command_buffer_push(struct nk_command_buffer* b, cmd->userdata = b->userdata; #endif b->end = cmd->next; + nk_crc_update((NK_UINT8*)cmd,size); return cmd; } NK_API void @@ -19446,6 +19449,7 @@ nk_clear(struct nk_context *ctx) if (ctx->use_pool) nk_buffer_clear(&ctx->memory); else nk_buffer_reset(&ctx->memory, NK_BUFFER_FRONT); + nk_crc_clear(); /*clear the draw buffer crc*/ ctx->build = 0; ctx->memory.calls = 0; From 47e418549fdedcc35d1e4f50dd0822890484259c Mon Sep 17 00:00:00 2001 From: "Alexander W. Schultz" Date: Fri, 15 Nov 2024 14:40:10 -0500 Subject: [PATCH 04/10] updates paq and nuklear.h after merge --- nuklear.h | 90 +++++++++++++++++++++++++++++++++++++++++++++++++++++ src/paq.bat | 2 +- src/paq.sh | 2 +- 3 files changed, 92 insertions(+), 2 deletions(-) diff --git a/nuklear.h b/nuklear.h index 831577c39..1321a4dba 100644 --- a/nuklear.h +++ b/nuklear.h @@ -16811,6 +16811,96 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +NK_STORAGE NK_UINT32 crc32c_table[] = { + 0x00000000L, 0xF26B8303L, 0xE13B70F7L, 0x1350F3F4L, 0xC79A971FL, 0x35F1141CL, + 0x26A1E7E8L, 0xD4CA64EBL, 0x8AD958CFL, 0x78B2DBCCL, 0x6BE22838L, 0x9989AB3BL, + 0x4D43CFD0L, 0xBF284CD3L, 0xAC78BF27L, 0x5E133C24L, 0x105EC76FL, 0xE235446CL, + 0xF165B798L, 0x030E349BL, 0xD7C45070L, 0x25AFD373L, 0x36FF2087L, 0xC494A384L, + 0x9A879FA0L, 0x68EC1CA3L, 0x7BBCEF57L, 0x89D76C54L, 0x5D1D08BFL, 0xAF768BBCL, + 0xBC267848L, 0x4E4DFB4BL, 0x20BD8EDEL, 0xD2D60DDDL, 0xC186FE29L, 0x33ED7D2AL, + 0xE72719C1L, 0x154C9AC2L, 0x061C6936L, 0xF477EA35L, 0xAA64D611L, 0x580F5512L, + 0x4B5FA6E6L, 0xB93425E5L, 0x6DFE410EL, 0x9F95C20DL, 0x8CC531F9L, 0x7EAEB2FAL, + 0x30E349B1L, 0xC288CAB2L, 0xD1D83946L, 0x23B3BA45L, 0xF779DEAEL, 0x05125DADL, + 0x1642AE59L, 0xE4292D5AL, 0xBA3A117EL, 0x4851927DL, 0x5B016189L, 0xA96AE28AL, + 0x7DA08661L, 0x8FCB0562L, 0x9C9BF696L, 0x6EF07595L, 0x417B1DBCL, 0xB3109EBFL, + 0xA0406D4BL, 0x522BEE48L, 0x86E18AA3L, 0x748A09A0L, 0x67DAFA54L, 0x95B17957L, + 0xCBA24573L, 0x39C9C670L, 0x2A993584L, 0xD8F2B687L, 0x0C38D26CL, 0xFE53516FL, + 0xED03A29BL, 0x1F682198L, 0x5125DAD3L, 0xA34E59D0L, 0xB01EAA24L, 0x42752927L, + 0x96BF4DCCL, 0x64D4CECFL, 0x77843D3BL, 0x85EFBE38L, 0xDBFC821CL, 0x2997011FL, + 0x3AC7F2EBL, 0xC8AC71E8L, 0x1C661503L, 0xEE0D9600L, 0xFD5D65F4L, 0x0F36E6F7L, + 0x61C69362L, 0x93AD1061L, 0x80FDE395L, 0x72966096L, 0xA65C047DL, 0x5437877EL, + 0x4767748AL, 0xB50CF789L, 0xEB1FCBADL, 0x197448AEL, 0x0A24BB5AL, 0xF84F3859L, + 0x2C855CB2L, 0xDEEEDFB1L, 0xCDBE2C45L, 0x3FD5AF46L, 0x7198540DL, 0x83F3D70EL, + 0x90A324FAL, 0x62C8A7F9L, 0xB602C312L, 0x44694011L, 0x5739B3E5L, 0xA55230E6L, + 0xFB410CC2L, 0x092A8FC1L, 0x1A7A7C35L, 0xE811FF36L, 0x3CDB9BDDL, 0xCEB018DEL, + 0xDDE0EB2AL, 0x2F8B6829L, 0x82F63B78L, 0x709DB87BL, 0x63CD4B8FL, 0x91A6C88CL, + 0x456CAC67L, 0xB7072F64L, 0xA457DC90L, 0x563C5F93L, 0x082F63B7L, 0xFA44E0B4L, + 0xE9141340L, 0x1B7F9043L, 0xCFB5F4A8L, 0x3DDE77ABL, 0x2E8E845FL, 0xDCE5075CL, + 0x92A8FC17L, 0x60C37F14L, 0x73938CE0L, 0x81F80FE3L, 0x55326B08L, 0xA759E80BL, + 0xB4091BFFL, 0x466298FCL, 0x1871A4D8L, 0xEA1A27DBL, 0xF94AD42FL, 0x0B21572CL, + 0xDFEB33C7L, 0x2D80B0C4L, 0x3ED04330L, 0xCCBBC033L, 0xA24BB5A6L, 0x502036A5L, + 0x4370C551L, 0xB11B4652L, 0x65D122B9L, 0x97BAA1BAL, 0x84EA524EL, 0x7681D14DL, + 0x2892ED69L, 0xDAF96E6AL, 0xC9A99D9EL, 0x3BC21E9DL, 0xEF087A76L, 0x1D63F975L, + 0x0E330A81L, 0xFC588982L, 0xB21572C9L, 0x407EF1CAL, 0x532E023EL, 0xA145813DL, + 0x758FE5D6L, 0x87E466D5L, 0x94B49521L, 0x66DF1622L, 0x38CC2A06L, 0xCAA7A905L, + 0xD9F75AF1L, 0x2B9CD9F2L, 0xFF56BD19L, 0x0D3D3E1AL, 0x1E6DCDEEL, 0xEC064EEDL, + 0xC38D26C4L, 0x31E6A5C7L, 0x22B65633L, 0xD0DDD530L, 0x0417B1DBL, 0xF67C32D8L, + 0xE52CC12CL, 0x1747422FL, 0x49547E0BL, 0xBB3FFD08L, 0xA86F0EFCL, 0x5A048DFFL, + 0x8ECEE914L, 0x7CA56A17L, 0x6FF599E3L, 0x9D9E1AE0L, 0xD3D3E1ABL, 0x21B862A8L, + 0x32E8915CL, 0xC083125FL, 0x144976B4L, 0xE622F5B7L, 0xF5720643L, 0x07198540L, + 0x590AB964L, 0xAB613A67L, 0xB831C993L, 0x4A5A4A90L, 0x9E902E7BL, 0x6CFBAD78L, + 0x7FAB5E8CL, 0x8DC0DD8FL, 0xE330A81AL, 0x115B2B19L, 0x020BD8EDL, 0xF0605BEEL, + 0x24AA3F05L, 0xD6C1BC06L, 0xC5914FF2L, 0x37FACCF1L, 0x69E9F0D5L, 0x9B8273D6L, + 0x88D28022L, 0x7AB90321L, 0xAE7367CAL, 0x5C18E4C9L, 0x4F48173DL, 0xBD23943EL, + 0xF36E6F75L, 0x0105EC76L, 0x12551F82L, 0xE03E9C81L, 0x34F4F86AL, 0xC69F7B69L, + 0xD5CF889DL, 0x27A40B9EL, 0x79B737BAL, 0x8BDCB4B9L, 0x988C474DL, 0x6AE7C44EL, + 0xBE2DA0A5L, 0x4C4623A6L, 0x5F16D052L, 0xAD7D5351L +}; + + +#define NK_CRC_SEED 0xffffffff /**< seed value of the crc*/ +NK_GLOBAL NK_UINT32 NK_BUFFER_CRC = NK_CRC_SEED; /**< the CRC value of the command buffer.*/ + +/** + * \brief steps the crc value by the amount of new data. + * + * \details + * this function should only be called in the nk_command_buffer_push() function + * and should only be given the `type` enum of the command being pushed. As the + * buffer is getting filled, this function will roll and calculate the CRC + * value. Never clearing will result is a proper CRC at the end of the drawing + * updates. + * + * \param[in] data is a pointer to the data to run the CRC on. + * \param[in] len is the size in bytes of the data. + */ +NK_LIB void nk_crc_update(NK_UINT8 *data, NK_SIZE_TYPE len) +{ + while (len--) NK_BUFFER_CRC = (NK_BUFFER_CRC<<8) ^ crc32c_table[(NK_BUFFER_CRC >> 24) ^ *data++]; +} + +/** + * \brief re-initializes the command buffer crc. + * + * \details + * should be called on nk_clear such that the CRC can start over. + */ +NK_LIB void nk_crc_clear() +{ + NK_BUFFER_CRC = NK_CRC_SEED; +} + +/** + * \brief returns the crc of the command buffer. + */ +NK_API NK_UINT32 nk_buffer_crc() +{ + return NK_BUFFER_CRC; +} + + + + #ifdef NK_INCLUDE_FONT_BAKING /* ------------------------------------------------------------- * diff --git a/src/paq.bat b/src/paq.bat index 654734819..e11260c3a 100644 --- a/src/paq.bat +++ b/src/paq.bat @@ -1 +1 @@ -build.py --macro NK --intro HEADER.md --pub nuklear.h --priv1 nuklear_internal.h,nuklear_math.c,nuklear_util.c,nuklear_color.c,nuklear_utf8.c,nuklear_buffer.c,nuklear_string.c,nuklear_draw.c,nuklear_vertex.c --extern stb_rect_pack.h,stb_truetype.h --priv2 nuklear_font.c,nuklear_input.c,nuklear_style.c,nuklear_context.c,nuklear_pool.c,nuklear_page_element.c,nuklear_table.c,nuklear_panel.c,nuklear_window.c,nuklear_popup.c,nuklear_contextual.c,nuklear_menu.c,nuklear_layout.c,nuklear_tree.c,nuklear_group.c,nuklear_list_view.c,nuklear_widget.c,nuklear_text.c,nuklear_image.c,nuklear_9slice.c,nuklear_button.c,nuklear_toggle.c,nuklear_selectable.c,nuklear_slider.c,nuklear_knob.c,nuklear_progress.c,nuklear_scrollbar.c,nuklear_text_editor.c,nuklear_edit.c,nuklear_property.c,nuklear_chart.c,nuklear_color_picker.c,nuklear_combo.c,nuklear_tooltip.c --outro LICENSE,CHANGELOG,CREDITS > ..\nuklear.h +build.py --macro NK --intro HEADER.md --pub nuklear.h --priv1 nuklear_internal.h,nuklear_math.c,nuklear_util.c,nuklear_color.c,nuklear_utf8.c,nuklear_buffer.c,nuklear_string.c,nuklear_draw.c,nuklear_vertex.c --extern stb_rect_pack.h,stb_truetype.h --priv2 nuklear_crc.c,nuklear_font.c,nuklear_input.c,nuklear_style.c,nuklear_context.c,nuklear_pool.c,nuklear_page_element.c,nuklear_table.c,nuklear_panel.c,nuklear_window.c,nuklear_popup.c,nuklear_contextual.c,nuklear_menu.c,nuklear_layout.c,nuklear_tree.c,nuklear_group.c,nuklear_list_view.c,nuklear_widget.c,nuklear_text.c,nuklear_image.c,nuklear_9slice.c,nuklear_button.c,nuklear_toggle.c,nuklear_selectable.c,nuklear_slider.c,nuklear_knob.c,nuklear_progress.c,nuklear_scrollbar.c,nuklear_text_editor.c,nuklear_edit.c,nuklear_property.c,nuklear_chart.c,nuklear_color_picker.c,nuklear_combo.c,nuklear_tooltip.c --outro LICENSE,CHANGELOG,CREDITS > ..\nuklear.h diff --git a/src/paq.sh b/src/paq.sh index 5e8a1da48..b33a8d8c5 100755 --- a/src/paq.sh +++ b/src/paq.sh @@ -1,2 +1,2 @@ #!/bin/sh -python3 build.py --macro NK --intro HEADER.md --pub nuklear.h --priv1 nuklear_internal.h,nuklear_math.c,nuklear_util.c,nuklear_color.c,nuklear_utf8.c,nuklear_buffer.c,nuklear_string.c,nuklear_draw.c,nuklear_vertex.c --extern stb_rect_pack.h,stb_truetype.h --priv2 nuklear_font.c,nuklear_input.c,nuklear_style.c,nuklear_context.c,nuklear_pool.c,nuklear_page_element.c,nuklear_table.c,nuklear_panel.c,nuklear_window.c,nuklear_popup.c,nuklear_contextual.c,nuklear_menu.c,nuklear_layout.c,nuklear_tree.c,nuklear_group.c,nuklear_list_view.c,nuklear_widget.c,nuklear_text.c,nuklear_image.c,nuklear_9slice.c,nuklear_button.c,nuklear_toggle.c,nuklear_selectable.c,nuklear_slider.c,nuklear_knob.c,nuklear_progress.c,nuklear_scrollbar.c,nuklear_text_editor.c,nuklear_edit.c,nuklear_property.c,nuklear_chart.c,nuklear_color_picker.c,nuklear_combo.c,nuklear_tooltip.c --outro LICENSE,CHANGELOG,CREDITS > ../nuklear.h +python3 build.py --macro NK --intro HEADER.md --pub nuklear.h --priv1 nuklear_internal.h,nuklear_math.c,nuklear_util.c,nuklear_color.c,nuklear_utf8.c,nuklear_buffer.c,nuklear_string.c,nuklear_draw.c,nuklear_vertex.c --extern stb_rect_pack.h,stb_truetype.h --priv2 nuklear_crc.c,nuklear_font.c,nuklear_input.c,nuklear_style.c,nuklear_context.c,nuklear_pool.c,nuklear_page_element.c,nuklear_table.c,nuklear_panel.c,nuklear_window.c,nuklear_popup.c,nuklear_contextual.c,nuklear_menu.c,nuklear_layout.c,nuklear_tree.c,nuklear_group.c,nuklear_list_view.c,nuklear_widget.c,nuklear_text.c,nuklear_image.c,nuklear_9slice.c,nuklear_button.c,nuklear_toggle.c,nuklear_selectable.c,nuklear_slider.c,nuklear_knob.c,nuklear_progress.c,nuklear_scrollbar.c,nuklear_text_editor.c,nuklear_edit.c,nuklear_property.c,nuklear_chart.c,nuklear_color_picker.c,nuklear_combo.c,nuklear_tooltip.c --outro LICENSE,CHANGELOG,CREDITS > ../nuklear.h From 0964dd8e93d55d8792a787eb1c41e93bcf0a5c4f Mon Sep 17 00:00:00 2001 From: "Alexander W. Schultz" Date: Mon, 18 Nov 2024 12:15:52 -0500 Subject: [PATCH 05/10] feat[crc]: adds conditional compilation to CRC with NK_DRAW_BUFFER_CRC --- src/nuklear_context.c | 2 ++ src/nuklear_crc.c | 2 ++ src/nuklear_draw.c | 2 ++ src/nuklear_internal.h | 2 ++ 4 files changed, 8 insertions(+) diff --git a/src/nuklear_context.c b/src/nuklear_context.c index 59d5d4f9b..94340e1b0 100644 --- a/src/nuklear_context.c +++ b/src/nuklear_context.c @@ -117,7 +117,9 @@ nk_clear(struct nk_context *ctx) if (ctx->use_pool) nk_buffer_clear(&ctx->memory); else nk_buffer_reset(&ctx->memory, NK_BUFFER_FRONT); +#ifdef NK_DRAW_BUFFER_CRC nk_crc_clear(); /*clear the draw buffer crc*/ +#endif ctx->build = 0; ctx->memory.calls = 0; diff --git a/src/nuklear_crc.c b/src/nuklear_crc.c index e55beee77..0de8d70db 100644 --- a/src/nuklear_crc.c +++ b/src/nuklear_crc.c @@ -1,3 +1,4 @@ +#ifdef NK_DRAW_BUFFER_CRC #include "nuklear.h" #include "nuklear_internal.h" @@ -87,3 +88,4 @@ NK_API NK_UINT32 nk_buffer_crc() { return NK_BUFFER_CRC; } +#endif diff --git a/src/nuklear_draw.c b/src/nuklear_draw.c index a0d761113..4a77a3744 100644 --- a/src/nuklear_draw.c +++ b/src/nuklear_draw.c @@ -63,7 +63,9 @@ nk_command_buffer_push(struct nk_command_buffer* b, cmd->userdata = b->userdata; #endif b->end = cmd->next; +#ifdef NK_DRAW_BUFFER_CRC nk_crc_update((NK_UINT8*)cmd,size); +#endif return cmd; } NK_API void diff --git a/src/nuklear_internal.h b/src/nuklear_internal.h index 7bd30ed1a..b7fc4fe6d 100644 --- a/src/nuklear_internal.h +++ b/src/nuklear_internal.h @@ -126,8 +126,10 @@ NK_LIB nk_bool nk_is_lower(int c); NK_LIB nk_bool nk_is_upper(int c); NK_LIB int nk_to_upper(int c); NK_LIB int nk_to_lower(int c); +#ifdef NK_DRAW_BUFFER_CRC NK_LIB void nk_crc_update(NK_UINT8 *data, NK_SIZE_TYPE len); NK_LIB void nk_crc_clear(); +#endif #ifndef NK_MEMCPY NK_LIB void* nk_memcopy(void *dst, const void *src, nk_size n); From a2667eafd9f7ac5e1ac7ce28be47a8a05dcbcc66 Mon Sep 17 00:00:00 2001 From: "Alexander W. Schultz" Date: Mon, 18 Nov 2024 14:00:55 -0500 Subject: [PATCH 06/10] move crc to nk_command_buffer for thread safety --- src/nuklear.h | 3 +++ src/nuklear_context.c | 6 +++--- src/nuklear_crc.c | 15 +++++++-------- src/nuklear_draw.c | 2 +- src/nuklear_internal.h | 4 ++-- 5 files changed, 16 insertions(+), 14 deletions(-) diff --git a/src/nuklear.h b/src/nuklear.h index a76d384c1..4261719ac 100644 --- a/src/nuklear.h +++ b/src/nuklear.h @@ -4635,6 +4635,9 @@ struct nk_command_buffer { int use_clipping; nk_handle userdata; nk_size begin, end, last; +#ifdef NK_DRAW_BUFFER_CRC + NK_UINT32 crc; +#endif }; /** shape outlines */ diff --git a/src/nuklear_context.c b/src/nuklear_context.c index 94340e1b0..86c7561c4 100644 --- a/src/nuklear_context.c +++ b/src/nuklear_context.c @@ -117,15 +117,15 @@ nk_clear(struct nk_context *ctx) if (ctx->use_pool) nk_buffer_clear(&ctx->memory); else nk_buffer_reset(&ctx->memory, NK_BUFFER_FRONT); -#ifdef NK_DRAW_BUFFER_CRC - nk_crc_clear(); /*clear the draw buffer crc*/ -#endif ctx->build = 0; ctx->memory.calls = 0; ctx->last_widget_state = 0; ctx->style.cursor_active = ctx->style.cursors[NK_CURSOR_ARROW]; NK_MEMSET(&ctx->overlay, 0, sizeof(ctx->overlay)); +#ifdef NK_DRAW_BUFFER_CRC + nk_crc_clear(ctx->overlay); /*clear the draw buffer crc*/ +#endif /* garbage collector */ iter = ctx->begin; diff --git a/src/nuklear_crc.c b/src/nuklear_crc.c index 0de8d70db..6ac626d52 100644 --- a/src/nuklear_crc.c +++ b/src/nuklear_crc.c @@ -49,8 +49,6 @@ NK_STORAGE NK_UINT32 crc32c_table[] = { }; -#define NK_CRC_SEED 0xffffffff /**< seed value of the crc*/ -NK_GLOBAL NK_UINT32 NK_BUFFER_CRC = NK_CRC_SEED; /**< the CRC value of the command buffer.*/ /** * \brief steps the crc value by the amount of new data. @@ -65,9 +63,9 @@ NK_GLOBAL NK_UINT32 NK_BUFFER_CRC = NK_CRC_SEED; /**< the CRC value of the comma * \param[in] data is a pointer to the data to run the CRC on. * \param[in] len is the size in bytes of the data. */ -NK_LIB void nk_crc_update(NK_UINT8 *data, NK_SIZE_TYPE len) +NK_LIB void nk_crc_update(struct nk_command_buffer *buf, NK_UINT8 *data, NK_SIZE_TYPE len) { - while (len--) NK_BUFFER_CRC = (NK_BUFFER_CRC<<8) ^ crc32c_table[(NK_BUFFER_CRC >> 24) ^ *data++]; + while (len--) buf->crc = (buf->crc<<8) ^ crc32c_table[(buf->crc >> 24) ^ *data++]; } /** @@ -76,16 +74,17 @@ NK_LIB void nk_crc_update(NK_UINT8 *data, NK_SIZE_TYPE len) * \details * should be called on nk_clear such that the CRC can start over. */ -NK_LIB void nk_crc_clear() +NK_LIB void nk_crc_clear(struct nk_command_buffer *buf) { - NK_BUFFER_CRC = NK_CRC_SEED; +#define NK_CRC_SEED 0xffffffff /**< seed value of the crc*/ + buf->crc = NK_CRC_SEED; } /** * \brief returns the crc of the command buffer. */ -NK_API NK_UINT32 nk_buffer_crc() +NK_API NK_UINT32 nk_buffer_crc(struct nk_command_buffer *buf) { - return NK_BUFFER_CRC; + return buf->crc; } #endif diff --git a/src/nuklear_draw.c b/src/nuklear_draw.c index 4a77a3744..4b645c3af 100644 --- a/src/nuklear_draw.c +++ b/src/nuklear_draw.c @@ -64,7 +64,7 @@ nk_command_buffer_push(struct nk_command_buffer* b, #endif b->end = cmd->next; #ifdef NK_DRAW_BUFFER_CRC - nk_crc_update((NK_UINT8*)cmd,size); + nk_crc_update(b, (NK_UINT8*)cmd,size); #endif return cmd; } diff --git a/src/nuklear_internal.h b/src/nuklear_internal.h index b7fc4fe6d..1f9907bd3 100644 --- a/src/nuklear_internal.h +++ b/src/nuklear_internal.h @@ -127,8 +127,8 @@ NK_LIB nk_bool nk_is_upper(int c); NK_LIB int nk_to_upper(int c); NK_LIB int nk_to_lower(int c); #ifdef NK_DRAW_BUFFER_CRC -NK_LIB void nk_crc_update(NK_UINT8 *data, NK_SIZE_TYPE len); -NK_LIB void nk_crc_clear(); +NK_LIB void nk_crc_update(struct nk_command_buffer*, NK_UINT8 *data, NK_SIZE_TYPE len); +NK_LIB void nk_crc_clear(struct nk_command_buffer* ); #endif #ifndef NK_MEMCPY From 010262607c04d752ae519b66b8d540db6da54442 Mon Sep 17 00:00:00 2001 From: "Alexander W. Schultz" Date: Mon, 18 Nov 2024 14:22:20 -0500 Subject: [PATCH 07/10] rolled version number --- nuklear.h | 35 +++++++++++++++++++++++------------ src/CHANGELOG | 1 + 2 files changed, 24 insertions(+), 12 deletions(-) diff --git a/nuklear.h b/nuklear.h index 1321a4dba..94de42f34 100644 --- a/nuklear.h +++ b/nuklear.h @@ -4857,6 +4857,9 @@ struct nk_command_buffer { int use_clipping; nk_handle userdata; nk_size begin, end, last; +#ifdef NK_DRAW_BUFFER_CRC + NK_UINT32 crc; +#endif }; /** shape outlines */ @@ -6175,8 +6178,10 @@ NK_LIB nk_bool nk_is_lower(int c); NK_LIB nk_bool nk_is_upper(int c); NK_LIB int nk_to_upper(int c); NK_LIB int nk_to_lower(int c); -NK_LIB void nk_crc_update(NK_UINT8 *data, NK_SIZE_TYPE len); -NK_LIB void nk_crc_clear(); +#ifdef NK_DRAW_BUFFER_CRC +NK_LIB void nk_crc_update(struct nk_command_buffer*, NK_UINT8 *data, NK_SIZE_TYPE len); +NK_LIB void nk_crc_clear(struct nk_command_buffer* ); +#endif #ifndef NK_MEMCPY NK_LIB void* nk_memcopy(void *dst, const void *src, nk_size n); @@ -9271,7 +9276,9 @@ nk_command_buffer_push(struct nk_command_buffer* b, cmd->userdata = b->userdata; #endif b->end = cmd->next; - nk_crc_update((NK_UINT8*)cmd,size); +#ifdef NK_DRAW_BUFFER_CRC + nk_crc_update(b, (NK_UINT8*)cmd,size); +#endif return cmd; } NK_API void @@ -16808,6 +16815,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ------------------------------------------------------------------------------ */ +#ifdef NK_DRAW_BUFFER_CRC @@ -16858,8 +16866,6 @@ NK_STORAGE NK_UINT32 crc32c_table[] = { }; -#define NK_CRC_SEED 0xffffffff /**< seed value of the crc*/ -NK_GLOBAL NK_UINT32 NK_BUFFER_CRC = NK_CRC_SEED; /**< the CRC value of the command buffer.*/ /** * \brief steps the crc value by the amount of new data. @@ -16874,9 +16880,9 @@ NK_GLOBAL NK_UINT32 NK_BUFFER_CRC = NK_CRC_SEED; /**< the CRC value of the comma * \param[in] data is a pointer to the data to run the CRC on. * \param[in] len is the size in bytes of the data. */ -NK_LIB void nk_crc_update(NK_UINT8 *data, NK_SIZE_TYPE len) +NK_LIB void nk_crc_update(struct nk_command_buffer *buf, NK_UINT8 *data, NK_SIZE_TYPE len) { - while (len--) NK_BUFFER_CRC = (NK_BUFFER_CRC<<8) ^ crc32c_table[(NK_BUFFER_CRC >> 24) ^ *data++]; + while (len--) buf->crc = (buf->crc<<8) ^ crc32c_table[(buf->crc >> 24) ^ *data++]; } /** @@ -16885,18 +16891,20 @@ NK_LIB void nk_crc_update(NK_UINT8 *data, NK_SIZE_TYPE len) * \details * should be called on nk_clear such that the CRC can start over. */ -NK_LIB void nk_crc_clear() +NK_LIB void nk_crc_clear(struct nk_command_buffer *buf) { - NK_BUFFER_CRC = NK_CRC_SEED; +#define NK_CRC_SEED 0xffffffff /**< seed value of the crc*/ + buf->crc = NK_CRC_SEED; } /** * \brief returns the crc of the command buffer. */ -NK_API NK_UINT32 nk_buffer_crc() +NK_API NK_UINT32 nk_buffer_crc(struct nk_command_buffer *buf) { - return NK_BUFFER_CRC; + return buf->crc; } +#endif @@ -19539,13 +19547,15 @@ nk_clear(struct nk_context *ctx) if (ctx->use_pool) nk_buffer_clear(&ctx->memory); else nk_buffer_reset(&ctx->memory, NK_BUFFER_FRONT); - nk_crc_clear(); /*clear the draw buffer crc*/ ctx->build = 0; ctx->memory.calls = 0; ctx->last_widget_state = 0; ctx->style.cursor_active = ctx->style.cursors[NK_CURSOR_ARROW]; NK_MEMSET(&ctx->overlay, 0, sizeof(ctx->overlay)); +#ifdef NK_DRAW_BUFFER_CRC + nk_crc_clear(ctx->overlay); /*clear the draw buffer crc*/ +#endif /* garbage collector */ iter = ctx->begin; @@ -30792,6 +30802,7 @@ nk_tooltipfv(struct nk_context *ctx, const char *fmt, va_list args) /// - [y]: Minor version with non-breaking API and library changes /// - [z]: Patch version with no direct changes to the API /// +/// - 2024/11/18 (4.12.2) - Adds CRC check on draw command buffer /// - 2024/03/07 (4.12.1) - Fix bitwise operations warnings in C++20 /// - 2023/11/26 (4.12.0) - Added an alignment option to checkboxes and radio buttons. /// - 2023/10/11 (4.11.0) - Added nk_widget_disable_begin() and nk_widget_disable_end() diff --git a/src/CHANGELOG b/src/CHANGELOG index c301e319d..aeb779896 100644 --- a/src/CHANGELOG +++ b/src/CHANGELOG @@ -7,6 +7,7 @@ /// - [y]: Minor version with non-breaking API and library changes /// - [z]: Patch version with no direct changes to the API /// +/// - 2024/11/18 (4.12.2) - Adds CRC check on draw command buffer /// - 2024/03/07 (4.12.1) - Fix bitwise operations warnings in C++20 /// - 2023/11/26 (4.12.0) - Added an alignment option to checkboxes and radio buttons. /// - 2023/10/11 (4.11.0) - Added nk_widget_disable_begin() and nk_widget_disable_end() From 3a16fbc08d7b4fb5e4045bf955e1d5ad291f52f5 Mon Sep 17 00:00:00 2001 From: "Alexander W. Schultz" Date: Mon, 18 Nov 2024 21:50:30 -0500 Subject: [PATCH 08/10] feat[crc]: custom crc can now be provided by user. Also a huge documentation update for CRC. --- src/nuklear_crc.c | 99 ++++++++++++++++++++++++++++++++++++++++++++-- src/nuklear_draw.c | 4 +- 2 files changed, 97 insertions(+), 6 deletions(-) diff --git a/src/nuklear_crc.c b/src/nuklear_crc.c index 6ac626d52..acdb0fff5 100644 --- a/src/nuklear_crc.c +++ b/src/nuklear_crc.c @@ -1,4 +1,88 @@ +/** + * \file nuklear_crc.c + * \brief Implements CRC checking of the draw command buffer. + * + * \details Implements a rolling CRC that gets updated with every draw_push + * function call. That is, for every `nk_xxx` api function call between + * `nk_begin()` and `nk_end()` there is one to many draw commands pushed into + * the draw buffer. For each one of those pushes, the command type is XOR'd + * then stored into that buffer's CRC member. Then on the next `nk_xxx` function + * call, another command push is executed and the previous crc is updated with + * the new XOR of the new command. This will result in a unique CRC value in the + * buffers crc member at the end of the draw execution. + * + * The purpose of this is to allow super cheap and fast detection of unique'ness + * between draw loops, such that the user can determine if they need to redraw + * the screen or not. The original method was to have the user store a copy of + * the entire draw buffer, then loop through the buffer and compare that with + * the most recent draw buffer. Once done, you can determine if something + * changed on the screen and needs to be `nk_convert`'d. Doing it that way would + * require 1 loop to fill the command buffer, 1 loop to check the command buffer + * against the previously stored buffer, then 1 more loop to copy the new buffer + * into the old for the next draw loop iteration. That is 3 loops of + * `command_buffer'length()` which could end up being quite large; making this + * an expensive operation. Which almost defeats the purpose of detecting + * unique'ness in the first place. + * + * Yet implementing this CRC, we cruch all of that down into just the initial + * draw loop. Then you have a unique code stored in a 32-bit integer that + * represents the buffer. So if you need to know if the current draw command + * buffer is different from the previous one; you simply need to retain a single + * interger value and then check whether the old interger is equal to the new + * one. We reduced 3x O(n) loop complexity and 2x O(n) memory/space complexity + * down to 1x O(n) loop complexity and O(1) memory complexity. The CRC + * calculation (depending on default or custom implementation) simply adds 1 + * table lookup and 1 XOR operation to a single integer. Practically a free + * upgrade by comparison. + * + * If you want to use the CRC, then you must either `#define NK_DRAW_BUFFER_CRC` + * or `#define NK_DRAW_BUFFER_CRC_CUSTOM` + * + * `#define NK_DRAW_BUFFER_CRC` will implement the default CRC algorithm which is + * a 32 bit castagnoli (CRC-32C). This is a very common CRC that is used in + * iSCSI, SMPTE, ext-4, etc. So common that intel processors have dedicated + * hardware for it and lots of libraries have SIMD acceleration for it (not that + * its necessary for this application) + * + * `#define NK_DRAW_BUFFER_CRC_CUSTOM` will allow the user to define their own CRC + * implementation. This is available because most embedded systems already have + * a CRC calculation of some kind, usually defined by their system constraints, + * so it would be redundant to create yet another CRC method. + * + * To use the `NK_DRAW_BUFFER_CRC_CUSTOM` the user will need to `#define + * NK_CRC_SEED` to their desired seed and also `#define NK_CRC_FUNC(c,d,l)` to + * point to a user defined implementation of the crc. + * + * The user defined implementation of the CRC **SHALL** have the declaration of + * ```c + * NK_UINT32 (NK_UINT32 crc, NK_UINT8 *data, NK_SIZE_TYPE len) + * ``` + * That is, Shall : + * - return a 32 bit integer (the new CRC value) + * - accept, as the first argument, a 32 bit integer. The initial value of the crc. + * - accept, as the second argument, a pointer to a byte buffer to be CRC'd. + * - accept, as the third argument, the length of the byte buffer. + * + * other than that, the user is free to use any CRC algorithm, table, + * implementation they choose. + * + * \addtogroup crc + * \brief Command buffer CRC Implementation + * @{ + */ + +#ifdef NK_DRAW_BUFFER_CRC_CUSTOM +#ifndef NK_CRC_SEED +#error "Must #define NK_CRC_SEED when using NK_DRAW_BUFFER_CRC_CUSTOM" +#endif +#ifndef NK_CRC_FUNC(b,d,l) +#error "Must #define NK_CRC_FUNC(c,d,l) when using NK_DRAW_BUFFER_CRC_CUSTOM" +#endif +#endif + #ifdef NK_DRAW_BUFFER_CRC +#define NK_CRC_SEED 0xffffffff /**< seed value of the crc*/ +#define NK_CRC_FUNC(c,d,l) nk_crc_update(b, d, l) #include "nuklear.h" #include "nuklear_internal.h" @@ -60,31 +144,38 @@ NK_STORAGE NK_UINT32 crc32c_table[] = { * value. Never clearing will result is a proper CRC at the end of the drawing * updates. * + * \param[in] crc is the previous value of the CRC from which to build on. * \param[in] data is a pointer to the data to run the CRC on. * \param[in] len is the size in bytes of the data. + * + * \returns the new crc value */ -NK_LIB void nk_crc_update(struct nk_command_buffer *buf, NK_UINT8 *data, NK_SIZE_TYPE len) +NK_LIB NK_UINT32 nk_crc_update(NK_UINT32 crc, NK_UINT8 *data, NK_SIZE_TYPE len) { - while (len--) buf->crc = (buf->crc<<8) ^ crc32c_table[(buf->crc >> 24) ^ *data++]; + while (len--) crc = (crc<<8) ^ crc32c_table[(crc >> 24) ^ *data++]; + return crc; } +#endif /** * \brief re-initializes the command buffer crc. * * \details * should be called on nk_clear such that the CRC can start over. + * + * \param[in] buf is the command buffer for which crc to clear */ NK_LIB void nk_crc_clear(struct nk_command_buffer *buf) { -#define NK_CRC_SEED 0xffffffff /**< seed value of the crc*/ buf->crc = NK_CRC_SEED; } /** * \brief returns the crc of the command buffer. + * \param[in] buf is the command buffer for which crc to clear */ NK_API NK_UINT32 nk_buffer_crc(struct nk_command_buffer *buf) { return buf->crc; } -#endif +/** @} *//*end documentation grouping*/ diff --git a/src/nuklear_draw.c b/src/nuklear_draw.c index 4b645c3af..0fe5ebceb 100644 --- a/src/nuklear_draw.c +++ b/src/nuklear_draw.c @@ -63,8 +63,8 @@ nk_command_buffer_push(struct nk_command_buffer* b, cmd->userdata = b->userdata; #endif b->end = cmd->next; -#ifdef NK_DRAW_BUFFER_CRC - nk_crc_update(b, (NK_UINT8*)cmd,size); +#ifdef NK_DRAW_BUFFER_CRC || NK_DRAW_BUFFER_CRC_CUSTOM + b->crc = NK_CRC_FUNC(b->crc, (NK_UINT8*)cmd,size); #endif return cmd; } From f715d23811e0264ac56d1342512d25baf3ab3a53 Mon Sep 17 00:00:00 2001 From: "Alexander W. Schultz" Date: Mon, 18 Nov 2024 22:22:39 -0500 Subject: [PATCH 09/10] chore[crc]: fixes compilation issues --- nuklear.h | 291 +++++++++++++++++++++++++++-------------- src/nuklear.h | 2 +- src/nuklear_context.c | 4 +- src/nuklear_crc.c | 8 +- src/nuklear_draw.c | 2 +- src/nuklear_internal.h | 6 +- 6 files changed, 204 insertions(+), 109 deletions(-) diff --git a/nuklear.h b/nuklear.h index 94de42f34..eb189c9ee 100644 --- a/nuklear.h +++ b/nuklear.h @@ -4857,7 +4857,7 @@ struct nk_command_buffer { int use_clipping; nk_handle userdata; nk_size begin, end, last; -#ifdef NK_DRAW_BUFFER_CRC +#if defined( NK_DRAW_BUFFER_CRC) || defined( NK_DRAW_BUFFER_CRC_CUSTOM) NK_UINT32 crc; #endif }; @@ -6178,9 +6178,9 @@ NK_LIB nk_bool nk_is_lower(int c); NK_LIB nk_bool nk_is_upper(int c); NK_LIB int nk_to_upper(int c); NK_LIB int nk_to_lower(int c); -#ifdef NK_DRAW_BUFFER_CRC -NK_LIB void nk_crc_update(struct nk_command_buffer*, NK_UINT8 *data, NK_SIZE_TYPE len); -NK_LIB void nk_crc_clear(struct nk_command_buffer* ); +#if defined( NK_DRAW_BUFFER_CRC) || defined(NK_DRAW_BUFFER_CRC_CUSTOM) +NK_LIB NK_UINT32 nk_crc_update(NK_UINT32 crc, NK_UINT8 *data, NK_SIZE_TYPE len); +NK_LIB void nk_crc_clear(struct nk_command_buffer *buf); #endif #ifndef NK_MEMCPY @@ -9211,6 +9211,190 @@ nk_str_free(struct nk_str *str) str->len = 0; } +/** + * \file nuklear_crc.c + * \brief Implements CRC checking of the draw command buffer. + * + * \details Implements a rolling CRC that gets updated with every draw_push + * function call. That is, for every `nk_xxx` api function call between + * `nk_begin()` and `nk_end()` there is one to many draw commands pushed into + * the draw buffer. For each one of those pushes, the command type is XOR'd + * then stored into that buffer's CRC member. Then on the next `nk_xxx` function + * call, another command push is executed and the previous crc is updated with + * the new XOR of the new command. This will result in a unique CRC value in the + * buffers crc member at the end of the draw execution. + * + * The purpose of this is to allow super cheap and fast detection of unique'ness + * between draw loops, such that the user can determine if they need to redraw + * the screen or not. The original method was to have the user store a copy of + * the entire draw buffer, then loop through the buffer and compare that with + * the most recent draw buffer. Once done, you can determine if something + * changed on the screen and needs to be `nk_convert`'d. Doing it that way would + * require 1 loop to fill the command buffer, 1 loop to check the command buffer + * against the previously stored buffer, then 1 more loop to copy the new buffer + * into the old for the next draw loop iteration. That is 3 loops of + * `command_buffer'length()` which could end up being quite large; making this + * an expensive operation. Which almost defeats the purpose of detecting + * unique'ness in the first place. + * + * Yet implementing this CRC, we cruch all of that down into just the initial + * draw loop. Then you have a unique code stored in a 32-bit integer that + * represents the buffer. So if you need to know if the current draw command + * buffer is different from the previous one; you simply need to retain a single + * interger value and then check whether the old interger is equal to the new + * one. We reduced 3x O(n) loop complexity and 2x O(n) memory/space complexity + * down to 1x O(n) loop complexity and O(1) memory complexity. The CRC + * calculation (depending on default or custom implementation) simply adds 1 + * table lookup and 1 XOR operation to a single integer. Practically a free + * upgrade by comparison. + * + * If you want to use the CRC, then you must either `#define NK_DRAW_BUFFER_CRC` + * or `#define NK_DRAW_BUFFER_CRC_CUSTOM` + * + * `#define NK_DRAW_BUFFER_CRC` will implement the default CRC algorithm which is + * a 32 bit castagnoli (CRC-32C). This is a very common CRC that is used in + * iSCSI, SMPTE, ext-4, etc. So common that intel processors have dedicated + * hardware for it and lots of libraries have SIMD acceleration for it (not that + * its necessary for this application) + * + * `#define NK_DRAW_BUFFER_CRC_CUSTOM` will allow the user to define their own CRC + * implementation. This is available because most embedded systems already have + * a CRC calculation of some kind, usually defined by their system constraints, + * so it would be redundant to create yet another CRC method. + * + * To use the `NK_DRAW_BUFFER_CRC_CUSTOM` the user will need to `#define + * NK_CRC_SEED` to their desired seed and also `#define NK_CRC_FUNC(c,d,l)` to + * point to a user defined implementation of the crc. + * + * The user defined implementation of the CRC **SHALL** have the declaration of + * ```c + * NK_UINT32 (NK_UINT32 crc, NK_UINT8 *data, NK_SIZE_TYPE len) + * ``` + * That is, Shall : + * - return a 32 bit integer (the new CRC value) + * - accept, as the first argument, a 32 bit integer. The initial value of the crc. + * - accept, as the second argument, a pointer to a byte buffer to be CRC'd. + * - accept, as the third argument, the length of the byte buffer. + * + * other than that, the user is free to use any CRC algorithm, table, + * implementation they choose. + * + * \addtogroup crc + * \brief Command buffer CRC Implementation + * @{ + */ + +#ifdef NK_DRAW_BUFFER_CRC_CUSTOM +#ifndef NK_CRC_SEED +#error "Must #define NK_CRC_SEED when using NK_DRAW_BUFFER_CRC_CUSTOM" +#endif +#ifndef NK_CRC_FUNC(b,d,l) +#error "Must #define NK_CRC_FUNC(c,d,l) when using NK_DRAW_BUFFER_CRC_CUSTOM" +#endif +#endif + +#ifdef NK_DRAW_BUFFER_CRC +#define NK_CRC_SEED 0xffffffff /**< seed value of the crc*/ +#define NK_CRC_FUNC(c,d,l) nk_crc_update(c, d, l) + + + +NK_STORAGE NK_UINT32 crc32c_table[] = { + 0x00000000L, 0xF26B8303L, 0xE13B70F7L, 0x1350F3F4L, 0xC79A971FL, 0x35F1141CL, + 0x26A1E7E8L, 0xD4CA64EBL, 0x8AD958CFL, 0x78B2DBCCL, 0x6BE22838L, 0x9989AB3BL, + 0x4D43CFD0L, 0xBF284CD3L, 0xAC78BF27L, 0x5E133C24L, 0x105EC76FL, 0xE235446CL, + 0xF165B798L, 0x030E349BL, 0xD7C45070L, 0x25AFD373L, 0x36FF2087L, 0xC494A384L, + 0x9A879FA0L, 0x68EC1CA3L, 0x7BBCEF57L, 0x89D76C54L, 0x5D1D08BFL, 0xAF768BBCL, + 0xBC267848L, 0x4E4DFB4BL, 0x20BD8EDEL, 0xD2D60DDDL, 0xC186FE29L, 0x33ED7D2AL, + 0xE72719C1L, 0x154C9AC2L, 0x061C6936L, 0xF477EA35L, 0xAA64D611L, 0x580F5512L, + 0x4B5FA6E6L, 0xB93425E5L, 0x6DFE410EL, 0x9F95C20DL, 0x8CC531F9L, 0x7EAEB2FAL, + 0x30E349B1L, 0xC288CAB2L, 0xD1D83946L, 0x23B3BA45L, 0xF779DEAEL, 0x05125DADL, + 0x1642AE59L, 0xE4292D5AL, 0xBA3A117EL, 0x4851927DL, 0x5B016189L, 0xA96AE28AL, + 0x7DA08661L, 0x8FCB0562L, 0x9C9BF696L, 0x6EF07595L, 0x417B1DBCL, 0xB3109EBFL, + 0xA0406D4BL, 0x522BEE48L, 0x86E18AA3L, 0x748A09A0L, 0x67DAFA54L, 0x95B17957L, + 0xCBA24573L, 0x39C9C670L, 0x2A993584L, 0xD8F2B687L, 0x0C38D26CL, 0xFE53516FL, + 0xED03A29BL, 0x1F682198L, 0x5125DAD3L, 0xA34E59D0L, 0xB01EAA24L, 0x42752927L, + 0x96BF4DCCL, 0x64D4CECFL, 0x77843D3BL, 0x85EFBE38L, 0xDBFC821CL, 0x2997011FL, + 0x3AC7F2EBL, 0xC8AC71E8L, 0x1C661503L, 0xEE0D9600L, 0xFD5D65F4L, 0x0F36E6F7L, + 0x61C69362L, 0x93AD1061L, 0x80FDE395L, 0x72966096L, 0xA65C047DL, 0x5437877EL, + 0x4767748AL, 0xB50CF789L, 0xEB1FCBADL, 0x197448AEL, 0x0A24BB5AL, 0xF84F3859L, + 0x2C855CB2L, 0xDEEEDFB1L, 0xCDBE2C45L, 0x3FD5AF46L, 0x7198540DL, 0x83F3D70EL, + 0x90A324FAL, 0x62C8A7F9L, 0xB602C312L, 0x44694011L, 0x5739B3E5L, 0xA55230E6L, + 0xFB410CC2L, 0x092A8FC1L, 0x1A7A7C35L, 0xE811FF36L, 0x3CDB9BDDL, 0xCEB018DEL, + 0xDDE0EB2AL, 0x2F8B6829L, 0x82F63B78L, 0x709DB87BL, 0x63CD4B8FL, 0x91A6C88CL, + 0x456CAC67L, 0xB7072F64L, 0xA457DC90L, 0x563C5F93L, 0x082F63B7L, 0xFA44E0B4L, + 0xE9141340L, 0x1B7F9043L, 0xCFB5F4A8L, 0x3DDE77ABL, 0x2E8E845FL, 0xDCE5075CL, + 0x92A8FC17L, 0x60C37F14L, 0x73938CE0L, 0x81F80FE3L, 0x55326B08L, 0xA759E80BL, + 0xB4091BFFL, 0x466298FCL, 0x1871A4D8L, 0xEA1A27DBL, 0xF94AD42FL, 0x0B21572CL, + 0xDFEB33C7L, 0x2D80B0C4L, 0x3ED04330L, 0xCCBBC033L, 0xA24BB5A6L, 0x502036A5L, + 0x4370C551L, 0xB11B4652L, 0x65D122B9L, 0x97BAA1BAL, 0x84EA524EL, 0x7681D14DL, + 0x2892ED69L, 0xDAF96E6AL, 0xC9A99D9EL, 0x3BC21E9DL, 0xEF087A76L, 0x1D63F975L, + 0x0E330A81L, 0xFC588982L, 0xB21572C9L, 0x407EF1CAL, 0x532E023EL, 0xA145813DL, + 0x758FE5D6L, 0x87E466D5L, 0x94B49521L, 0x66DF1622L, 0x38CC2A06L, 0xCAA7A905L, + 0xD9F75AF1L, 0x2B9CD9F2L, 0xFF56BD19L, 0x0D3D3E1AL, 0x1E6DCDEEL, 0xEC064EEDL, + 0xC38D26C4L, 0x31E6A5C7L, 0x22B65633L, 0xD0DDD530L, 0x0417B1DBL, 0xF67C32D8L, + 0xE52CC12CL, 0x1747422FL, 0x49547E0BL, 0xBB3FFD08L, 0xA86F0EFCL, 0x5A048DFFL, + 0x8ECEE914L, 0x7CA56A17L, 0x6FF599E3L, 0x9D9E1AE0L, 0xD3D3E1ABL, 0x21B862A8L, + 0x32E8915CL, 0xC083125FL, 0x144976B4L, 0xE622F5B7L, 0xF5720643L, 0x07198540L, + 0x590AB964L, 0xAB613A67L, 0xB831C993L, 0x4A5A4A90L, 0x9E902E7BL, 0x6CFBAD78L, + 0x7FAB5E8CL, 0x8DC0DD8FL, 0xE330A81AL, 0x115B2B19L, 0x020BD8EDL, 0xF0605BEEL, + 0x24AA3F05L, 0xD6C1BC06L, 0xC5914FF2L, 0x37FACCF1L, 0x69E9F0D5L, 0x9B8273D6L, + 0x88D28022L, 0x7AB90321L, 0xAE7367CAL, 0x5C18E4C9L, 0x4F48173DL, 0xBD23943EL, + 0xF36E6F75L, 0x0105EC76L, 0x12551F82L, 0xE03E9C81L, 0x34F4F86AL, 0xC69F7B69L, + 0xD5CF889DL, 0x27A40B9EL, 0x79B737BAL, 0x8BDCB4B9L, 0x988C474DL, 0x6AE7C44EL, + 0xBE2DA0A5L, 0x4C4623A6L, 0x5F16D052L, 0xAD7D5351L +}; + + + +/** + * \brief steps the crc value by the amount of new data. + * + * \details + * this function should only be called in the nk_command_buffer_push() function + * and should only be given the `type` enum of the command being pushed. As the + * buffer is getting filled, this function will roll and calculate the CRC + * value. Never clearing will result is a proper CRC at the end of the drawing + * updates. + * + * \param[in] crc is the previous value of the CRC from which to build on. + * \param[in] data is a pointer to the data to run the CRC on. + * \param[in] len is the size in bytes of the data. + * + * \returns the new crc value + */ +NK_LIB NK_UINT32 nk_crc_update(NK_UINT32 crc, NK_UINT8 *data, NK_SIZE_TYPE len) +{ + while (len--) crc = (crc<<8) ^ crc32c_table[(crc >> 24) ^ *data++]; + return crc; +} +#endif + +#if defined(NK_DRAW_BUFFER_CRC) || defined(NK_DRAW_BUFFER_CRC_CUSTOM) +/** + * \brief re-initializes the command buffer crc. + * + * \details + * should be called on nk_clear such that the CRC can start over. + * + * \param[in] buf is the command buffer for which crc to clear + */ +NK_LIB void nk_crc_clear(struct nk_command_buffer *buf) +{ + buf->crc = NK_CRC_SEED; +} + +/** + * \brief returns the crc of the command buffer. + * \param[in] buf is the command buffer for which crc to clear + */ +NK_API NK_UINT32 nk_buffer_crc(struct nk_context *ctx) +{ + return ctx->overlay.crc; +} +/** @} *//*end documentation grouping*/ +#endif + @@ -9276,8 +9460,8 @@ nk_command_buffer_push(struct nk_command_buffer* b, cmd->userdata = b->userdata; #endif b->end = cmd->next; -#ifdef NK_DRAW_BUFFER_CRC - nk_crc_update(b, (NK_UINT8*)cmd,size); +#if defined(NK_DRAW_BUFFER_CRC) || defined(NK_DRAW_BUFFER_CRC_CUSTOM) + b->crc = NK_CRC_FUNC(b->crc, (NK_UINT8*)cmd,size); #endif return cmd; } @@ -16815,97 +16999,6 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ------------------------------------------------------------------------------ */ -#ifdef NK_DRAW_BUFFER_CRC - - - -NK_STORAGE NK_UINT32 crc32c_table[] = { - 0x00000000L, 0xF26B8303L, 0xE13B70F7L, 0x1350F3F4L, 0xC79A971FL, 0x35F1141CL, - 0x26A1E7E8L, 0xD4CA64EBL, 0x8AD958CFL, 0x78B2DBCCL, 0x6BE22838L, 0x9989AB3BL, - 0x4D43CFD0L, 0xBF284CD3L, 0xAC78BF27L, 0x5E133C24L, 0x105EC76FL, 0xE235446CL, - 0xF165B798L, 0x030E349BL, 0xD7C45070L, 0x25AFD373L, 0x36FF2087L, 0xC494A384L, - 0x9A879FA0L, 0x68EC1CA3L, 0x7BBCEF57L, 0x89D76C54L, 0x5D1D08BFL, 0xAF768BBCL, - 0xBC267848L, 0x4E4DFB4BL, 0x20BD8EDEL, 0xD2D60DDDL, 0xC186FE29L, 0x33ED7D2AL, - 0xE72719C1L, 0x154C9AC2L, 0x061C6936L, 0xF477EA35L, 0xAA64D611L, 0x580F5512L, - 0x4B5FA6E6L, 0xB93425E5L, 0x6DFE410EL, 0x9F95C20DL, 0x8CC531F9L, 0x7EAEB2FAL, - 0x30E349B1L, 0xC288CAB2L, 0xD1D83946L, 0x23B3BA45L, 0xF779DEAEL, 0x05125DADL, - 0x1642AE59L, 0xE4292D5AL, 0xBA3A117EL, 0x4851927DL, 0x5B016189L, 0xA96AE28AL, - 0x7DA08661L, 0x8FCB0562L, 0x9C9BF696L, 0x6EF07595L, 0x417B1DBCL, 0xB3109EBFL, - 0xA0406D4BL, 0x522BEE48L, 0x86E18AA3L, 0x748A09A0L, 0x67DAFA54L, 0x95B17957L, - 0xCBA24573L, 0x39C9C670L, 0x2A993584L, 0xD8F2B687L, 0x0C38D26CL, 0xFE53516FL, - 0xED03A29BL, 0x1F682198L, 0x5125DAD3L, 0xA34E59D0L, 0xB01EAA24L, 0x42752927L, - 0x96BF4DCCL, 0x64D4CECFL, 0x77843D3BL, 0x85EFBE38L, 0xDBFC821CL, 0x2997011FL, - 0x3AC7F2EBL, 0xC8AC71E8L, 0x1C661503L, 0xEE0D9600L, 0xFD5D65F4L, 0x0F36E6F7L, - 0x61C69362L, 0x93AD1061L, 0x80FDE395L, 0x72966096L, 0xA65C047DL, 0x5437877EL, - 0x4767748AL, 0xB50CF789L, 0xEB1FCBADL, 0x197448AEL, 0x0A24BB5AL, 0xF84F3859L, - 0x2C855CB2L, 0xDEEEDFB1L, 0xCDBE2C45L, 0x3FD5AF46L, 0x7198540DL, 0x83F3D70EL, - 0x90A324FAL, 0x62C8A7F9L, 0xB602C312L, 0x44694011L, 0x5739B3E5L, 0xA55230E6L, - 0xFB410CC2L, 0x092A8FC1L, 0x1A7A7C35L, 0xE811FF36L, 0x3CDB9BDDL, 0xCEB018DEL, - 0xDDE0EB2AL, 0x2F8B6829L, 0x82F63B78L, 0x709DB87BL, 0x63CD4B8FL, 0x91A6C88CL, - 0x456CAC67L, 0xB7072F64L, 0xA457DC90L, 0x563C5F93L, 0x082F63B7L, 0xFA44E0B4L, - 0xE9141340L, 0x1B7F9043L, 0xCFB5F4A8L, 0x3DDE77ABL, 0x2E8E845FL, 0xDCE5075CL, - 0x92A8FC17L, 0x60C37F14L, 0x73938CE0L, 0x81F80FE3L, 0x55326B08L, 0xA759E80BL, - 0xB4091BFFL, 0x466298FCL, 0x1871A4D8L, 0xEA1A27DBL, 0xF94AD42FL, 0x0B21572CL, - 0xDFEB33C7L, 0x2D80B0C4L, 0x3ED04330L, 0xCCBBC033L, 0xA24BB5A6L, 0x502036A5L, - 0x4370C551L, 0xB11B4652L, 0x65D122B9L, 0x97BAA1BAL, 0x84EA524EL, 0x7681D14DL, - 0x2892ED69L, 0xDAF96E6AL, 0xC9A99D9EL, 0x3BC21E9DL, 0xEF087A76L, 0x1D63F975L, - 0x0E330A81L, 0xFC588982L, 0xB21572C9L, 0x407EF1CAL, 0x532E023EL, 0xA145813DL, - 0x758FE5D6L, 0x87E466D5L, 0x94B49521L, 0x66DF1622L, 0x38CC2A06L, 0xCAA7A905L, - 0xD9F75AF1L, 0x2B9CD9F2L, 0xFF56BD19L, 0x0D3D3E1AL, 0x1E6DCDEEL, 0xEC064EEDL, - 0xC38D26C4L, 0x31E6A5C7L, 0x22B65633L, 0xD0DDD530L, 0x0417B1DBL, 0xF67C32D8L, - 0xE52CC12CL, 0x1747422FL, 0x49547E0BL, 0xBB3FFD08L, 0xA86F0EFCL, 0x5A048DFFL, - 0x8ECEE914L, 0x7CA56A17L, 0x6FF599E3L, 0x9D9E1AE0L, 0xD3D3E1ABL, 0x21B862A8L, - 0x32E8915CL, 0xC083125FL, 0x144976B4L, 0xE622F5B7L, 0xF5720643L, 0x07198540L, - 0x590AB964L, 0xAB613A67L, 0xB831C993L, 0x4A5A4A90L, 0x9E902E7BL, 0x6CFBAD78L, - 0x7FAB5E8CL, 0x8DC0DD8FL, 0xE330A81AL, 0x115B2B19L, 0x020BD8EDL, 0xF0605BEEL, - 0x24AA3F05L, 0xD6C1BC06L, 0xC5914FF2L, 0x37FACCF1L, 0x69E9F0D5L, 0x9B8273D6L, - 0x88D28022L, 0x7AB90321L, 0xAE7367CAL, 0x5C18E4C9L, 0x4F48173DL, 0xBD23943EL, - 0xF36E6F75L, 0x0105EC76L, 0x12551F82L, 0xE03E9C81L, 0x34F4F86AL, 0xC69F7B69L, - 0xD5CF889DL, 0x27A40B9EL, 0x79B737BAL, 0x8BDCB4B9L, 0x988C474DL, 0x6AE7C44EL, - 0xBE2DA0A5L, 0x4C4623A6L, 0x5F16D052L, 0xAD7D5351L -}; - - - -/** - * \brief steps the crc value by the amount of new data. - * - * \details - * this function should only be called in the nk_command_buffer_push() function - * and should only be given the `type` enum of the command being pushed. As the - * buffer is getting filled, this function will roll and calculate the CRC - * value. Never clearing will result is a proper CRC at the end of the drawing - * updates. - * - * \param[in] data is a pointer to the data to run the CRC on. - * \param[in] len is the size in bytes of the data. - */ -NK_LIB void nk_crc_update(struct nk_command_buffer *buf, NK_UINT8 *data, NK_SIZE_TYPE len) -{ - while (len--) buf->crc = (buf->crc<<8) ^ crc32c_table[(buf->crc >> 24) ^ *data++]; -} - -/** - * \brief re-initializes the command buffer crc. - * - * \details - * should be called on nk_clear such that the CRC can start over. - */ -NK_LIB void nk_crc_clear(struct nk_command_buffer *buf) -{ -#define NK_CRC_SEED 0xffffffff /**< seed value of the crc*/ - buf->crc = NK_CRC_SEED; -} - -/** - * \brief returns the crc of the command buffer. - */ -NK_API NK_UINT32 nk_buffer_crc(struct nk_command_buffer *buf) -{ - return buf->crc; -} -#endif - @@ -19553,8 +19646,8 @@ nk_clear(struct nk_context *ctx) ctx->last_widget_state = 0; ctx->style.cursor_active = ctx->style.cursors[NK_CURSOR_ARROW]; NK_MEMSET(&ctx->overlay, 0, sizeof(ctx->overlay)); -#ifdef NK_DRAW_BUFFER_CRC - nk_crc_clear(ctx->overlay); /*clear the draw buffer crc*/ +#if defined( NK_DRAW_BUFFER_CRC) || defined( NK_DRAW_BUFFER_CRC_CUSTOM) + nk_crc_clear(&ctx->overlay); /*clear the draw buffer crc*/ #endif /* garbage collector */ diff --git a/src/nuklear.h b/src/nuklear.h index 4261719ac..a0a6fc4a2 100644 --- a/src/nuklear.h +++ b/src/nuklear.h @@ -4635,7 +4635,7 @@ struct nk_command_buffer { int use_clipping; nk_handle userdata; nk_size begin, end, last; -#ifdef NK_DRAW_BUFFER_CRC +#if defined( NK_DRAW_BUFFER_CRC) || defined( NK_DRAW_BUFFER_CRC_CUSTOM) NK_UINT32 crc; #endif }; diff --git a/src/nuklear_context.c b/src/nuklear_context.c index 86c7561c4..9acf73d74 100644 --- a/src/nuklear_context.c +++ b/src/nuklear_context.c @@ -123,8 +123,8 @@ nk_clear(struct nk_context *ctx) ctx->last_widget_state = 0; ctx->style.cursor_active = ctx->style.cursors[NK_CURSOR_ARROW]; NK_MEMSET(&ctx->overlay, 0, sizeof(ctx->overlay)); -#ifdef NK_DRAW_BUFFER_CRC - nk_crc_clear(ctx->overlay); /*clear the draw buffer crc*/ +#if defined( NK_DRAW_BUFFER_CRC) || defined( NK_DRAW_BUFFER_CRC_CUSTOM) + nk_crc_clear(&ctx->overlay); /*clear the draw buffer crc*/ #endif /* garbage collector */ diff --git a/src/nuklear_crc.c b/src/nuklear_crc.c index acdb0fff5..d2e6c5b7e 100644 --- a/src/nuklear_crc.c +++ b/src/nuklear_crc.c @@ -82,7 +82,7 @@ #ifdef NK_DRAW_BUFFER_CRC #define NK_CRC_SEED 0xffffffff /**< seed value of the crc*/ -#define NK_CRC_FUNC(c,d,l) nk_crc_update(b, d, l) +#define NK_CRC_FUNC(c,d,l) nk_crc_update(c, d, l) #include "nuklear.h" #include "nuklear_internal.h" @@ -157,6 +157,7 @@ NK_LIB NK_UINT32 nk_crc_update(NK_UINT32 crc, NK_UINT8 *data, NK_SIZE_TYPE len) } #endif +#if defined(NK_DRAW_BUFFER_CRC) || defined(NK_DRAW_BUFFER_CRC_CUSTOM) /** * \brief re-initializes the command buffer crc. * @@ -174,8 +175,9 @@ NK_LIB void nk_crc_clear(struct nk_command_buffer *buf) * \brief returns the crc of the command buffer. * \param[in] buf is the command buffer for which crc to clear */ -NK_API NK_UINT32 nk_buffer_crc(struct nk_command_buffer *buf) +NK_API NK_UINT32 nk_buffer_crc(struct nk_context *ctx) { - return buf->crc; + return ctx->overlay.crc; } /** @} *//*end documentation grouping*/ +#endif diff --git a/src/nuklear_draw.c b/src/nuklear_draw.c index 0fe5ebceb..2099111d2 100644 --- a/src/nuklear_draw.c +++ b/src/nuklear_draw.c @@ -63,7 +63,7 @@ nk_command_buffer_push(struct nk_command_buffer* b, cmd->userdata = b->userdata; #endif b->end = cmd->next; -#ifdef NK_DRAW_BUFFER_CRC || NK_DRAW_BUFFER_CRC_CUSTOM +#if defined(NK_DRAW_BUFFER_CRC) || defined(NK_DRAW_BUFFER_CRC_CUSTOM) b->crc = NK_CRC_FUNC(b->crc, (NK_UINT8*)cmd,size); #endif return cmd; diff --git a/src/nuklear_internal.h b/src/nuklear_internal.h index 1f9907bd3..7607a805d 100644 --- a/src/nuklear_internal.h +++ b/src/nuklear_internal.h @@ -126,9 +126,9 @@ NK_LIB nk_bool nk_is_lower(int c); NK_LIB nk_bool nk_is_upper(int c); NK_LIB int nk_to_upper(int c); NK_LIB int nk_to_lower(int c); -#ifdef NK_DRAW_BUFFER_CRC -NK_LIB void nk_crc_update(struct nk_command_buffer*, NK_UINT8 *data, NK_SIZE_TYPE len); -NK_LIB void nk_crc_clear(struct nk_command_buffer* ); +#if defined( NK_DRAW_BUFFER_CRC) || defined(NK_DRAW_BUFFER_CRC_CUSTOM) +NK_LIB NK_UINT32 nk_crc_update(NK_UINT32 crc, NK_UINT8 *data, NK_SIZE_TYPE len); +NK_LIB void nk_crc_clear(struct nk_command_buffer *buf); #endif #ifndef NK_MEMCPY From 7acd29578da5f961b5ee1ecc04cf1753efc48ff9 Mon Sep 17 00:00:00 2001 From: "Alexander W. Schultz" Date: Tue, 19 Nov 2024 23:30:36 -0500 Subject: [PATCH 10/10] fix[crc]: CRC calculation work without breaking the demos. CRC calculations appear to be updating pretty well. however for panels that get drawn before others, there seems to be no change in CRC for small updates on hover, like highlighting an object as you mouse over it. Note that the CRC does change with highlights in the last panel that is rendered. More investigation is required. --- nuklear.h | 101 ++++++++++++++++++++++++++--------------- src/nuklear.h | 5 +- src/nuklear_context.c | 12 +++-- src/nuklear_crc.c | 74 ++++++++++++++++++------------ src/nuklear_draw.c | 2 +- src/nuklear_internal.h | 5 +- src/nuklear_window.c | 3 ++ src/paq.sh | 2 +- 8 files changed, 131 insertions(+), 73 deletions(-) diff --git a/nuklear.h b/nuklear.h index eb189c9ee..c254c59ba 100644 --- a/nuklear.h +++ b/nuklear.h @@ -4857,7 +4857,7 @@ struct nk_command_buffer { int use_clipping; nk_handle userdata; nk_size begin, end, last; -#if defined( NK_DRAW_BUFFER_CRC) || defined( NK_DRAW_BUFFER_CRC_CUSTOM) +#ifdef NK_DRAW_CRC NK_UINT32 crc; #endif }; @@ -5965,6 +5965,9 @@ struct nk_context { struct nk_page_element *freelist; unsigned int count; unsigned int seq; +#ifdef NK_DRAW_CRC + NK_UINT32 crc; +#endif }; /* ============================================================== @@ -6178,9 +6181,10 @@ NK_LIB nk_bool nk_is_lower(int c); NK_LIB nk_bool nk_is_upper(int c); NK_LIB int nk_to_upper(int c); NK_LIB int nk_to_lower(int c); -#if defined( NK_DRAW_BUFFER_CRC) || defined(NK_DRAW_BUFFER_CRC_CUSTOM) +#ifdef NK_DRAW_CRC +#ifndef NK_DRAW_CRC_CUSTOM NK_LIB NK_UINT32 nk_crc_update(NK_UINT32 crc, NK_UINT8 *data, NK_SIZE_TYPE len); -NK_LIB void nk_crc_clear(struct nk_command_buffer *buf); +#endif #endif #ifndef NK_MEMCPY @@ -9248,21 +9252,21 @@ nk_str_free(struct nk_str *str) * table lookup and 1 XOR operation to a single integer. Practically a free * upgrade by comparison. * - * If you want to use the CRC, then you must either `#define NK_DRAW_BUFFER_CRC` - * or `#define NK_DRAW_BUFFER_CRC_CUSTOM` + * If you want to use the CRC, then you must either `#define NK_DRAW_CRC` + * or `#define NK_DRAW_CRC_CUSTOM` * - * `#define NK_DRAW_BUFFER_CRC` will implement the default CRC algorithm which is + * `#define NK_DRAW_CRC` will implement the default CRC algorithm which is * a 32 bit castagnoli (CRC-32C). This is a very common CRC that is used in * iSCSI, SMPTE, ext-4, etc. So common that intel processors have dedicated * hardware for it and lots of libraries have SIMD acceleration for it (not that * its necessary for this application) * - * `#define NK_DRAW_BUFFER_CRC_CUSTOM` will allow the user to define their own CRC + * `#define NK_DRAW_CRC_CUSTOM` will allow the user to define their own CRC * implementation. This is available because most embedded systems already have * a CRC calculation of some kind, usually defined by their system constraints, * so it would be redundant to create yet another CRC method. * - * To use the `NK_DRAW_BUFFER_CRC_CUSTOM` the user will need to `#define + * To use the `NK_DRAW_CRC_CUSTOM` the user will need to `#define * NK_CRC_SEED` to their desired seed and also `#define NK_CRC_FUNC(c,d,l)` to * point to a user defined implementation of the crc. * @@ -9279,26 +9283,56 @@ nk_str_free(struct nk_str *str) * other than that, the user is free to use any CRC algorithm, table, * implementation they choose. * + * \internal + * Information for nuklear developers. Each context includes a command buffer + * for drawing, usually called `ctx->current->buffer`. This is the buffer with + * the draw commands and we grab the CRC value stored with this buffer + * `ctx->current->buffer.crc`. The buffer, in regards to a context, only exists + * to draw a panel and will _dissappear_ once `nk_end()` is called. This is + * because nk_end commits the draw buffer to the context's overal draw array and + * closes out the `current` buffer to wait for another `nk_begin()` to start a + * new panel using the `nk_buffer_start()` command. + * + * What this means for the CRC is that, when a user decides they want to check + * on the CRC, they will do so **after** the `nk_end()` call (because you need + * to make sure all of the information is there). But attempting to grab the CRC + * at `ctx->current->buffer.crc` will result in a Seg Fault because that memory + * was deallocated with the `nk_end()` call. But not only that, we determined + * that the `current->buffer` is meant to be used for all sequences of + * `nk_begin()` to `nk_end()`. Meaning that we will get new CRCs for each panel; + * but only be able to look at the final CRC (unless we grab them as we go, but + * thats silly when we just want to know whether to draw or not). That means we + * better hope the user only ever interacts with which ever panel was the final + * one drawn, otherwise we wont see a crc change. + * + * The solution was to store the CRC at the Context level. So now `struct + * nk_context` contains a `crc` member that gets rolled when the current buffer + * finishes (i.e. `nk_end()` was called). This means that, whenever + * `nk_finish` is called, we calc the context CRC based off the current buffer + * crc. This retains the CRC value through successive calls to `nk_begin()` and + * `nk_end()` and rolls the number appropriately. * \addtogroup crc * \brief Command buffer CRC Implementation * @{ */ -#ifdef NK_DRAW_BUFFER_CRC_CUSTOM +#ifdef NK_DRAW_CRC_CUSTOM #ifndef NK_CRC_SEED -#error "Must #define NK_CRC_SEED when using NK_DRAW_BUFFER_CRC_CUSTOM" +#error "Must #define NK_CRC_SEED when using NK_DRAW_CRC_CUSTOM" #endif #ifndef NK_CRC_FUNC(b,d,l) -#error "Must #define NK_CRC_FUNC(c,d,l) when using NK_DRAW_BUFFER_CRC_CUSTOM" +#error "Must #define NK_CRC_FUNC(c,d,l) when using NK_DRAW_CRC_CUSTOM" #endif +#define NK_DRAW_CRC #endif -#ifdef NK_DRAW_BUFFER_CRC +#ifdef NK_DRAW_CRC #define NK_CRC_SEED 0xffffffff /**< seed value of the crc*/ #define NK_CRC_FUNC(c,d,l) nk_crc_update(c, d, l) +#ifndef NK_DRAW_CRC_CUSTOM NK_STORAGE NK_UINT32 crc32c_table[] = { 0x00000000L, 0xF26B8303L, 0xE13B70F7L, 0x1350F3F4L, 0xC79A971FL, 0x35F1141CL, 0x26A1E7E8L, 0xD4CA64EBL, 0x8AD958CFL, 0x78B2DBCCL, 0x6BE22838L, 0x9989AB3BL, @@ -9345,6 +9379,7 @@ NK_STORAGE NK_UINT32 crc32c_table[] = { 0xBE2DA0A5L, 0x4C4623A6L, 0x5F16D052L, 0xAD7D5351L }; +#endif /** @@ -9368,32 +9403,17 @@ NK_LIB NK_UINT32 nk_crc_update(NK_UINT32 crc, NK_UINT8 *data, NK_SIZE_TYPE len) while (len--) crc = (crc<<8) ^ crc32c_table[(crc >> 24) ^ *data++]; return crc; } -#endif -#if defined(NK_DRAW_BUFFER_CRC) || defined(NK_DRAW_BUFFER_CRC_CUSTOM) /** - * \brief re-initializes the command buffer crc. - * - * \details - * should be called on nk_clear such that the CRC can start over. - * - * \param[in] buf is the command buffer for which crc to clear + * \brief returns the crc of the context + * \param[in] buf is the context for which to retrieve the CRC */ -NK_LIB void nk_crc_clear(struct nk_command_buffer *buf) +NK_API NK_UINT32 nk_get_crc(struct nk_context *ctx) { - buf->crc = NK_CRC_SEED; -} - -/** - * \brief returns the crc of the command buffer. - * \param[in] buf is the command buffer for which crc to clear - */ -NK_API NK_UINT32 nk_buffer_crc(struct nk_context *ctx) -{ - return ctx->overlay.crc; + return (ctx) ? ctx->crc : NK_CRC_SEED; } /** @} *//*end documentation grouping*/ -#endif +#endif /* NK_DRAW_CRC @@ -9460,7 +9480,7 @@ nk_command_buffer_push(struct nk_command_buffer* b, cmd->userdata = b->userdata; #endif b->end = cmd->next; -#if defined(NK_DRAW_BUFFER_CRC) || defined(NK_DRAW_BUFFER_CRC_CUSTOM) +#ifdef NK_DRAW_CRC b->crc = NK_CRC_FUNC(b->crc, (NK_UINT8*)cmd,size); #endif return cmd; @@ -19646,9 +19666,6 @@ nk_clear(struct nk_context *ctx) ctx->last_widget_state = 0; ctx->style.cursor_active = ctx->style.cursors[NK_CURSOR_ARROW]; NK_MEMSET(&ctx->overlay, 0, sizeof(ctx->overlay)); -#if defined( NK_DRAW_BUFFER_CRC) || defined( NK_DRAW_BUFFER_CRC_CUSTOM) - nk_crc_clear(&ctx->overlay); /*clear the draw buffer crc*/ -#endif /* garbage collector */ iter = ctx->begin; @@ -19696,6 +19713,9 @@ nk_clear(struct nk_context *ctx) iter = next; } else iter = iter->next; } +#ifdef NK_DRAW_CRC + ctx->crc = NK_CRC_SEED; +#endif ctx->seq++; } NK_LIB void @@ -19708,6 +19728,9 @@ nk_start_buffer(struct nk_context *ctx, struct nk_command_buffer *buffer) buffer->end = buffer->begin; buffer->last = buffer->begin; buffer->clip = nk_null_rect; +#ifdef NK_DRAW_CRC + buffer->crc = NK_CRC_SEED; +#endif } NK_LIB void nk_start(struct nk_context *ctx, struct nk_window *win) @@ -19762,6 +19785,9 @@ nk_finish(struct nk_context *ctx, struct nk_window *win) NK_ASSERT(ctx); NK_ASSERT(win); if (!ctx || !win) return; +#ifdef NK_DRAW_CRC + ctx->crc = NK_CRC_FUNC(ctx->crc, &win->buffer.crc, sizeof(win->buffer.crc)); +#endif nk_finish_buffer(ctx, &win->buffer); if (!win->popup.buf.active) return; @@ -21001,6 +21027,9 @@ nk_begin_titled(struct nk_context *ctx, const char *name, const char *title, } win->layout = (struct nk_panel*)nk_create_panel(ctx); ctx->current = win; +#ifdef NK_DRAW_CRC + ctx->crc = NK_CRC_SEED; +#endif ret = nk_panel_begin(ctx, title, NK_PANEL_WINDOW); win->layout->offset_x = &win->scrollbar.x; win->layout->offset_y = &win->scrollbar.y; diff --git a/src/nuklear.h b/src/nuklear.h index a0a6fc4a2..abedd8a5a 100644 --- a/src/nuklear.h +++ b/src/nuklear.h @@ -4635,7 +4635,7 @@ struct nk_command_buffer { int use_clipping; nk_handle userdata; nk_size begin, end, last; -#if defined( NK_DRAW_BUFFER_CRC) || defined( NK_DRAW_BUFFER_CRC_CUSTOM) +#ifdef NK_DRAW_CRC NK_UINT32 crc; #endif }; @@ -5743,6 +5743,9 @@ struct nk_context { struct nk_page_element *freelist; unsigned int count; unsigned int seq; +#ifdef NK_DRAW_CRC + NK_UINT32 crc; +#endif }; /* ============================================================== diff --git a/src/nuklear_context.c b/src/nuklear_context.c index 9acf73d74..e3646e9f5 100644 --- a/src/nuklear_context.c +++ b/src/nuklear_context.c @@ -123,9 +123,6 @@ nk_clear(struct nk_context *ctx) ctx->last_widget_state = 0; ctx->style.cursor_active = ctx->style.cursors[NK_CURSOR_ARROW]; NK_MEMSET(&ctx->overlay, 0, sizeof(ctx->overlay)); -#if defined( NK_DRAW_BUFFER_CRC) || defined( NK_DRAW_BUFFER_CRC_CUSTOM) - nk_crc_clear(&ctx->overlay); /*clear the draw buffer crc*/ -#endif /* garbage collector */ iter = ctx->begin; @@ -173,6 +170,9 @@ nk_clear(struct nk_context *ctx) iter = next; } else iter = iter->next; } +#ifdef NK_DRAW_CRC + ctx->crc = NK_CRC_SEED; +#endif ctx->seq++; } NK_LIB void @@ -185,6 +185,9 @@ nk_start_buffer(struct nk_context *ctx, struct nk_command_buffer *buffer) buffer->end = buffer->begin; buffer->last = buffer->begin; buffer->clip = nk_null_rect; +#ifdef NK_DRAW_CRC + buffer->crc = NK_CRC_SEED; +#endif } NK_LIB void nk_start(struct nk_context *ctx, struct nk_window *win) @@ -239,6 +242,9 @@ nk_finish(struct nk_context *ctx, struct nk_window *win) NK_ASSERT(ctx); NK_ASSERT(win); if (!ctx || !win) return; +#ifdef NK_DRAW_CRC + ctx->crc = NK_CRC_FUNC(ctx->crc, &win->buffer.crc, sizeof(win->buffer.crc)); +#endif nk_finish_buffer(ctx, &win->buffer); if (!win->popup.buf.active) return; diff --git a/src/nuklear_crc.c b/src/nuklear_crc.c index d2e6c5b7e..85d14ab43 100644 --- a/src/nuklear_crc.c +++ b/src/nuklear_crc.c @@ -35,21 +35,21 @@ * table lookup and 1 XOR operation to a single integer. Practically a free * upgrade by comparison. * - * If you want to use the CRC, then you must either `#define NK_DRAW_BUFFER_CRC` - * or `#define NK_DRAW_BUFFER_CRC_CUSTOM` + * If you want to use the CRC, then you must either `#define NK_DRAW_CRC` + * or `#define NK_DRAW_CRC_CUSTOM` * - * `#define NK_DRAW_BUFFER_CRC` will implement the default CRC algorithm which is + * `#define NK_DRAW_CRC` will implement the default CRC algorithm which is * a 32 bit castagnoli (CRC-32C). This is a very common CRC that is used in * iSCSI, SMPTE, ext-4, etc. So common that intel processors have dedicated * hardware for it and lots of libraries have SIMD acceleration for it (not that * its necessary for this application) * - * `#define NK_DRAW_BUFFER_CRC_CUSTOM` will allow the user to define their own CRC + * `#define NK_DRAW_CRC_CUSTOM` will allow the user to define their own CRC * implementation. This is available because most embedded systems already have * a CRC calculation of some kind, usually defined by their system constraints, * so it would be redundant to create yet another CRC method. * - * To use the `NK_DRAW_BUFFER_CRC_CUSTOM` the user will need to `#define + * To use the `NK_DRAW_CRC_CUSTOM` the user will need to `#define * NK_CRC_SEED` to their desired seed and also `#define NK_CRC_FUNC(c,d,l)` to * point to a user defined implementation of the crc. * @@ -66,26 +66,56 @@ * other than that, the user is free to use any CRC algorithm, table, * implementation they choose. * + * \internal + * Information for nuklear developers. Each context includes a command buffer + * for drawing, usually called `ctx->current->buffer`. This is the buffer with + * the draw commands and we grab the CRC value stored with this buffer + * `ctx->current->buffer.crc`. The buffer, in regards to a context, only exists + * to draw a panel and will _dissappear_ once `nk_end()` is called. This is + * because nk_end commits the draw buffer to the context's overal draw array and + * closes out the `current` buffer to wait for another `nk_begin()` to start a + * new panel using the `nk_buffer_start()` command. + * + * What this means for the CRC is that, when a user decides they want to check + * on the CRC, they will do so **after** the `nk_end()` call (because you need + * to make sure all of the information is there). But attempting to grab the CRC + * at `ctx->current->buffer.crc` will result in a Seg Fault because that memory + * was deallocated with the `nk_end()` call. But not only that, we determined + * that the `current->buffer` is meant to be used for all sequences of + * `nk_begin()` to `nk_end()`. Meaning that we will get new CRCs for each panel; + * but only be able to look at the final CRC (unless we grab them as we go, but + * thats silly when we just want to know whether to draw or not). That means we + * better hope the user only ever interacts with which ever panel was the final + * one drawn, otherwise we wont see a crc change. + * + * The solution was to store the CRC at the Context level. So now `struct + * nk_context` contains a `crc` member that gets rolled when the current buffer + * finishes (i.e. `nk_end()` was called). This means that, whenever + * `nk_finish` is called, we calc the context CRC based off the current buffer + * crc. This retains the CRC value through successive calls to `nk_begin()` and + * `nk_end()` and rolls the number appropriately. * \addtogroup crc * \brief Command buffer CRC Implementation * @{ */ -#ifdef NK_DRAW_BUFFER_CRC_CUSTOM +#ifdef NK_DRAW_CRC_CUSTOM #ifndef NK_CRC_SEED -#error "Must #define NK_CRC_SEED when using NK_DRAW_BUFFER_CRC_CUSTOM" +#error "Must #define NK_CRC_SEED when using NK_DRAW_CRC_CUSTOM" #endif #ifndef NK_CRC_FUNC(b,d,l) -#error "Must #define NK_CRC_FUNC(c,d,l) when using NK_DRAW_BUFFER_CRC_CUSTOM" +#error "Must #define NK_CRC_FUNC(c,d,l) when using NK_DRAW_CRC_CUSTOM" #endif +#define NK_DRAW_CRC #endif -#ifdef NK_DRAW_BUFFER_CRC +#ifdef NK_DRAW_CRC #define NK_CRC_SEED 0xffffffff /**< seed value of the crc*/ #define NK_CRC_FUNC(c,d,l) nk_crc_update(c, d, l) #include "nuklear.h" #include "nuklear_internal.h" +#ifndef NK_DRAW_CRC_CUSTOM NK_STORAGE NK_UINT32 crc32c_table[] = { 0x00000000L, 0xF26B8303L, 0xE13B70F7L, 0x1350F3F4L, 0xC79A971FL, 0x35F1141CL, 0x26A1E7E8L, 0xD4CA64EBL, 0x8AD958CFL, 0x78B2DBCCL, 0x6BE22838L, 0x9989AB3BL, @@ -132,6 +162,7 @@ NK_STORAGE NK_UINT32 crc32c_table[] = { 0xBE2DA0A5L, 0x4C4623A6L, 0x5F16D052L, 0xAD7D5351L }; +#endif /** @@ -155,29 +186,14 @@ NK_LIB NK_UINT32 nk_crc_update(NK_UINT32 crc, NK_UINT8 *data, NK_SIZE_TYPE len) while (len--) crc = (crc<<8) ^ crc32c_table[(crc >> 24) ^ *data++]; return crc; } -#endif -#if defined(NK_DRAW_BUFFER_CRC) || defined(NK_DRAW_BUFFER_CRC_CUSTOM) /** - * \brief re-initializes the command buffer crc. - * - * \details - * should be called on nk_clear such that the CRC can start over. - * - * \param[in] buf is the command buffer for which crc to clear + * \brief returns the crc of the context + * \param[in] buf is the context for which to retrieve the CRC */ -NK_LIB void nk_crc_clear(struct nk_command_buffer *buf) +NK_API NK_UINT32 nk_get_crc(struct nk_context *ctx) { - buf->crc = NK_CRC_SEED; -} - -/** - * \brief returns the crc of the command buffer. - * \param[in] buf is the command buffer for which crc to clear - */ -NK_API NK_UINT32 nk_buffer_crc(struct nk_context *ctx) -{ - return ctx->overlay.crc; + return (ctx) ? ctx->crc : NK_CRC_SEED; } /** @} *//*end documentation grouping*/ -#endif +#endif /* NK_DRAW_CRC diff --git a/src/nuklear_draw.c b/src/nuklear_draw.c index 2099111d2..76c4de367 100644 --- a/src/nuklear_draw.c +++ b/src/nuklear_draw.c @@ -63,7 +63,7 @@ nk_command_buffer_push(struct nk_command_buffer* b, cmd->userdata = b->userdata; #endif b->end = cmd->next; -#if defined(NK_DRAW_BUFFER_CRC) || defined(NK_DRAW_BUFFER_CRC_CUSTOM) +#ifdef NK_DRAW_CRC b->crc = NK_CRC_FUNC(b->crc, (NK_UINT8*)cmd,size); #endif return cmd; diff --git a/src/nuklear_internal.h b/src/nuklear_internal.h index 7607a805d..e81fecbdd 100644 --- a/src/nuklear_internal.h +++ b/src/nuklear_internal.h @@ -126,9 +126,10 @@ NK_LIB nk_bool nk_is_lower(int c); NK_LIB nk_bool nk_is_upper(int c); NK_LIB int nk_to_upper(int c); NK_LIB int nk_to_lower(int c); -#if defined( NK_DRAW_BUFFER_CRC) || defined(NK_DRAW_BUFFER_CRC_CUSTOM) +#ifdef NK_DRAW_CRC +#ifndef NK_DRAW_CRC_CUSTOM NK_LIB NK_UINT32 nk_crc_update(NK_UINT32 crc, NK_UINT8 *data, NK_SIZE_TYPE len); -NK_LIB void nk_crc_clear(struct nk_command_buffer *buf); +#endif #endif #ifndef NK_MEMCPY diff --git a/src/nuklear_window.c b/src/nuklear_window.c index 8c286e44e..e2ddec5d8 100644 --- a/src/nuklear_window.c +++ b/src/nuklear_window.c @@ -288,6 +288,9 @@ nk_begin_titled(struct nk_context *ctx, const char *name, const char *title, } win->layout = (struct nk_panel*)nk_create_panel(ctx); ctx->current = win; +#ifdef NK_DRAW_CRC + ctx->crc = NK_CRC_SEED; +#endif ret = nk_panel_begin(ctx, title, NK_PANEL_WINDOW); win->layout->offset_x = &win->scrollbar.x; win->layout->offset_y = &win->scrollbar.y; diff --git a/src/paq.sh b/src/paq.sh index b33a8d8c5..88f520fa3 100755 --- a/src/paq.sh +++ b/src/paq.sh @@ -1,2 +1,2 @@ #!/bin/sh -python3 build.py --macro NK --intro HEADER.md --pub nuklear.h --priv1 nuklear_internal.h,nuklear_math.c,nuklear_util.c,nuklear_color.c,nuklear_utf8.c,nuklear_buffer.c,nuklear_string.c,nuklear_draw.c,nuklear_vertex.c --extern stb_rect_pack.h,stb_truetype.h --priv2 nuklear_crc.c,nuklear_font.c,nuklear_input.c,nuklear_style.c,nuklear_context.c,nuklear_pool.c,nuklear_page_element.c,nuklear_table.c,nuklear_panel.c,nuklear_window.c,nuklear_popup.c,nuklear_contextual.c,nuklear_menu.c,nuklear_layout.c,nuklear_tree.c,nuklear_group.c,nuklear_list_view.c,nuklear_widget.c,nuklear_text.c,nuklear_image.c,nuklear_9slice.c,nuklear_button.c,nuklear_toggle.c,nuklear_selectable.c,nuklear_slider.c,nuklear_knob.c,nuklear_progress.c,nuklear_scrollbar.c,nuklear_text_editor.c,nuklear_edit.c,nuklear_property.c,nuklear_chart.c,nuklear_color_picker.c,nuklear_combo.c,nuklear_tooltip.c --outro LICENSE,CHANGELOG,CREDITS > ../nuklear.h +python3 build.py --macro NK --intro HEADER.md --pub nuklear.h --priv1 nuklear_internal.h,nuklear_math.c,nuklear_util.c,nuklear_color.c,nuklear_utf8.c,nuklear_buffer.c,nuklear_string.c,nuklear_crc.c,nuklear_draw.c,nuklear_vertex.c --extern stb_rect_pack.h,stb_truetype.h --priv2 nuklear_font.c,nuklear_input.c,nuklear_style.c,nuklear_context.c,nuklear_pool.c,nuklear_page_element.c,nuklear_table.c,nuklear_panel.c,nuklear_window.c,nuklear_popup.c,nuklear_contextual.c,nuklear_menu.c,nuklear_layout.c,nuklear_tree.c,nuklear_group.c,nuklear_list_view.c,nuklear_widget.c,nuklear_text.c,nuklear_image.c,nuklear_9slice.c,nuklear_button.c,nuklear_toggle.c,nuklear_selectable.c,nuklear_slider.c,nuklear_knob.c,nuklear_progress.c,nuklear_scrollbar.c,nuklear_text_editor.c,nuklear_edit.c,nuklear_property.c,nuklear_chart.c,nuklear_color_picker.c,nuklear_combo.c,nuklear_tooltip.c --outro LICENSE,CHANGELOG,CREDITS > ../nuklear.h