struct brush_solid_ALPHA_PASS_common { struct Samplers { sampler2D_impl sClipMask_impl; int sClipMask_slot; sampler2D_impl sGpuCache_impl; int sGpuCache_slot; sampler2D_impl sPrimitiveHeadersF_impl; int sPrimitiveHeadersF_slot; isampler2D_impl sPrimitiveHeadersI_impl; int sPrimitiveHeadersI_slot; sampler2D_impl sRenderTasks_impl; int sRenderTasks_slot; sampler2D_impl sTransformPalette_impl; int sTransformPalette_slot; bool set_slot(int index, int value) { switch (index) { case 7: sClipMask_slot = value; return true; case 2: sGpuCache_slot = value; return true; case 4: sPrimitiveHeadersF_slot = value; return true; case 5: sPrimitiveHeadersI_slot = value; return true; case 1: sRenderTasks_slot = value; return true; case 3: sTransformPalette_slot = value; return true; } return false; } } samplers; struct AttribLocations { int aPosition = NULL_ATTRIB; int aData = NULL_ATTRIB; void bind_loc(const char* name, int index) { if (strcmp("aPosition", name) == 0) { aPosition = index; return; } if (strcmp("aData", name) == 0) { aData = index; return; } } int get_loc(const char* name) const { if (strcmp("aPosition", name) == 0) { return aPosition != NULL_ATTRIB ? aPosition : -1; } if (strcmp("aData", name) == 0) { return aData != NULL_ATTRIB ? aData : -1; } return -1; } } attrib_locations; vec4_scalar vTransformBounds; vec4_scalar v_color; sampler2D sClipMask; sampler2D sGpuCache; sampler2D sPrimitiveHeadersF; isampler2D sPrimitiveHeadersI; sampler2D sRenderTasks; sampler2D sTransformPalette; mat4_scalar uTransform; void bind_textures() { sClipMask = lookup_sampler(&samplers.sClipMask_impl, samplers.sClipMask_slot); sGpuCache = lookup_sampler(&samplers.sGpuCache_impl, samplers.sGpuCache_slot); sPrimitiveHeadersF = lookup_sampler(&samplers.sPrimitiveHeadersF_impl, samplers.sPrimitiveHeadersF_slot); sPrimitiveHeadersI = lookup_isampler(&samplers.sPrimitiveHeadersI_impl, samplers.sPrimitiveHeadersI_slot); sRenderTasks = lookup_sampler(&samplers.sRenderTasks_impl, samplers.sRenderTasks_slot); sTransformPalette = lookup_sampler(&samplers.sTransformPalette_impl, samplers.sTransformPalette_slot); } }; struct brush_solid_ALPHA_PASS_vert : VertexShaderImpl, brush_solid_ALPHA_PASS_common { private: typedef brush_solid_ALPHA_PASS_vert Self; // int32_t uMode; // mat4_scalar uTransform; vec2 aPosition; struct RectWithSize_scalar { vec2_scalar p0; vec2_scalar size; RectWithSize_scalar() = default; RectWithSize_scalar(vec2_scalar p0, vec2_scalar size) : p0(p0), size(size){} }; struct RectWithSize { vec2 p0; vec2 size; RectWithSize() = default; RectWithSize(vec2 p0, vec2 size) : p0(p0), size(size){} RectWithSize(vec2_scalar p0, vec2_scalar size):p0(p0),size(size){ } IMPLICIT RectWithSize(RectWithSize_scalar s):p0(s.p0),size(s.size){ } friend RectWithSize if_then_else(I32 c, RectWithSize t, RectWithSize e) { return RectWithSize( if_then_else(c, t.p0, e.p0), if_then_else(c, t.size, e.size)); }}; struct RectWithEndpoint_scalar { vec2_scalar p0; vec2_scalar p1; RectWithEndpoint_scalar() = default; RectWithEndpoint_scalar(vec2_scalar p0, vec2_scalar p1) : p0(p0), p1(p1){} }; struct RectWithEndpoint { vec2 p0; vec2 p1; RectWithEndpoint() = default; RectWithEndpoint(vec2 p0, vec2 p1) : p0(p0), p1(p1){} RectWithEndpoint(vec2_scalar p0, vec2_scalar p1):p0(p0),p1(p1){ } IMPLICIT RectWithEndpoint(RectWithEndpoint_scalar s):p0(s.p0),p1(s.p1){ } friend RectWithEndpoint if_then_else(I32 c, RectWithEndpoint t, RectWithEndpoint e) { return RectWithEndpoint( if_then_else(c, t.p0, e.p0), if_then_else(c, t.p1, e.p1)); }}; // sampler2D sRenderTasks; struct RenderTaskData_scalar { RectWithEndpoint_scalar task_rect; vec4_scalar user_data; RenderTaskData_scalar() = default; RenderTaskData_scalar(RectWithEndpoint_scalar task_rect, vec4_scalar user_data) : task_rect(task_rect), user_data(user_data){} }; struct RenderTaskData { RectWithEndpoint task_rect; vec4 user_data; RenderTaskData() = default; RenderTaskData(RectWithEndpoint task_rect, vec4 user_data) : task_rect(task_rect), user_data(user_data){} RenderTaskData(RectWithEndpoint_scalar task_rect, vec4_scalar user_data):task_rect(task_rect),user_data(user_data){ } IMPLICIT RenderTaskData(RenderTaskData_scalar s):task_rect(s.task_rect),user_data(s.user_data){ } friend RenderTaskData if_then_else(I32 c, RenderTaskData t, RenderTaskData e) { return RenderTaskData( if_then_else(c, t.task_rect, e.task_rect), if_then_else(c, t.user_data, e.user_data)); }}; struct PictureTask_scalar { RectWithEndpoint_scalar task_rect; float device_pixel_scale; vec2_scalar content_origin; PictureTask_scalar() = default; PictureTask_scalar(RectWithEndpoint_scalar task_rect, float device_pixel_scale, vec2_scalar content_origin) : task_rect(task_rect), device_pixel_scale(device_pixel_scale), content_origin(content_origin){} }; struct PictureTask { RectWithEndpoint task_rect; Float device_pixel_scale; vec2 content_origin; PictureTask() = default; PictureTask(RectWithEndpoint task_rect, Float device_pixel_scale, vec2 content_origin) : task_rect(task_rect), device_pixel_scale(device_pixel_scale), content_origin(content_origin){} PictureTask(RectWithEndpoint_scalar task_rect, float device_pixel_scale, vec2_scalar content_origin):task_rect(task_rect),device_pixel_scale(device_pixel_scale),content_origin(content_origin){ } IMPLICIT PictureTask(PictureTask_scalar s):task_rect(s.task_rect),device_pixel_scale(s.device_pixel_scale),content_origin(s.content_origin){ } friend PictureTask if_then_else(I32 c, PictureTask t, PictureTask e) { return PictureTask( if_then_else(c, t.task_rect, e.task_rect), if_then_else(c, t.device_pixel_scale, e.device_pixel_scale), if_then_else(c, t.content_origin, e.content_origin)); }}; struct ClipArea_scalar { RectWithEndpoint_scalar task_rect; float device_pixel_scale; vec2_scalar screen_origin; ClipArea_scalar() = default; ClipArea_scalar(RectWithEndpoint_scalar task_rect, float device_pixel_scale, vec2_scalar screen_origin) : task_rect(task_rect), device_pixel_scale(device_pixel_scale), screen_origin(screen_origin){} }; struct ClipArea { RectWithEndpoint task_rect; Float device_pixel_scale; vec2 screen_origin; ClipArea() = default; ClipArea(RectWithEndpoint task_rect, Float device_pixel_scale, vec2 screen_origin) : task_rect(task_rect), device_pixel_scale(device_pixel_scale), screen_origin(screen_origin){} ClipArea(RectWithEndpoint_scalar task_rect, float device_pixel_scale, vec2_scalar screen_origin):task_rect(task_rect),device_pixel_scale(device_pixel_scale),screen_origin(screen_origin){ } IMPLICIT ClipArea(ClipArea_scalar s):task_rect(s.task_rect),device_pixel_scale(s.device_pixel_scale),screen_origin(s.screen_origin){ } friend ClipArea if_then_else(I32 c, ClipArea t, ClipArea e) { return ClipArea( if_then_else(c, t.task_rect, e.task_rect), if_then_else(c, t.device_pixel_scale, e.device_pixel_scale), if_then_else(c, t.screen_origin, e.screen_origin)); }}; // sampler2D sGpuCache; struct ImageSource_scalar { RectWithEndpoint_scalar uv_rect; vec4_scalar user_data; ImageSource_scalar() = default; ImageSource_scalar(RectWithEndpoint_scalar uv_rect, vec4_scalar user_data) : uv_rect(uv_rect), user_data(user_data){} }; struct ImageSource { RectWithEndpoint uv_rect; vec4 user_data; ImageSource() = default; ImageSource(RectWithEndpoint uv_rect, vec4 user_data) : uv_rect(uv_rect), user_data(user_data){} ImageSource(RectWithEndpoint_scalar uv_rect, vec4_scalar user_data):uv_rect(uv_rect),user_data(user_data){ } IMPLICIT ImageSource(ImageSource_scalar s):uv_rect(s.uv_rect),user_data(s.user_data){ } friend ImageSource if_then_else(I32 c, ImageSource t, ImageSource e) { return ImageSource( if_then_else(c, t.uv_rect, e.uv_rect), if_then_else(c, t.user_data, e.user_data)); }}; struct ImageSourceExtra_scalar { vec4_scalar st_tl; vec4_scalar st_tr; vec4_scalar st_bl; vec4_scalar st_br; ImageSourceExtra_scalar() = default; ImageSourceExtra_scalar(vec4_scalar st_tl, vec4_scalar st_tr, vec4_scalar st_bl, vec4_scalar st_br) : st_tl(st_tl), st_tr(st_tr), st_bl(st_bl), st_br(st_br){} }; struct ImageSourceExtra { vec4 st_tl; vec4 st_tr; vec4 st_bl; vec4 st_br; ImageSourceExtra() = default; ImageSourceExtra(vec4 st_tl, vec4 st_tr, vec4 st_bl, vec4 st_br) : st_tl(st_tl), st_tr(st_tr), st_bl(st_bl), st_br(st_br){} ImageSourceExtra(vec4_scalar st_tl, vec4_scalar st_tr, vec4_scalar st_bl, vec4_scalar st_br):st_tl(st_tl),st_tr(st_tr),st_bl(st_bl),st_br(st_br){ } IMPLICIT ImageSourceExtra(ImageSourceExtra_scalar s):st_tl(s.st_tl),st_tr(s.st_tr),st_bl(s.st_bl),st_br(s.st_br){ } friend ImageSourceExtra if_then_else(I32 c, ImageSourceExtra t, ImageSourceExtra e) { return ImageSourceExtra( if_then_else(c, t.st_tl, e.st_tl), if_then_else(c, t.st_tr, e.st_tr), if_then_else(c, t.st_bl, e.st_bl), if_then_else(c, t.st_br, e.st_br)); }}; // vec4_scalar vTransformBounds; // sampler2D sTransformPalette; struct Transform_scalar { mat4_scalar m; mat4_scalar inv_m; bool is_axis_aligned; Transform_scalar() = default; Transform_scalar(mat4_scalar m, mat4_scalar inv_m, bool is_axis_aligned) : m(m), inv_m(inv_m), is_axis_aligned(is_axis_aligned){} }; struct Transform { mat4 m; mat4 inv_m; Bool is_axis_aligned; Transform() = default; Transform(mat4 m, mat4 inv_m, Bool is_axis_aligned) : m(m), inv_m(inv_m), is_axis_aligned(is_axis_aligned){} Transform(mat4_scalar m, mat4_scalar inv_m, bool is_axis_aligned):m(m),inv_m(inv_m),is_axis_aligned(is_axis_aligned){ } IMPLICIT Transform(Transform_scalar s):m(s.m),inv_m(s.inv_m),is_axis_aligned(s.is_axis_aligned){ } friend Transform if_then_else(I32 c, Transform t, Transform e) { return Transform( if_then_else(c, t.m, e.m), if_then_else(c, t.inv_m, e.inv_m), if_then_else(c, t.is_axis_aligned, e.is_axis_aligned)); }}; // sampler2D sClipMask; // sampler2D sPrimitiveHeadersF; // isampler2D sPrimitiveHeadersI; ivec4_scalar aData; struct Instance_scalar { int32_t prim_header_address; int32_t picture_task_address; int32_t clip_address; int32_t segment_index; int32_t flags; int32_t resource_address; int32_t brush_kind; Instance_scalar() = default; Instance_scalar(int32_t prim_header_address, int32_t picture_task_address, int32_t clip_address, int32_t segment_index, int32_t flags, int32_t resource_address, int32_t brush_kind) : prim_header_address(prim_header_address), picture_task_address(picture_task_address), clip_address(clip_address), segment_index(segment_index), flags(flags), resource_address(resource_address), brush_kind(brush_kind){} }; struct Instance { I32 prim_header_address; I32 picture_task_address; I32 clip_address; I32 segment_index; I32 flags; I32 resource_address; I32 brush_kind; Instance() = default; Instance(I32 prim_header_address, I32 picture_task_address, I32 clip_address, I32 segment_index, I32 flags, I32 resource_address, I32 brush_kind) : prim_header_address(prim_header_address), picture_task_address(picture_task_address), clip_address(clip_address), segment_index(segment_index), flags(flags), resource_address(resource_address), brush_kind(brush_kind){} Instance(int32_t prim_header_address, int32_t picture_task_address, int32_t clip_address, int32_t segment_index, int32_t flags, int32_t resource_address, int32_t brush_kind):prim_header_address(prim_header_address),picture_task_address(picture_task_address),clip_address(clip_address),segment_index(segment_index),flags(flags),resource_address(resource_address),brush_kind(brush_kind){ } IMPLICIT Instance(Instance_scalar s):prim_header_address(s.prim_header_address),picture_task_address(s.picture_task_address),clip_address(s.clip_address),segment_index(s.segment_index),flags(s.flags),resource_address(s.resource_address),brush_kind(s.brush_kind){ } friend Instance if_then_else(I32 c, Instance t, Instance e) { return Instance( if_then_else(c, t.prim_header_address, e.prim_header_address), if_then_else(c, t.picture_task_address, e.picture_task_address), if_then_else(c, t.clip_address, e.clip_address), if_then_else(c, t.segment_index, e.segment_index), if_then_else(c, t.flags, e.flags), if_then_else(c, t.resource_address, e.resource_address), if_then_else(c, t.brush_kind, e.brush_kind)); }}; struct PrimitiveHeader_scalar { RectWithEndpoint_scalar local_rect; RectWithEndpoint_scalar local_clip_rect; float z; int32_t specific_prim_address; int32_t transform_id; ivec4_scalar user_data; PrimitiveHeader_scalar() = default; PrimitiveHeader_scalar(RectWithEndpoint_scalar local_rect, RectWithEndpoint_scalar local_clip_rect, float z, int32_t specific_prim_address, int32_t transform_id, ivec4_scalar user_data) : local_rect(local_rect), local_clip_rect(local_clip_rect), z(z), specific_prim_address(specific_prim_address), transform_id(transform_id), user_data(user_data){} }; struct PrimitiveHeader { RectWithEndpoint local_rect; RectWithEndpoint local_clip_rect; Float z; I32 specific_prim_address; I32 transform_id; ivec4 user_data; PrimitiveHeader() = default; PrimitiveHeader(RectWithEndpoint local_rect, RectWithEndpoint local_clip_rect, Float z, I32 specific_prim_address, I32 transform_id, ivec4 user_data) : local_rect(local_rect), local_clip_rect(local_clip_rect), z(z), specific_prim_address(specific_prim_address), transform_id(transform_id), user_data(user_data){} PrimitiveHeader(RectWithEndpoint_scalar local_rect, RectWithEndpoint_scalar local_clip_rect, float z, int32_t specific_prim_address, int32_t transform_id, ivec4_scalar user_data):local_rect(local_rect),local_clip_rect(local_clip_rect),z(z),specific_prim_address(specific_prim_address),transform_id(transform_id),user_data(user_data){ } IMPLICIT PrimitiveHeader(PrimitiveHeader_scalar s):local_rect(s.local_rect),local_clip_rect(s.local_clip_rect),z(s.z),specific_prim_address(s.specific_prim_address),transform_id(s.transform_id),user_data(s.user_data){ } friend PrimitiveHeader if_then_else(I32 c, PrimitiveHeader t, PrimitiveHeader e) { return PrimitiveHeader( if_then_else(c, t.local_rect, e.local_rect), if_then_else(c, t.local_clip_rect, e.local_clip_rect), if_then_else(c, t.z, e.z), if_then_else(c, t.specific_prim_address, e.specific_prim_address), if_then_else(c, t.transform_id, e.transform_id), if_then_else(c, t.user_data, e.user_data)); }}; struct VertexInfo_scalar { vec2_scalar local_pos; vec4_scalar world_pos; VertexInfo_scalar() = default; VertexInfo_scalar(vec2_scalar local_pos, vec4_scalar world_pos) : local_pos(local_pos), world_pos(world_pos){} }; struct VertexInfo { vec2 local_pos; vec4 world_pos; VertexInfo() = default; VertexInfo(vec2 local_pos, vec4 world_pos) : local_pos(local_pos), world_pos(world_pos){} VertexInfo(vec2_scalar local_pos, vec4_scalar world_pos):local_pos(local_pos),world_pos(world_pos){ } IMPLICIT VertexInfo(VertexInfo_scalar s):local_pos(s.local_pos),world_pos(s.world_pos){ } friend VertexInfo if_then_else(I32 c, VertexInfo t, VertexInfo e) { return VertexInfo( if_then_else(c, t.local_pos, e.local_pos), if_then_else(c, t.world_pos, e.world_pos)); }}; // vec4_scalar v_color; struct SolidBrush_scalar { vec4_scalar color; SolidBrush_scalar() = default; explicit SolidBrush_scalar(vec4_scalar color) : color(color){} }; struct SolidBrush { vec4 color; SolidBrush() = default; explicit SolidBrush(vec4 color) : color(color){} explicit SolidBrush(vec4_scalar color):color(color){ } IMPLICIT SolidBrush(SolidBrush_scalar s):color(s.color){ } friend SolidBrush if_then_else(I32 c, SolidBrush t, SolidBrush e) { return SolidBrush( if_then_else(c, t.color, e.color)); }}; Instance_scalar decode_instance_attributes() { Instance_scalar instance; (instance).prim_header_address = (aData).sel(X); (instance).picture_task_address = ((aData).sel(Y))>>(16); (instance).clip_address = ((aData).sel(Y))&(65535); (instance).segment_index = ((aData).sel(Z))&(65535); (instance).flags = ((aData).sel(Z))>>(16); (instance).resource_address = ((aData).sel(W))&(16777215); (instance).brush_kind = ((aData).sel(W))>>(24); return instance; } PrimitiveHeader_scalar fetch_prim_header(int32_t index) { PrimitiveHeader_scalar ph; ivec2_scalar uv_f = make_ivec2(make_int((2u)*((make_uint(index))%((1024u)/(2u)))), make_int((make_uint(index))/((1024u)/(2u)))); vec4_scalar* sPrimitiveHeadersF_uv_f_fetch = texelFetchPtr(sPrimitiveHeadersF, uv_f, 0, 1, 0, 0); vec4_scalar local_rect = texelFetchUnchecked(sPrimitiveHeadersF, sPrimitiveHeadersF_uv_f_fetch, 0, 0); vec4_scalar local_clip_rect = texelFetchUnchecked(sPrimitiveHeadersF, sPrimitiveHeadersF_uv_f_fetch, 1, 0); (ph).local_rect = RectWithEndpoint_scalar((local_rect).sel(X, Y), (local_rect).sel(Z, W)); (ph).local_clip_rect = RectWithEndpoint_scalar((local_clip_rect).sel(X, Y), (local_clip_rect).sel(Z, W)); ivec2_scalar uv_i = make_ivec2(make_int((2u)*((make_uint(index))%((1024u)/(2u)))), make_int((make_uint(index))/((1024u)/(2u)))); ivec4_scalar* sPrimitiveHeadersI_uv_i_fetch = texelFetchPtr(sPrimitiveHeadersI, uv_i, 0, 1, 0, 0); ivec4_scalar data0 = texelFetchUnchecked(sPrimitiveHeadersI, sPrimitiveHeadersI_uv_i_fetch, 0, 0); ivec4_scalar data1 = texelFetchUnchecked(sPrimitiveHeadersI, sPrimitiveHeadersI_uv_i_fetch, 1, 0); (ph).z = make_float((data0).sel(X)); (ph).specific_prim_address = (data0).sel(Y); (ph).transform_id = (data0).sel(Z); (ph).user_data = data1; return ph; } Transform_scalar fetch_transform(int32_t id) { Transform_scalar transform; (transform).is_axis_aligned = ((id)>>(24))==(0); int32_t index = (id)&(16777215); ivec2_scalar uv = make_ivec2(make_int((8u)*((make_uint(index))%((1024u)/(8u)))), make_int((make_uint(index))/((1024u)/(8u)))); ivec2_scalar uv0 = make_ivec2(((uv).sel(X))+(0), (uv).sel(Y)); vec4_scalar* sTransformPalette_uv0_fetch = texelFetchPtr(sTransformPalette, uv0, 0, 7, 0, 0); (transform).m[0] = texelFetchUnchecked(sTransformPalette, sTransformPalette_uv0_fetch, 0, 0); (transform).m[1] = texelFetchUnchecked(sTransformPalette, sTransformPalette_uv0_fetch, 1, 0); (transform).m[2] = texelFetchUnchecked(sTransformPalette, sTransformPalette_uv0_fetch, 2, 0); (transform).m[3] = texelFetchUnchecked(sTransformPalette, sTransformPalette_uv0_fetch, 3, 0); (transform).inv_m[0] = texelFetchUnchecked(sTransformPalette, sTransformPalette_uv0_fetch, 4, 0); (transform).inv_m[1] = texelFetchUnchecked(sTransformPalette, sTransformPalette_uv0_fetch, 5, 0); (transform).inv_m[2] = texelFetchUnchecked(sTransformPalette, sTransformPalette_uv0_fetch, 6, 0); (transform).inv_m[3] = texelFetchUnchecked(sTransformPalette, sTransformPalette_uv0_fetch, 7, 0); return transform; } RenderTaskData_scalar fetch_render_task_data(int32_t index) { ivec2_scalar uv = make_ivec2(make_int((2u)*((make_uint(index))%((1024u)/(2u)))), make_int((make_uint(index))/((1024u)/(2u)))); vec4_scalar* sRenderTasks_uv_fetch = texelFetchPtr(sRenderTasks, uv, 0, 1, 0, 0); vec4_scalar texel0 = texelFetchUnchecked(sRenderTasks, sRenderTasks_uv_fetch, 0, 0); vec4_scalar texel1 = texelFetchUnchecked(sRenderTasks, sRenderTasks_uv_fetch, 1, 0); RectWithEndpoint_scalar task_rect = RectWithEndpoint_scalar((texel0).sel(X, Y), (texel0).sel(Z, W)); RenderTaskData_scalar data = RenderTaskData_scalar(task_rect, texel1); return data; } PictureTask_scalar fetch_picture_task(int32_t address) { RenderTaskData_scalar task_data = fetch_render_task_data(address); PictureTask_scalar task = PictureTask_scalar((task_data).task_rect, ((task_data).user_data).sel(X), ((task_data).user_data).sel(Y, Z)); return task; } ClipArea_scalar fetch_clip_area(int32_t index) { ClipArea_scalar area; if ((index)>=(32767)) { { (area).task_rect = RectWithEndpoint_scalar(make_vec2(0.f), make_vec2(0.f)); (area).device_pixel_scale = 0.f; (area).screen_origin = make_vec2(0.f); } } else { RenderTaskData_scalar task_data = fetch_render_task_data(index); (area).task_rect = (task_data).task_rect; (area).device_pixel_scale = ((task_data).user_data).sel(X); (area).screen_origin = ((task_data).user_data).sel(Y, Z); } return area; } ivec2_scalar get_gpu_cache_uv(int32_t address) { return make_ivec2((make_uint(address))%(1024u), (make_uint(address))/(1024u)); } Array fetch_from_gpu_cache_2(int32_t address) { ivec2_scalar uv = get_gpu_cache_uv(address); vec4_scalar* sGpuCache_uv_fetch = texelFetchPtr(sGpuCache, uv, 0, 1, 0, 0); return Array{{texelFetchUnchecked(sGpuCache, sGpuCache_uv_fetch, 0, 0), texelFetchUnchecked(sGpuCache, sGpuCache_uv_fetch, 1, 0)}}; } vec2 rect_clamp(RectWithEndpoint_scalar rect, vec2 pt) { return clamp(pt, (rect).p0, (rect).p1); } VertexInfo write_vertex(vec2 local_pos, RectWithEndpoint_scalar local_clip_rect, float z, Transform_scalar transform, PictureTask_scalar task) { vec2 clamped_local_pos = rect_clamp(local_clip_rect, local_pos); vec4 world_pos = ((transform).m)*(make_vec4(clamped_local_pos, 0.f, 1.f)); vec2 device_pos = ((world_pos).sel(X, Y))*((task).device_pixel_scale); vec2_scalar final_offset = (-((task).content_origin))+(((task).task_rect).p0); gl_Position = (uTransform)*(make_vec4((device_pos)+((final_offset)*((world_pos).sel(W))), (z)*((world_pos).sel(W)), (world_pos).sel(W))); VertexInfo vi = VertexInfo(clamped_local_pos, world_pos); return vi; } VertexInfo write_transform_vertex(RectWithEndpoint_scalar local_segment_rect, RectWithEndpoint_scalar local_prim_rect, RectWithEndpoint_scalar local_clip_rect, int32_t edge_flags, float z, Transform_scalar transform, PictureTask_scalar task) { RectWithEndpoint_scalar clip_rect = local_clip_rect; RectWithEndpoint_scalar segment_rect = local_segment_rect; bvec4_scalar clipped = make_bvec4(greaterThan((clip_rect).p0, (segment_rect).p0), lessThan((clip_rect).p1, (segment_rect).p1)); swgl_antiAlias((edge_flags)|(((clipped).sel(X) ? 1 : 0)|(((clipped).sel(Y) ? 2 : 0)|(((clipped).sel(Z) ? 4 : 0)|((clipped).sel(W) ? 8 : 0))))); (segment_rect).p0 = clamp((segment_rect).p0, (clip_rect).p0, (clip_rect).p1); (segment_rect).p1 = clamp((segment_rect).p1, (clip_rect).p0, (clip_rect).p1); local_segment_rect = segment_rect; vec2 local_pos = mix((local_segment_rect).p0, (local_segment_rect).p1, (aPosition).sel(X, Y)); vec2_scalar task_offset = (((task).task_rect).p0)-((task).content_origin); vec4 world_pos = ((transform).m)*(make_vec4(local_pos, 0.f, 1.f)); vec4 final_pos = make_vec4((((world_pos).sel(X, Y))*((task).device_pixel_scale))+((task_offset)*((world_pos).sel(W))), (z)*((world_pos).sel(W)), (world_pos).sel(W)); gl_Position = (uTransform)*(final_pos); VertexInfo vi = VertexInfo(local_pos, world_pos); return vi; } vec2_scalar rect_size(RectWithEndpoint_scalar rect) { return ((rect).p1)-((rect).p0); } void write_clip(vec4 world_pos, ClipArea_scalar area, PictureTask_scalar task) { swgl_clipMask(sClipMask, ((((task).task_rect).p0)-((task).content_origin))-((((area).task_rect).p0)-((area).screen_origin)), ((area).task_rect).p0, rect_size((area).task_rect)); } vec4_scalar fetch_from_gpu_cache_1(int32_t address) { ivec2_scalar uv = get_gpu_cache_uv(address); return texelFetch(sGpuCache, uv, 0); } SolidBrush_scalar fetch_solid_primitive(int32_t address) { vec4_scalar data = fetch_from_gpu_cache_1(address); return SolidBrush_scalar(data); } void brush_vs(VertexInfo vi, int32_t prim_address, RectWithEndpoint_scalar local_rect, RectWithEndpoint_scalar segment_rect, ivec4_scalar prim_user_data, int32_t specific_resource_address, mat4_scalar transform, PictureTask_scalar pic_task, int32_t brush_flags, vec4_scalar unused) { SolidBrush_scalar prim = fetch_solid_primitive(prim_address); float opacity = (make_float((prim_user_data).sel(X)))/(65535.f); v_color = ((prim).color)*(opacity); } void brush_shader_main_vs(Instance_scalar instance, PrimitiveHeader_scalar ph, Transform_scalar transform, PictureTask_scalar pic_task, ClipArea_scalar clip_area) { int32_t edge_flags = ((instance).flags)&(255); int32_t brush_flags = (((instance).flags)>>(8))&(255); vec4_scalar segment_data; RectWithEndpoint_scalar segment_rect; if (((instance).segment_index)==(65535)) { { segment_rect = (ph).local_rect; segment_data = make_vec4(0.f); } } else { int32_t segment_address = (((ph).specific_prim_address)+(1))+(((instance).segment_index)*(2)); Array segment_info = fetch_from_gpu_cache_2(segment_address); segment_rect = RectWithEndpoint_scalar((segment_info[0]).sel(X, Y), (segment_info[0]).sel(Z, W)); (segment_rect).p0 += ((ph).local_rect).p0; (segment_rect).p1 += ((ph).local_rect).p0; segment_data = segment_info[1]; } VertexInfo vi; if ((transform).is_axis_aligned) { { vec2 local_pos = mix((segment_rect).p0, (segment_rect).p1, (aPosition).sel(X, Y)); vi = write_vertex(local_pos, (ph).local_clip_rect, (ph).z, transform, pic_task); } } else { vi = write_transform_vertex(segment_rect, (ph).local_rect, (ph).local_clip_rect, edge_flags, (ph).z, transform, pic_task); } write_clip((vi).world_pos, clip_area, pic_task); brush_vs(vi, (ph).specific_prim_address, (ph).local_rect, segment_rect, (ph).user_data, (instance).resource_address, (transform).m, pic_task, brush_flags, segment_data); } ALWAYS_INLINE void main(void) { Instance_scalar instance = decode_instance_attributes(); PrimitiveHeader_scalar ph = fetch_prim_header((instance).prim_header_address); Transform_scalar transform = fetch_transform((ph).transform_id); PictureTask_scalar task = fetch_picture_task((instance).picture_task_address); ClipArea_scalar clip_area = fetch_clip_area((instance).clip_address); brush_shader_main_vs(instance, ph, transform, task, clip_area); } static void set_uniform_1i(Self *self, int index, int value) { if (self->samplers.set_slot(index, value)) return; switch (index) { case 7: assert(0); // sClipMask break; case 2: assert(0); // sGpuCache break; case 4: assert(0); // sPrimitiveHeadersF break; case 5: assert(0); // sPrimitiveHeadersI break; case 1: assert(0); // sRenderTasks break; case 3: assert(0); // sTransformPalette break; case 6: assert(0); // uTransform break; } } static void set_uniform_4fv(Self *self, int index, const float *value) { switch (index) { case 7: assert(0); // sClipMask break; case 2: assert(0); // sGpuCache break; case 4: assert(0); // sPrimitiveHeadersF break; case 5: assert(0); // sPrimitiveHeadersI break; case 1: assert(0); // sRenderTasks break; case 3: assert(0); // sTransformPalette break; case 6: assert(0); // uTransform break; } } static void set_uniform_matrix4fv(Self *self, int index, const float *value) { switch (index) { case 7: assert(0); // sClipMask break; case 2: assert(0); // sGpuCache break; case 4: assert(0); // sPrimitiveHeadersF break; case 5: assert(0); // sPrimitiveHeadersI break; case 1: assert(0); // sRenderTasks break; case 3: assert(0); // sTransformPalette break; case 6: self->uTransform = mat4_scalar::load_from_ptr(value); break; } } static void load_attribs(Self *self, VertexAttrib *attribs, uint32_t start, int instance, int count) { load_attrib(self->aPosition, attribs[self->attrib_locations.aPosition], start, instance, count); load_flat_attrib(self->aData, attribs[self->attrib_locations.aData], start, instance, count); } public: struct InterpOutputs { }; private: ALWAYS_INLINE void store_interp_outputs(char* dest_ptr, size_t stride) { for(int n = 0; n < 4; n++) { auto* dest = reinterpret_cast(dest_ptr); dest_ptr += stride; } } static void run(Self* self, char* interps, size_t interp_stride) { self->main(); self->store_interp_outputs(interps, interp_stride); } static void init_batch(Self *self) { self->bind_textures(); } public: brush_solid_ALPHA_PASS_vert() { set_uniform_1i_func = (SetUniform1iFunc)&set_uniform_1i; set_uniform_4fv_func = (SetUniform4fvFunc)&set_uniform_4fv; set_uniform_matrix4fv_func = (SetUniformMatrix4fvFunc)&set_uniform_matrix4fv; init_batch_func = (InitBatchFunc)&init_batch; load_attribs_func = (LoadAttribsFunc)&load_attribs; run_primitive_func = (RunPrimitiveFunc)&run; } }; struct brush_solid_ALPHA_PASS_frag : FragmentShaderImpl, brush_solid_ALPHA_PASS_vert { private: typedef brush_solid_ALPHA_PASS_frag Self; #define oFragColor gl_FragColor // vec4 oFragColor; struct RectWithSize_scalar { vec2_scalar p0; vec2_scalar size; RectWithSize_scalar() = default; RectWithSize_scalar(vec2_scalar p0, vec2_scalar size) : p0(p0), size(size){} }; struct RectWithSize { vec2 p0; vec2 size; RectWithSize() = default; RectWithSize(vec2 p0, vec2 size) : p0(p0), size(size){} RectWithSize(vec2_scalar p0, vec2_scalar size):p0(p0),size(size){ } IMPLICIT RectWithSize(RectWithSize_scalar s):p0(s.p0),size(s.size){ } friend RectWithSize if_then_else(I32 c, RectWithSize t, RectWithSize e) { return RectWithSize( if_then_else(c, t.p0, e.p0), if_then_else(c, t.size, e.size)); }}; struct RectWithEndpoint_scalar { vec2_scalar p0; vec2_scalar p1; RectWithEndpoint_scalar() = default; RectWithEndpoint_scalar(vec2_scalar p0, vec2_scalar p1) : p0(p0), p1(p1){} }; struct RectWithEndpoint { vec2 p0; vec2 p1; RectWithEndpoint() = default; RectWithEndpoint(vec2 p0, vec2 p1) : p0(p0), p1(p1){} RectWithEndpoint(vec2_scalar p0, vec2_scalar p1):p0(p0),p1(p1){ } IMPLICIT RectWithEndpoint(RectWithEndpoint_scalar s):p0(s.p0),p1(s.p1){ } friend RectWithEndpoint if_then_else(I32 c, RectWithEndpoint t, RectWithEndpoint e) { return RectWithEndpoint( if_then_else(c, t.p0, e.p0), if_then_else(c, t.p1, e.p1)); }}; // sampler2D sGpuCache; // vec4_scalar vTransformBounds; // sampler2D sClipMask; struct Fragment_scalar { vec4_scalar color; Fragment_scalar() = default; explicit Fragment_scalar(vec4_scalar color) : color(color){} }; struct Fragment { vec4 color; Fragment() = default; explicit Fragment(vec4 color) : color(color){} explicit Fragment(vec4_scalar color):color(color){ } IMPLICIT Fragment(Fragment_scalar s):color(s.color){ } friend Fragment if_then_else(I32 c, Fragment t, Fragment e) { return Fragment( if_then_else(c, t.color, e.color)); }}; // vec4_scalar v_color; float antialias_brush() { return 1.f; } Fragment_scalar brush_fs() { vec4_scalar color = v_color; color *= antialias_brush(); return Fragment_scalar(color); } float do_clip() { return 1.f; } void write_output(vec4 color) { oFragColor = color; } ALWAYS_INLINE void main(void) { Fragment frag = brush_fs(); float clip_alpha = do_clip(); (frag).color *= clip_alpha; write_output((frag).color); } void swgl_drawSpanRGBA8() { swgl_commitSolidRGBA8(v_color); } void swgl_drawSpanR8() { swgl_commitSolidR8((v_color).sel(X)); } typedef brush_solid_ALPHA_PASS_vert::InterpOutputs InterpInputs; InterpInputs interp_step; static void read_interp_inputs(Self *self, const InterpInputs *init, const InterpInputs *step) { } ALWAYS_INLINE void step_interp_inputs(int steps = 4) { float chunks = steps * 0.25f; } static void run(Self *self) { self->main(); self->step_interp_inputs(); } static void skip(Self* self, int steps) { self->step_interp_inputs(steps); } static int draw_span_RGBA8(Self* self) { DISPATCH_DRAW_SPAN(self, RGBA8); } static int draw_span_R8(Self* self) { DISPATCH_DRAW_SPAN(self, R8); } public: brush_solid_ALPHA_PASS_frag() { init_span_func = (InitSpanFunc)&read_interp_inputs; run_func = (RunFunc)&run; skip_func = (SkipFunc)&skip; draw_span_RGBA8_func = (DrawSpanRGBA8Func)&draw_span_RGBA8; draw_span_R8_func = (DrawSpanR8Func)&draw_span_R8; init_span_w_func = (InitSpanWFunc)&read_interp_inputs; run_w_func = (RunWFunc)&run; skip_w_func = (SkipWFunc)&skip; } }; struct brush_solid_ALPHA_PASS_program : ProgramImpl, brush_solid_ALPHA_PASS_frag { int get_uniform(const char *name) const override { if (strcmp("sClipMask", name) == 0) { return 7; } if (strcmp("sGpuCache", name) == 0) { return 2; } if (strcmp("sPrimitiveHeadersF", name) == 0) { return 4; } if (strcmp("sPrimitiveHeadersI", name) == 0) { return 5; } if (strcmp("sRenderTasks", name) == 0) { return 1; } if (strcmp("sTransformPalette", name) == 0) { return 3; } if (strcmp("uTransform", name) == 0) { return 6; } return -1; } void bind_attrib(const char* name, int index) override { attrib_locations.bind_loc(name, index); } int get_attrib(const char* name) const override { return attrib_locations.get_loc(name); } size_t interpolants_size() const override { return sizeof(InterpOutputs); } VertexShaderImpl* get_vertex_shader() override { return this; } FragmentShaderImpl* get_fragment_shader() override { return this; } const char* get_name() const override { return "brush_solid_ALPHA_PASS"; } static ProgramImpl* loader() { return new brush_solid_ALPHA_PASS_program; } };