Home | History | Annotate | Download | only in nouveau
      1 /*
      2  * Copyright (C) 2009 Francisco Jerez.
      3  * All Rights Reserved.
      4  *
      5  * Permission is hereby granted, free of charge, to any person obtaining
      6  * a copy of this software and associated documentation files (the
      7  * "Software"), to deal in the Software without restriction, including
      8  * without limitation the rights to use, copy, modify, merge, publish,
      9  * distribute, sublicense, and/or sell copies of the Software, and to
     10  * permit persons to whom the Software is furnished to do so, subject to
     11  * the following conditions:
     12  *
     13  * The above copyright notice and this permission notice (including the
     14  * next paragraph) shall be included in all copies or substantial
     15  * portions of the Software.
     16  *
     17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
     18  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
     19  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
     20  * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
     21  * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
     22  * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
     23  * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
     24  *
     25  */
     26 
     27 #include "nouveau_driver.h"
     28 #include "nouveau_context.h"
     29 #include "nouveau_texture.h"
     30 #include "nouveau_util.h"
     31 
     32 #include "swrast/swrast.h"
     33 #include "tnl/tnl.h"
     34 
     35 static void
     36 nouveau_alpha_func(struct gl_context *ctx, GLenum func, GLfloat ref)
     37 {
     38 	context_dirty(ctx, ALPHA_FUNC);
     39 }
     40 
     41 static void
     42 nouveau_blend_color(struct gl_context *ctx, const GLfloat color[4])
     43 {
     44 	context_dirty(ctx, BLEND_COLOR);
     45 }
     46 
     47 static void
     48 nouveau_blend_equation_separate(struct gl_context *ctx, GLenum modeRGB, GLenum modeA)
     49 {
     50 	context_dirty(ctx, BLEND_EQUATION);
     51 }
     52 
     53 static void
     54 nouveau_blend_func_separate(struct gl_context *ctx, GLenum sfactorRGB,
     55 			    GLenum dfactorRGB, GLenum sfactorA, GLenum dfactorA)
     56 {
     57 	context_dirty(ctx, BLEND_FUNC);
     58 }
     59 
     60 static void
     61 nouveau_clip_plane(struct gl_context *ctx, GLenum plane, const GLfloat *equation)
     62 {
     63 	context_dirty_i(ctx, CLIP_PLANE, plane - GL_CLIP_PLANE0);
     64 }
     65 
     66 static void
     67 nouveau_color_mask(struct gl_context *ctx, GLboolean rmask, GLboolean gmask,
     68 		   GLboolean bmask, GLboolean amask)
     69 {
     70 	context_dirty(ctx, COLOR_MASK);
     71 }
     72 
     73 static void
     74 nouveau_color_material(struct gl_context *ctx, GLenum face, GLenum mode)
     75 {
     76 	context_dirty(ctx, COLOR_MATERIAL);
     77 	context_dirty(ctx, MATERIAL_FRONT_AMBIENT);
     78 	context_dirty(ctx, MATERIAL_BACK_AMBIENT);
     79 	context_dirty(ctx, MATERIAL_FRONT_DIFFUSE);
     80 	context_dirty(ctx, MATERIAL_BACK_DIFFUSE);
     81 	context_dirty(ctx, MATERIAL_FRONT_SPECULAR);
     82 	context_dirty(ctx, MATERIAL_BACK_SPECULAR);
     83 }
     84 
     85 static void
     86 nouveau_cull_face(struct gl_context *ctx, GLenum mode)
     87 {
     88 	context_dirty(ctx, CULL_FACE);
     89 }
     90 
     91 static void
     92 nouveau_front_face(struct gl_context *ctx, GLenum mode)
     93 {
     94 	context_dirty(ctx, FRONT_FACE);
     95 }
     96 
     97 static void
     98 nouveau_depth_func(struct gl_context *ctx, GLenum func)
     99 {
    100 	context_dirty(ctx, DEPTH);
    101 }
    102 
    103 static void
    104 nouveau_depth_mask(struct gl_context *ctx, GLboolean flag)
    105 {
    106 	context_dirty(ctx, DEPTH);
    107 }
    108 
    109 static void
    110 nouveau_depth_range(struct gl_context *ctx, GLclampd nearval, GLclampd farval)
    111 {
    112 	context_dirty(ctx, VIEWPORT);
    113 }
    114 
    115 static void
    116 nouveau_read_buffer(struct gl_context *ctx, GLenum buffer)
    117 {
    118 	nouveau_validate_framebuffer(ctx);
    119 }
    120 
    121 static void
    122 nouveau_draw_buffers(struct gl_context *ctx, GLsizei n, const GLenum *buffers)
    123 {
    124 	nouveau_validate_framebuffer(ctx);
    125 	context_dirty(ctx, FRAMEBUFFER);
    126 }
    127 
    128 static void
    129 nouveau_enable(struct gl_context *ctx, GLenum cap, GLboolean state)
    130 {
    131 	int i;
    132 
    133 	switch (cap) {
    134 	case GL_ALPHA_TEST:
    135 		context_dirty(ctx, ALPHA_FUNC);
    136 		break;
    137 	case GL_BLEND:
    138 		context_dirty(ctx, BLEND_EQUATION);
    139 		break;
    140 	case GL_COLOR_LOGIC_OP:
    141 		context_dirty(ctx, LOGIC_OPCODE);
    142 		break;
    143 	case GL_COLOR_MATERIAL:
    144 		context_dirty(ctx, COLOR_MATERIAL);
    145 		context_dirty(ctx, MATERIAL_FRONT_AMBIENT);
    146 		context_dirty(ctx, MATERIAL_BACK_AMBIENT);
    147 		context_dirty(ctx, MATERIAL_FRONT_DIFFUSE);
    148 		context_dirty(ctx, MATERIAL_BACK_DIFFUSE);
    149 		context_dirty(ctx, MATERIAL_FRONT_SPECULAR);
    150 		context_dirty(ctx, MATERIAL_BACK_SPECULAR);
    151 		break;
    152 	case GL_COLOR_SUM_EXT:
    153 		context_dirty(ctx, FRAG);
    154 		context_dirty(ctx, LIGHT_MODEL);
    155 		break;
    156 	case GL_CULL_FACE:
    157 		context_dirty(ctx, CULL_FACE);
    158 		break;
    159 	case GL_DEPTH_TEST:
    160 		context_dirty(ctx, DEPTH);
    161 		break;
    162 	case GL_DITHER:
    163 		context_dirty(ctx, DITHER);
    164 		break;
    165 	case GL_FOG:
    166 		context_dirty(ctx, FOG);
    167 		context_dirty(ctx, FRAG);
    168 		context_dirty(ctx, MODELVIEW);
    169 		break;
    170 	case GL_LIGHT0:
    171 	case GL_LIGHT1:
    172 	case GL_LIGHT2:
    173 	case GL_LIGHT3:
    174 	case GL_LIGHT4:
    175 	case GL_LIGHT5:
    176 	case GL_LIGHT6:
    177 	case GL_LIGHT7:
    178 		context_dirty(ctx, MODELVIEW);
    179 		context_dirty(ctx, LIGHT_ENABLE);
    180 		context_dirty_i(ctx, LIGHT_SOURCE, cap - GL_LIGHT0);
    181 		context_dirty(ctx, MATERIAL_FRONT_AMBIENT);
    182 		context_dirty(ctx, MATERIAL_BACK_AMBIENT);
    183 		context_dirty(ctx, MATERIAL_FRONT_DIFFUSE);
    184 		context_dirty(ctx, MATERIAL_BACK_DIFFUSE);
    185 		context_dirty(ctx, MATERIAL_FRONT_SPECULAR);
    186 		context_dirty(ctx, MATERIAL_BACK_SPECULAR);
    187 		context_dirty(ctx, MATERIAL_FRONT_SHININESS);
    188 		context_dirty(ctx, MATERIAL_BACK_SHININESS);
    189 		break;
    190 	case GL_LIGHTING:
    191 		context_dirty(ctx, FRAG);
    192 		context_dirty(ctx, MODELVIEW);
    193 		context_dirty(ctx, LIGHT_MODEL);
    194 		context_dirty(ctx, LIGHT_ENABLE);
    195 
    196 		for (i = 0; i < MAX_LIGHTS; i++) {
    197 			if (ctx->Light.Light[i].Enabled)
    198 				context_dirty_i(ctx, LIGHT_SOURCE, i);
    199 		}
    200 
    201 		context_dirty(ctx, MATERIAL_FRONT_AMBIENT);
    202 		context_dirty(ctx, MATERIAL_BACK_AMBIENT);
    203 		context_dirty(ctx, MATERIAL_FRONT_DIFFUSE);
    204 		context_dirty(ctx, MATERIAL_BACK_DIFFUSE);
    205 		context_dirty(ctx, MATERIAL_FRONT_SPECULAR);
    206 		context_dirty(ctx, MATERIAL_BACK_SPECULAR);
    207 		context_dirty(ctx, MATERIAL_FRONT_SHININESS);
    208 		context_dirty(ctx, MATERIAL_BACK_SHININESS);
    209 		break;
    210 	case GL_LINE_SMOOTH:
    211 		context_dirty(ctx, LINE_MODE);
    212 		break;
    213 	case GL_NORMALIZE:
    214 		context_dirty(ctx, LIGHT_ENABLE);
    215 		break;
    216 	case GL_POINT_SMOOTH:
    217 		context_dirty(ctx, POINT_MODE);
    218 		break;
    219 	case GL_POLYGON_OFFSET_POINT:
    220 	case GL_POLYGON_OFFSET_LINE:
    221 	case GL_POLYGON_OFFSET_FILL:
    222 		context_dirty(ctx, POLYGON_OFFSET);
    223 		break;
    224 	case GL_POLYGON_SMOOTH:
    225 		context_dirty(ctx, POLYGON_MODE);
    226 		break;
    227 	case GL_SCISSOR_TEST:
    228 		context_dirty(ctx, SCISSOR);
    229 		break;
    230 	case GL_STENCIL_TEST:
    231 		context_dirty(ctx, STENCIL_FUNC);
    232 		break;
    233 	case GL_TEXTURE_1D:
    234 	case GL_TEXTURE_2D:
    235 	case GL_TEXTURE_3D:
    236 	case GL_TEXTURE_RECTANGLE:
    237 		context_dirty_i(ctx, TEX_ENV, ctx->Texture.CurrentUnit);
    238 		context_dirty_i(ctx, TEX_OBJ, ctx->Texture.CurrentUnit);
    239 		break;
    240 	case GL_TEXTURE_GEN_S:
    241 	case GL_TEXTURE_GEN_T:
    242 	case GL_TEXTURE_GEN_R:
    243 	case GL_TEXTURE_GEN_Q:
    244 		context_dirty_i(ctx, TEX_GEN, ctx->Texture.CurrentUnit);
    245 		context_dirty(ctx, MODELVIEW);
    246 		break;
    247 	}
    248 }
    249 
    250 static void
    251 nouveau_fog(struct gl_context *ctx, GLenum pname, const GLfloat *params)
    252 {
    253 	context_dirty(ctx, FOG);
    254 }
    255 
    256 static void
    257 nouveau_light(struct gl_context *ctx, GLenum light, GLenum pname, const GLfloat *params)
    258 {
    259 	switch (pname) {
    260 	case GL_AMBIENT:
    261 		context_dirty(ctx, MATERIAL_FRONT_AMBIENT);
    262 		context_dirty(ctx, MATERIAL_BACK_AMBIENT);
    263 		break;
    264 	case GL_DIFFUSE:
    265 		context_dirty(ctx, MATERIAL_FRONT_DIFFUSE);
    266 		context_dirty(ctx, MATERIAL_BACK_DIFFUSE);
    267 		break;
    268 	case GL_SPECULAR:
    269 		context_dirty(ctx, MATERIAL_FRONT_SPECULAR);
    270 		context_dirty(ctx, MATERIAL_BACK_SPECULAR);
    271 		break;
    272 	case GL_SPOT_CUTOFF:
    273 	case GL_POSITION:
    274 		context_dirty(ctx, MODELVIEW);
    275 		context_dirty(ctx, LIGHT_ENABLE);
    276 		context_dirty_i(ctx, LIGHT_SOURCE, light - GL_LIGHT0);
    277 		break;
    278 	default:
    279 		context_dirty_i(ctx, LIGHT_SOURCE, light - GL_LIGHT0);
    280 		break;
    281 	}
    282 }
    283 
    284 static void
    285 nouveau_light_model(struct gl_context *ctx, GLenum pname, const GLfloat *params)
    286 {
    287 	context_dirty(ctx, LIGHT_MODEL);
    288 	context_dirty(ctx, MODELVIEW);
    289 }
    290 
    291 static void
    292 nouveau_line_stipple(struct gl_context *ctx, GLint factor, GLushort pattern )
    293 {
    294 	context_dirty(ctx, LINE_STIPPLE);
    295 }
    296 
    297 static void
    298 nouveau_line_width(struct gl_context *ctx, GLfloat width)
    299 {
    300 	context_dirty(ctx, LINE_MODE);
    301 }
    302 
    303 static void
    304 nouveau_logic_opcode(struct gl_context *ctx, GLenum opcode)
    305 {
    306 	context_dirty(ctx, LOGIC_OPCODE);
    307 }
    308 
    309 static void
    310 nouveau_point_parameter(struct gl_context *ctx, GLenum pname, const GLfloat *params)
    311 {
    312 	context_dirty(ctx, POINT_PARAMETER);
    313 }
    314 
    315 static void
    316 nouveau_point_size(struct gl_context *ctx, GLfloat size)
    317 {
    318 	context_dirty(ctx, POINT_MODE);
    319 }
    320 
    321 static void
    322 nouveau_polygon_mode(struct gl_context *ctx, GLenum face, GLenum mode)
    323 {
    324 	context_dirty(ctx, POLYGON_MODE);
    325 }
    326 
    327 static void
    328 nouveau_polygon_offset(struct gl_context *ctx, GLfloat factor, GLfloat units)
    329 {
    330 	context_dirty(ctx, POLYGON_OFFSET);
    331 }
    332 
    333 static void
    334 nouveau_polygon_stipple(struct gl_context *ctx, const GLubyte *mask)
    335 {
    336 	context_dirty(ctx, POLYGON_STIPPLE);
    337 }
    338 
    339 static void
    340 nouveau_render_mode(struct gl_context *ctx, GLenum mode)
    341 {
    342 	context_dirty(ctx, RENDER_MODE);
    343 }
    344 
    345 static void
    346 nouveau_scissor(struct gl_context *ctx, GLint x, GLint y, GLsizei w, GLsizei h)
    347 {
    348 	context_dirty(ctx, SCISSOR);
    349 }
    350 
    351 static void
    352 nouveau_shade_model(struct gl_context *ctx, GLenum mode)
    353 {
    354 	context_dirty(ctx, SHADE_MODEL);
    355 }
    356 
    357 static void
    358 nouveau_stencil_func_separate(struct gl_context *ctx, GLenum face, GLenum func,
    359 			      GLint ref, GLuint mask)
    360 {
    361 	context_dirty(ctx, STENCIL_FUNC);
    362 }
    363 
    364 static void
    365 nouveau_stencil_mask_separate(struct gl_context *ctx, GLenum face, GLuint mask)
    366 {
    367 	context_dirty(ctx, STENCIL_MASK);
    368 }
    369 
    370 static void
    371 nouveau_stencil_op_separate(struct gl_context *ctx, GLenum face, GLenum fail,
    372 			    GLenum zfail, GLenum zpass)
    373 {
    374 	context_dirty(ctx, STENCIL_OP);
    375 }
    376 
    377 static void
    378 nouveau_tex_gen(struct gl_context *ctx, GLenum coord, GLenum pname,
    379 		const GLfloat *params)
    380 {
    381 	switch (pname) {
    382 	case GL_TEXTURE_GEN_MODE:
    383 		context_dirty_i(ctx, TEX_GEN, ctx->Texture.CurrentUnit);
    384 		context_dirty(ctx, MODELVIEW);
    385 		break;
    386 	default:
    387 		context_dirty_i(ctx, TEX_GEN, ctx->Texture.CurrentUnit);
    388 		break;
    389 	}
    390 }
    391 
    392 static void
    393 nouveau_tex_env(struct gl_context *ctx, GLenum target, GLenum pname,
    394 		const GLfloat *param)
    395 {
    396 	switch (target) {
    397 	case GL_TEXTURE_FILTER_CONTROL_EXT:
    398 		context_dirty_i(ctx, TEX_OBJ, ctx->Texture.CurrentUnit);
    399 		break;
    400 	default:
    401 		context_dirty_i(ctx, TEX_ENV, ctx->Texture.CurrentUnit);
    402 		break;
    403 	}
    404 }
    405 
    406 static void
    407 nouveau_tex_parameter(struct gl_context *ctx, GLenum target,
    408 		      struct gl_texture_object *t, GLenum pname,
    409 		      const GLfloat *params)
    410 {
    411 	switch (pname) {
    412 	case GL_TEXTURE_MAG_FILTER:
    413 	case GL_TEXTURE_WRAP_S:
    414 	case GL_TEXTURE_WRAP_T:
    415 	case GL_TEXTURE_WRAP_R:
    416 	case GL_TEXTURE_MIN_LOD:
    417 	case GL_TEXTURE_MAX_LOD:
    418 	case GL_TEXTURE_MAX_ANISOTROPY_EXT:
    419 	case GL_TEXTURE_LOD_BIAS:
    420 		context_dirty_i(ctx, TEX_OBJ, ctx->Texture.CurrentUnit);
    421 		break;
    422 
    423 	case GL_TEXTURE_MIN_FILTER:
    424 	case GL_TEXTURE_BASE_LEVEL:
    425 	case GL_TEXTURE_MAX_LEVEL:
    426 		nouveau_texture_reallocate(ctx, t);
    427 		context_dirty_i(ctx, TEX_OBJ, ctx->Texture.CurrentUnit);
    428 		break;
    429 	}
    430 }
    431 
    432 static void
    433 nouveau_viewport(struct gl_context *ctx, GLint x, GLint y, GLsizei w, GLsizei h)
    434 {
    435 	context_dirty(ctx, VIEWPORT);
    436 }
    437 
    438 void
    439 nouveau_emit_nothing(struct gl_context *ctx, int emit)
    440 {
    441 }
    442 
    443 int
    444 nouveau_next_dirty_state(struct gl_context *ctx)
    445 {
    446 	struct nouveau_context *nctx = to_nouveau_context(ctx);
    447 	int i = BITSET_FFS(nctx->dirty) - 1;
    448 
    449 	if (i < 0 || i >= context_drv(ctx)->num_emit)
    450 		return -1;
    451 
    452 	return i;
    453 }
    454 
    455 void
    456 nouveau_state_emit(struct gl_context *ctx)
    457 {
    458 	struct nouveau_context *nctx = to_nouveau_context(ctx);
    459 	const struct nouveau_driver *drv = context_drv(ctx);
    460 	int i;
    461 
    462 	while ((i = nouveau_next_dirty_state(ctx)) >= 0) {
    463 		BITSET_CLEAR(nctx->dirty, i);
    464 		drv->emit[i](ctx, i);
    465 	}
    466 
    467 	BITSET_ZERO(nctx->dirty);
    468 }
    469 
    470 static void
    471 nouveau_update_state(struct gl_context *ctx, GLbitfield new_state)
    472 {
    473 	int i;
    474 
    475 	if (new_state & (_NEW_PROJECTION | _NEW_MODELVIEW))
    476 		context_dirty(ctx, PROJECTION);
    477 
    478 	if (new_state & _NEW_MODELVIEW)
    479 		context_dirty(ctx, MODELVIEW);
    480 
    481 	if (new_state & _NEW_TEXTURE_MATRIX) {
    482 		for (i = 0; i < ctx->Const.MaxTextureCoordUnits; i++)
    483 			context_dirty_i(ctx, TEX_MAT, i);
    484 	}
    485 
    486 	if (new_state & _NEW_CURRENT_ATTRIB &&
    487 	    new_state & _NEW_LIGHT) {
    488 		context_dirty(ctx, MATERIAL_FRONT_AMBIENT);
    489 		context_dirty(ctx, MATERIAL_BACK_AMBIENT);
    490 		context_dirty(ctx, MATERIAL_FRONT_DIFFUSE);
    491 		context_dirty(ctx, MATERIAL_BACK_DIFFUSE);
    492 		context_dirty(ctx, MATERIAL_FRONT_SPECULAR);
    493 		context_dirty(ctx, MATERIAL_BACK_SPECULAR);
    494 		context_dirty(ctx, MATERIAL_FRONT_SHININESS);
    495 		context_dirty(ctx, MATERIAL_BACK_SHININESS);
    496 	}
    497 
    498 	if (new_state & _NEW_TEXTURE) {
    499 		for (i = 0; i < ctx->Const.MaxTextureUnits; i++) {
    500 			if (ctx->Texture.Unit[i].Sampler)
    501 				context_dirty_i(ctx, TEX_OBJ, i);
    502 		}
    503 	}
    504 
    505 	_swrast_InvalidateState(ctx, new_state);
    506 	_tnl_InvalidateState(ctx, new_state);
    507 
    508 	nouveau_state_emit(ctx);
    509 }
    510 
    511 void
    512 nouveau_state_init(struct gl_context *ctx)
    513 {
    514 	struct nouveau_context *nctx = to_nouveau_context(ctx);
    515 
    516 	ctx->Driver.AlphaFunc = nouveau_alpha_func;
    517 	ctx->Driver.BlendColor = nouveau_blend_color;
    518 	ctx->Driver.BlendEquationSeparate = nouveau_blend_equation_separate;
    519 	ctx->Driver.BlendFuncSeparate = nouveau_blend_func_separate;
    520 	ctx->Driver.ClipPlane = nouveau_clip_plane;
    521 	ctx->Driver.ColorMask = nouveau_color_mask;
    522 	ctx->Driver.ColorMaterial = nouveau_color_material;
    523 	ctx->Driver.CullFace = nouveau_cull_face;
    524 	ctx->Driver.FrontFace = nouveau_front_face;
    525 	ctx->Driver.DepthFunc = nouveau_depth_func;
    526 	ctx->Driver.DepthMask = nouveau_depth_mask;
    527 	ctx->Driver.DepthRange = nouveau_depth_range;
    528 	ctx->Driver.ReadBuffer = nouveau_read_buffer;
    529 	ctx->Driver.DrawBuffers = nouveau_draw_buffers;
    530 	ctx->Driver.Enable = nouveau_enable;
    531 	ctx->Driver.Fogfv = nouveau_fog;
    532 	ctx->Driver.Lightfv = nouveau_light;
    533 	ctx->Driver.LightModelfv = nouveau_light_model;
    534 	ctx->Driver.LineStipple = nouveau_line_stipple;
    535 	ctx->Driver.LineWidth = nouveau_line_width;
    536 	ctx->Driver.LogicOpcode = nouveau_logic_opcode;
    537 	ctx->Driver.PointParameterfv = nouveau_point_parameter;
    538 	ctx->Driver.PointSize = nouveau_point_size;
    539 	ctx->Driver.PolygonMode = nouveau_polygon_mode;
    540 	ctx->Driver.PolygonOffset = nouveau_polygon_offset;
    541 	ctx->Driver.PolygonStipple = nouveau_polygon_stipple;
    542 	ctx->Driver.RenderMode = nouveau_render_mode;
    543 	ctx->Driver.Scissor = nouveau_scissor;
    544 	ctx->Driver.ShadeModel = nouveau_shade_model;
    545 	ctx->Driver.StencilFuncSeparate = nouveau_stencil_func_separate;
    546 	ctx->Driver.StencilMaskSeparate = nouveau_stencil_mask_separate;
    547 	ctx->Driver.StencilOpSeparate = nouveau_stencil_op_separate;
    548 	ctx->Driver.TexGen = nouveau_tex_gen;
    549 	ctx->Driver.TexEnv = nouveau_tex_env;
    550 	ctx->Driver.TexParameter = nouveau_tex_parameter;
    551 	ctx->Driver.Viewport = nouveau_viewport;
    552 
    553 	ctx->Driver.UpdateState = nouveau_update_state;
    554 
    555 	BITSET_ONES(nctx->dirty);
    556 }
    557