@@ -2146,23 +2146,24 @@ void RendererCanvasRenderRD::_render_batch_items(RenderTarget p_to_render_target
21462146 current_batch->material_data = material_data;
21472147 }
21482148
2149- Transform2D base_transform = p_canvas_transform_inverse * ci->final_transform ;
2150- if (!ci-> repeat_size . x && ! ci->repeat_size . y ) {
2151- _record_item_commands (ci, p_to_render_target, base_transform, current_clip, p_lights, instance_index, batch_broken, r_sdf_used);
2149+ if (ci-> repeat_source_item == nullptr || ci->repeat_size == Vector2 ()) {
2150+ Transform2D base_transform = p_canvas_transform_inverse * ci->final_transform ;
2151+ _record_item_commands (ci, p_to_render_target, base_transform, current_clip, p_lights, instance_index, batch_broken, r_sdf_used, current_batch );
21522152 } else {
21532153 Point2 start_pos = ci->repeat_size * -(ci->repeat_times / 2 );
2154- Point2 end_pos = ci->repeat_size * ci->repeat_times + ci->repeat_size + start_pos;
2155- Point2 pos = start_pos;
2156- do {
2157- do {
2158- Transform2D transform = base_transform * Transform2D (0 , pos / ci->xform_curr .get_scale ());
2159- _record_item_commands (ci, p_to_render_target, transform, current_clip, p_lights, instance_index, batch_broken, r_sdf_used);
2160- pos.y += ci->repeat_size .y ;
2161- } while (pos.y < end_pos.y );
2162-
2163- pos.x += ci->repeat_size .x ;
2164- pos.y = start_pos.y ;
2165- } while (pos.x < end_pos.x );
2154+ Point2 offset;
2155+ int repeat_times_x = ci->repeat_size .x ? ci->repeat_times : 0 ;
2156+ int repeat_times_y = ci->repeat_size .y ? ci->repeat_times : 0 ;
2157+ for (int ry = 0 ; ry <= repeat_times_y; ry++) {
2158+ offset.y = start_pos.y + ry * ci->repeat_size .y ;
2159+ for (int rx = 0 ; rx <= repeat_times_x; rx++) {
2160+ offset.x = start_pos.x + rx * ci->repeat_size .x ;
2161+ Transform2D base_transform = ci->final_transform ;
2162+ base_transform.columns [2 ] += ci->repeat_source_item ->final_transform .basis_xform (offset);
2163+ base_transform = p_canvas_transform_inverse * base_transform;
2164+ _record_item_commands (ci, p_to_render_target, base_transform, current_clip, p_lights, instance_index, batch_broken, r_sdf_used, current_batch);
2165+ }
2166+ }
21662167 }
21672168 }
21682169
@@ -2262,9 +2263,7 @@ void RendererCanvasRenderRD::_render_batch_items(RenderTarget p_to_render_target
22622263 state.last_instance_index += instance_index;
22632264}
22642265
2265- void RendererCanvasRenderRD::_record_item_commands (const Item *p_item, RenderTarget p_render_target, const Transform2D &p_base_transform, Item *&r_current_clip, Light *p_lights, uint32_t &r_index, bool &r_batch_broken, bool &r_sdf_used) {
2266- Batch *current_batch = &state.canvas_instance_batches [state.current_batch_index ];
2267-
2266+ void RendererCanvasRenderRD::_record_item_commands (const Item *p_item, RenderTarget p_render_target, const Transform2D &p_base_transform, Item *&r_current_clip, Light *p_lights, uint32_t &r_index, bool &r_batch_broken, bool &r_sdf_used, Batch *&r_current_batch) {
22682267 RenderingServer::CanvasItemTextureFilter texture_filter = p_item->texture_filter == RS::CANVAS_ITEM_TEXTURE_FILTER_DEFAULT ? default_filter : p_item->texture_filter ;
22692268 RenderingServer::CanvasItemTextureRepeat texture_repeat = p_item->texture_repeat == RS::CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT ? default_repeat : p_item->texture_repeat ;
22702269
@@ -2310,9 +2309,9 @@ void RendererCanvasRenderRD::_record_item_commands(const Item *p_item, RenderTar
23102309
23112310 light_mode = (light_count > 0 || using_directional_lights) ? PIPELINE_LIGHT_MODE_ENABLED : PIPELINE_LIGHT_MODE_DISABLED;
23122311
2313- if (light_mode != current_batch ->light_mode ) {
2314- current_batch = _new_batch (r_batch_broken);
2315- current_batch ->light_mode = light_mode;
2312+ if (light_mode != r_current_batch ->light_mode ) {
2313+ r_current_batch = _new_batch (r_batch_broken);
2314+ r_current_batch ->light_mode = light_mode;
23162315 }
23172316
23182317 // new_instance_data should be called after the current_batch is set.
@@ -2338,11 +2337,11 @@ void RendererCanvasRenderRD::_record_item_commands(const Item *p_item, RenderTar
23382337 instance_data->world [i] = world[i];
23392338 }
23402339
2341- instance_data->flags = base_flags | current_batch ->tex_flags ; // Reset on each command for safety, keep canvas texture binding config.
2340+ instance_data->flags = base_flags | r_current_batch ->tex_flags ; // Reset on each command for safety, keep canvas texture binding config.
23422341
2343- instance_data->color_texture_pixel_size [0 ] = current_batch ->tex_texpixel_size .width ;
2344- instance_data->color_texture_pixel_size [1 ] = current_batch ->tex_texpixel_size .height ;
2345- instance_data->specular_shininess = current_batch ->tex_specular_shininess ;
2342+ instance_data->color_texture_pixel_size [0 ] = r_current_batch ->tex_texpixel_size .width ;
2343+ instance_data->color_texture_pixel_size [1 ] = r_current_batch ->tex_texpixel_size .height ;
2344+ instance_data->specular_shininess = r_current_batch ->tex_specular_shininess ;
23462345
23472346 return instance_data;
23482347 };
@@ -2359,12 +2358,12 @@ void RendererCanvasRenderRD::_record_item_commands(const Item *p_item, RenderTar
23592358 const Item::CommandRect *rect = static_cast <const Item::CommandRect *>(c);
23602359
23612360 // 1: If commands are different, start a new batch.
2362- if (current_batch ->command_type != Item::Command::TYPE_RECT) {
2363- current_batch = _new_batch (r_batch_broken);
2364- current_batch ->command_type = Item::Command::TYPE_RECT;
2365- current_batch ->command = c;
2361+ if (r_current_batch ->command_type != Item::Command::TYPE_RECT) {
2362+ r_current_batch = _new_batch (r_batch_broken);
2363+ r_current_batch ->command_type = Item::Command::TYPE_RECT;
2364+ r_current_batch ->command = c;
23662365 // default variant
2367- current_batch ->pipeline_variant = PIPELINE_VARIANT_QUAD;
2366+ r_current_batch ->pipeline_variant = PIPELINE_VARIANT_QUAD;
23682367 }
23692368
23702369 if (bool (rect->flags & CANVAS_RECT_TILE)) {
@@ -2374,10 +2373,10 @@ void RendererCanvasRenderRD::_record_item_commands(const Item *p_item, RenderTar
23742373 bool has_msdf = bool (rect->flags & CANVAS_RECT_MSDF);
23752374 TextureState tex_state (rect->texture , texture_filter, texture_repeat, has_msdf, use_linear_colors);
23762375
2377- if (tex_state != current_batch ->tex_state ) {
2378- current_batch = _new_batch (r_batch_broken);
2379- current_batch ->set_tex_state (tex_state);
2380- _prepare_batch_texture (current_batch , rect->texture );
2376+ if (tex_state != r_current_batch ->tex_state ) {
2377+ r_current_batch = _new_batch (r_batch_broken);
2378+ r_current_batch ->set_tex_state (tex_state);
2379+ _prepare_batch_texture (r_current_batch , rect->texture );
23812380 }
23822381
23832382 Color modulated = rect->modulate * base_color;
@@ -2388,19 +2387,19 @@ void RendererCanvasRenderRD::_record_item_commands(const Item *p_item, RenderTar
23882387 bool has_blend = bool (rect->flags & CANVAS_RECT_LCD);
23892388 // Start a new batch if the blend mode has changed,
23902389 // or blend mode is enabled and the modulation has changed.
2391- if (has_blend != current_batch ->has_blend || (has_blend && modulated != current_batch ->modulate )) {
2392- current_batch = _new_batch (r_batch_broken);
2393- current_batch ->has_blend = has_blend;
2394- current_batch ->modulate = modulated;
2395- current_batch ->pipeline_variant = has_blend ? PIPELINE_VARIANT_QUAD_LCD_BLEND : PIPELINE_VARIANT_QUAD;
2390+ if (has_blend != r_current_batch ->has_blend || (has_blend && modulated != r_current_batch ->modulate )) {
2391+ r_current_batch = _new_batch (r_batch_broken);
2392+ r_current_batch ->has_blend = has_blend;
2393+ r_current_batch ->modulate = modulated;
2394+ r_current_batch ->pipeline_variant = has_blend ? PIPELINE_VARIANT_QUAD_LCD_BLEND : PIPELINE_VARIANT_QUAD;
23962395 }
23972396
23982397 InstanceData *instance_data = new_instance_data ();
23992398 Rect2 src_rect;
24002399 Rect2 dst_rect;
24012400
24022401 if (rect->texture .is_valid ()) {
2403- src_rect = (rect->flags & CANVAS_RECT_REGION) ? Rect2 (rect->source .position * current_batch ->tex_texpixel_size , rect->source .size * current_batch ->tex_texpixel_size ) : Rect2 (0 , 0 , 1 , 1 );
2402+ src_rect = (rect->flags & CANVAS_RECT_REGION) ? Rect2 (rect->source .position * r_current_batch ->tex_texpixel_size , rect->source .size * r_current_batch ->tex_texpixel_size ) : Rect2 (0 , 0 , 1 , 1 );
24042403 dst_rect = Rect2 (rect->rect .position , rect->rect .size );
24052404
24062405 if (dst_rect.size .width < 0 ) {
@@ -2470,24 +2469,24 @@ void RendererCanvasRenderRD::_record_item_commands(const Item *p_item, RenderTar
24702469 instance_data->dst_rect [2 ] = dst_rect.size .width ;
24712470 instance_data->dst_rect [3 ] = dst_rect.size .height ;
24722471
2473- _add_to_batch (r_index, r_batch_broken, current_batch );
2472+ _add_to_batch (r_index, r_batch_broken, r_current_batch );
24742473 } break ;
24752474
24762475 case Item::Command::TYPE_NINEPATCH: {
24772476 const Item::CommandNinePatch *np = static_cast <const Item::CommandNinePatch *>(c);
24782477
2479- if (current_batch ->command_type != Item::Command::TYPE_NINEPATCH) {
2480- current_batch = _new_batch (r_batch_broken);
2481- current_batch ->command_type = Item::Command::TYPE_NINEPATCH;
2482- current_batch ->command = c;
2483- current_batch ->pipeline_variant = PipelineVariant::PIPELINE_VARIANT_NINEPATCH;
2478+ if (r_current_batch ->command_type != Item::Command::TYPE_NINEPATCH) {
2479+ r_current_batch = _new_batch (r_batch_broken);
2480+ r_current_batch ->command_type = Item::Command::TYPE_NINEPATCH;
2481+ r_current_batch ->command = c;
2482+ r_current_batch ->pipeline_variant = PipelineVariant::PIPELINE_VARIANT_NINEPATCH;
24842483 }
24852484
24862485 TextureState tex_state (np->texture , texture_filter, texture_repeat, false , use_linear_colors);
2487- if (tex_state != current_batch ->tex_state ) {
2488- current_batch = _new_batch (r_batch_broken);
2489- current_batch ->set_tex_state (tex_state);
2490- _prepare_batch_texture (current_batch , np->texture );
2486+ if (tex_state != r_current_batch ->tex_state ) {
2487+ r_current_batch = _new_batch (r_batch_broken);
2488+ r_current_batch ->set_tex_state (tex_state);
2489+ _prepare_batch_texture (r_current_batch , np->texture );
24912490 }
24922491
24932492 InstanceData *instance_data = new_instance_data ();
@@ -2499,7 +2498,7 @@ void RendererCanvasRenderRD::_record_item_commands(const Item *p_item, RenderTar
24992498 src_rect = Rect2 (0 , 0 , 1 , 1 );
25002499 } else {
25012500 if (np->source != Rect2 ()) {
2502- src_rect = Rect2 (np->source .position .x * current_batch ->tex_texpixel_size .width , np->source .position .y * current_batch ->tex_texpixel_size .height , np->source .size .x * current_batch ->tex_texpixel_size .width , np->source .size .y * current_batch ->tex_texpixel_size .height );
2501+ src_rect = Rect2 (np->source .position .x * r_current_batch ->tex_texpixel_size .width , np->source .position .y * r_current_batch ->tex_texpixel_size .height , np->source .size .x * r_current_batch ->tex_texpixel_size .width , np->source .size .y * r_current_batch ->tex_texpixel_size .height );
25032502 instance_data->color_texture_pixel_size [0 ] = 1.0 / np->source .size .width ;
25042503 instance_data->color_texture_pixel_size [1 ] = 1.0 / np->source .size .height ;
25052504 } else {
@@ -2539,30 +2538,30 @@ void RendererCanvasRenderRD::_record_item_commands(const Item *p_item, RenderTar
25392538 instance_data->ninepatch_margins [2 ] = np->margin [SIDE_RIGHT];
25402539 instance_data->ninepatch_margins [3 ] = np->margin [SIDE_BOTTOM];
25412540
2542- _add_to_batch (r_index, r_batch_broken, current_batch );
2541+ _add_to_batch (r_index, r_batch_broken, r_current_batch );
25432542 } break ;
25442543
25452544 case Item::Command::TYPE_POLYGON: {
25462545 const Item::CommandPolygon *polygon = static_cast <const Item::CommandPolygon *>(c);
25472546
25482547 // Polygon's can't be batched, so always create a new batch
2549- current_batch = _new_batch (r_batch_broken);
2548+ r_current_batch = _new_batch (r_batch_broken);
25502549
2551- current_batch ->command_type = Item::Command::TYPE_POLYGON;
2552- current_batch ->command = c;
2550+ r_current_batch ->command_type = Item::Command::TYPE_POLYGON;
2551+ r_current_batch ->command = c;
25532552
25542553 TextureState tex_state (polygon->texture , texture_filter, texture_repeat, false , use_linear_colors);
2555- if (tex_state != current_batch ->tex_state ) {
2556- current_batch = _new_batch (r_batch_broken);
2557- current_batch ->set_tex_state (tex_state);
2558- _prepare_batch_texture (current_batch , polygon->texture );
2554+ if (tex_state != r_current_batch ->tex_state ) {
2555+ r_current_batch = _new_batch (r_batch_broken);
2556+ r_current_batch ->set_tex_state (tex_state);
2557+ _prepare_batch_texture (r_current_batch , polygon->texture );
25592558 }
25602559
25612560 // pipeline variant
25622561 {
25632562 static const PipelineVariant variant[RS::PRIMITIVE_MAX] = { PIPELINE_VARIANT_ATTRIBUTE_POINTS, PIPELINE_VARIANT_ATTRIBUTE_LINES, PIPELINE_VARIANT_ATTRIBUTE_LINES_STRIP, PIPELINE_VARIANT_ATTRIBUTE_TRIANGLES, PIPELINE_VARIANT_ATTRIBUTE_TRIANGLE_STRIP };
25642563 ERR_CONTINUE (polygon->primitive < 0 || polygon->primitive >= RS::PRIMITIVE_MAX);
2565- current_batch ->pipeline_variant = variant[polygon->primitive ];
2564+ r_current_batch ->pipeline_variant = variant[polygon->primitive ];
25662565 }
25672566
25682567 InstanceData *instance_data = new_instance_data ();
@@ -2577,27 +2576,27 @@ void RendererCanvasRenderRD::_record_item_commands(const Item *p_item, RenderTar
25772576 instance_data->modulation [2 ] = color.b ;
25782577 instance_data->modulation [3 ] = color.a ;
25792578
2580- _add_to_batch (r_index, r_batch_broken, current_batch );
2579+ _add_to_batch (r_index, r_batch_broken, r_current_batch );
25812580 } break ;
25822581
25832582 case Item::Command::TYPE_PRIMITIVE: {
25842583 const Item::CommandPrimitive *primitive = static_cast <const Item::CommandPrimitive *>(c);
25852584
2586- if (primitive->point_count != current_batch ->primitive_points || current_batch ->command_type != Item::Command::TYPE_PRIMITIVE) {
2587- current_batch = _new_batch (r_batch_broken);
2588- current_batch ->command_type = Item::Command::TYPE_PRIMITIVE;
2589- current_batch ->command = c;
2590- current_batch ->primitive_points = primitive->point_count ;
2585+ if (primitive->point_count != r_current_batch ->primitive_points || r_current_batch ->command_type != Item::Command::TYPE_PRIMITIVE) {
2586+ r_current_batch = _new_batch (r_batch_broken);
2587+ r_current_batch ->command_type = Item::Command::TYPE_PRIMITIVE;
2588+ r_current_batch ->command = c;
2589+ r_current_batch ->primitive_points = primitive->point_count ;
25912590
25922591 static const PipelineVariant variant[4 ] = { PIPELINE_VARIANT_PRIMITIVE_POINTS, PIPELINE_VARIANT_PRIMITIVE_LINES, PIPELINE_VARIANT_PRIMITIVE_TRIANGLES, PIPELINE_VARIANT_PRIMITIVE_TRIANGLES };
25932592 ERR_CONTINUE (primitive->point_count == 0 || primitive->point_count > 4 );
2594- current_batch ->pipeline_variant = variant[primitive->point_count - 1 ];
2593+ r_current_batch ->pipeline_variant = variant[primitive->point_count - 1 ];
25952594
25962595 TextureState tex_state (primitive->texture , texture_filter, texture_repeat, false , use_linear_colors);
2597- if (tex_state != current_batch ->tex_state ) {
2598- current_batch = _new_batch (r_batch_broken);
2599- current_batch ->set_tex_state (tex_state);
2600- _prepare_batch_texture (current_batch , primitive->texture );
2596+ if (tex_state != r_current_batch ->tex_state ) {
2597+ r_current_batch = _new_batch (r_batch_broken);
2598+ r_current_batch ->set_tex_state (tex_state);
2599+ _prepare_batch_texture (r_current_batch , primitive->texture );
26012600 }
26022601 }
26032602
@@ -2616,7 +2615,7 @@ void RendererCanvasRenderRD::_record_item_commands(const Item *p_item, RenderTar
26162615 instance_data->colors [j * 2 + 1 ] = (uint32_t (Math::make_half_float (col.a )) << 16 ) | Math::make_half_float (col.b );
26172616 }
26182617
2619- _add_to_batch (r_index, r_batch_broken, current_batch );
2618+ _add_to_batch (r_index, r_batch_broken, r_current_batch );
26202619
26212620 if (primitive->point_count == 4 ) {
26222621 instance_data = new_instance_data ();
@@ -2636,29 +2635,29 @@ void RendererCanvasRenderRD::_record_item_commands(const Item *p_item, RenderTar
26362635 instance_data->colors [j * 2 + 1 ] = (uint32_t (Math::make_half_float (col.a )) << 16 ) | Math::make_half_float (col.b );
26372636 }
26382637
2639- _add_to_batch (r_index, r_batch_broken, current_batch );
2638+ _add_to_batch (r_index, r_batch_broken, r_current_batch );
26402639 }
26412640 } break ;
26422641
26432642 case Item::Command::TYPE_MESH:
26442643 case Item::Command::TYPE_MULTIMESH:
26452644 case Item::Command::TYPE_PARTICLES: {
26462645 // Mesh's can't be batched, so always create a new batch
2647- current_batch = _new_batch (r_batch_broken);
2648- current_batch ->command = c;
2649- current_batch ->command_type = c->type ;
2646+ r_current_batch = _new_batch (r_batch_broken);
2647+ r_current_batch ->command = c;
2648+ r_current_batch ->command_type = c->type ;
26502649
26512650 InstanceData *instance_data = nullptr ;
26522651
26532652 Color modulate (1 , 1 , 1 , 1 );
26542653 if (c->type == Item::Command::TYPE_MESH) {
26552654 const Item::CommandMesh *m = static_cast <const Item::CommandMesh *>(c);
26562655 TextureState tex_state (m->texture , texture_filter, texture_repeat, false , use_linear_colors);
2657- current_batch ->set_tex_state (tex_state);
2658- _prepare_batch_texture (current_batch , m->texture );
2656+ r_current_batch ->set_tex_state (tex_state);
2657+ _prepare_batch_texture (r_current_batch , m->texture );
26592658 instance_data = new_instance_data ();
26602659
2661- current_batch ->mesh_instance_count = 1 ;
2660+ r_current_batch ->mesh_instance_count = 1 ;
26622661 _update_transform_2d_to_mat2x3 (base_transform * draw_transform * m->transform , instance_data->world );
26632662 modulate = m->modulate ;
26642663 } else if (c->type == Item::Command::TYPE_MULTIMESH) {
@@ -2671,14 +2670,14 @@ void RendererCanvasRenderRD::_record_item_commands(const Item *p_item, RenderTar
26712670 break ;
26722671 }
26732672
2674- current_batch ->mesh_instance_count = mesh_storage->multimesh_get_instances_to_draw (multimesh);
2675- if (current_batch ->mesh_instance_count == 0 ) {
2673+ r_current_batch ->mesh_instance_count = mesh_storage->multimesh_get_instances_to_draw (multimesh);
2674+ if (r_current_batch ->mesh_instance_count == 0 ) {
26762675 break ;
26772676 }
26782677
26792678 TextureState tex_state (mm->texture , texture_filter, texture_repeat, false , use_linear_colors);
2680- current_batch ->set_tex_state (tex_state);
2681- _prepare_batch_texture (current_batch , mm->texture );
2679+ r_current_batch ->set_tex_state (tex_state);
2680+ _prepare_batch_texture (r_current_batch , mm->texture );
26822681 instance_data = new_instance_data ();
26832682
26842683 instance_data->flags |= 1 ; // multimesh, trails disabled
@@ -2695,15 +2694,15 @@ void RendererCanvasRenderRD::_record_item_commands(const Item *p_item, RenderTar
26952694
26962695 const Item::CommandParticles *pt = static_cast <const Item::CommandParticles *>(c);
26972696 TextureState tex_state (pt->texture , texture_filter, texture_repeat, false , use_linear_colors);
2698- current_batch ->set_tex_state (tex_state);
2699- _prepare_batch_texture (current_batch , pt->texture );
2697+ r_current_batch ->set_tex_state (tex_state);
2698+ _prepare_batch_texture (r_current_batch , pt->texture );
27002699
27012700 instance_data = new_instance_data ();
27022701
27032702 uint32_t divisor = 1 ;
2704- current_batch ->mesh_instance_count = particles_storage->particles_get_amount (pt->particles , divisor);
2703+ r_current_batch ->mesh_instance_count = particles_storage->particles_get_amount (pt->particles , divisor);
27052704 instance_data->flags |= (divisor & FLAGS_INSTANCING_MASK);
2706- current_batch ->mesh_instance_count /= divisor;
2705+ r_current_batch ->mesh_instance_count /= divisor;
27072706
27082707 RID particles = pt->particles ;
27092708
@@ -2741,7 +2740,7 @@ void RendererCanvasRenderRD::_record_item_commands(const Item *p_item, RenderTar
27412740 instance_data->modulation [2 ] = modulated.b ;
27422741 instance_data->modulation [3 ] = modulated.a ;
27432742
2744- _add_to_batch (r_index, r_batch_broken, current_batch );
2743+ _add_to_batch (r_index, r_batch_broken, r_current_batch );
27452744 } break ;
27462745
27472746 case Item::Command::TYPE_TRANSFORM: {
@@ -2754,12 +2753,12 @@ void RendererCanvasRenderRD::_record_item_commands(const Item *p_item, RenderTar
27542753 const Item::CommandClipIgnore *ci = static_cast <const Item::CommandClipIgnore *>(c);
27552754 if (r_current_clip) {
27562755 if (ci->ignore != reclip) {
2757- current_batch = _new_batch (r_batch_broken);
2756+ r_current_batch = _new_batch (r_batch_broken);
27582757 if (ci->ignore ) {
2759- current_batch ->clip = nullptr ;
2758+ r_current_batch ->clip = nullptr ;
27602759 reclip = true ;
27612760 } else {
2762- current_batch ->clip = r_current_clip;
2761+ r_current_batch ->clip = r_current_clip;
27632762 reclip = false ;
27642763 }
27652764 }
0 commit comments