OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "gpu/command_buffer/service/gles2_cmd_decoder.h" | 5 #include "gpu/command_buffer/service/gles2_cmd_decoder.h" |
6 | 6 |
7 #include <stdio.h> | 7 #include <stdio.h> |
8 | 8 |
9 #include <algorithm> | 9 #include <algorithm> |
10 #include <list> | 10 #include <list> |
(...skipping 1273 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1284 NOTREACHED(); | 1284 NOTREACHED(); |
1285 return 0; | 1285 return 0; |
1286 } | 1286 } |
1287 | 1287 |
1288 // Gets the framebuffer info for a particular target. | 1288 // Gets the framebuffer info for a particular target. |
1289 FramebufferManager::FramebufferInfo* GetFramebufferInfoForTarget( | 1289 FramebufferManager::FramebufferInfo* GetFramebufferInfoForTarget( |
1290 GLenum target) { | 1290 GLenum target) { |
1291 FramebufferManager::FramebufferInfo* info = NULL; | 1291 FramebufferManager::FramebufferInfo* info = NULL; |
1292 switch (target) { | 1292 switch (target) { |
1293 case GL_FRAMEBUFFER: | 1293 case GL_FRAMEBUFFER: |
1294 case GL_DRAW_FRAMEBUFFER: | 1294 case GL_DRAW_FRAMEBUFFER_EXT: |
1295 info = bound_draw_framebuffer_; | 1295 info = bound_draw_framebuffer_; |
1296 break; | 1296 break; |
1297 case GL_READ_FRAMEBUFFER: | 1297 case GL_READ_FRAMEBUFFER_EXT: |
1298 info = bound_read_framebuffer_; | 1298 info = bound_read_framebuffer_; |
1299 break; | 1299 break; |
1300 default: | 1300 default: |
1301 NOTREACHED(); | 1301 NOTREACHED(); |
1302 break; | 1302 break; |
1303 } | 1303 } |
1304 return info; | 1304 return info; |
1305 } | 1305 } |
1306 | 1306 |
1307 RenderbufferManager::RenderbufferInfo* GetRenderbufferInfoForTarget( | 1307 RenderbufferManager::RenderbufferInfo* GetRenderbufferInfoForTarget( |
(...skipping 1183 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2491 if (bound_element_array_buffer_ == buffer) { | 2491 if (bound_element_array_buffer_ == buffer) { |
2492 bound_element_array_buffer_ = NULL; | 2492 bound_element_array_buffer_ = NULL; |
2493 } | 2493 } |
2494 RemoveBufferInfo(client_ids[ii]); | 2494 RemoveBufferInfo(client_ids[ii]); |
2495 } | 2495 } |
2496 } | 2496 } |
2497 } | 2497 } |
2498 | 2498 |
2499 void GLES2DecoderImpl::DeleteFramebuffersHelper( | 2499 void GLES2DecoderImpl::DeleteFramebuffersHelper( |
2500 GLsizei n, const GLuint* client_ids) { | 2500 GLsizei n, const GLuint* client_ids) { |
2501 bool supports_seperate_framebuffer_binds = | 2501 bool supports_separate_framebuffer_binds = |
2502 feature_info_->feature_flags().chromium_framebuffer_multisample; | 2502 feature_info_->feature_flags().chromium_framebuffer_multisample; |
2503 | 2503 |
2504 for (GLsizei ii = 0; ii < n; ++ii) { | 2504 for (GLsizei ii = 0; ii < n; ++ii) { |
2505 FramebufferManager::FramebufferInfo* framebuffer = | 2505 FramebufferManager::FramebufferInfo* framebuffer = |
2506 GetFramebufferInfo(client_ids[ii]); | 2506 GetFramebufferInfo(client_ids[ii]); |
2507 if (framebuffer && !framebuffer->IsDeleted()) { | 2507 if (framebuffer && !framebuffer->IsDeleted()) { |
2508 if (framebuffer == bound_draw_framebuffer_) { | 2508 if (framebuffer == bound_draw_framebuffer_) { |
2509 bound_draw_framebuffer_ = NULL; | 2509 bound_draw_framebuffer_ = NULL; |
2510 state_dirty_ = true; | 2510 state_dirty_ = true; |
2511 GLenum target = supports_seperate_framebuffer_binds ? | 2511 GLenum target = supports_separate_framebuffer_binds ? |
2512 GL_DRAW_FRAMEBUFFER : GL_FRAMEBUFFER; | 2512 GL_DRAW_FRAMEBUFFER_EXT : GL_FRAMEBUFFER; |
2513 glBindFramebufferEXT(target, GetBackbufferServiceId()); | 2513 glBindFramebufferEXT(target, GetBackbufferServiceId()); |
2514 } | 2514 } |
2515 if (framebuffer == bound_read_framebuffer_) { | 2515 if (framebuffer == bound_read_framebuffer_) { |
2516 bound_read_framebuffer_ = NULL; | 2516 bound_read_framebuffer_ = NULL; |
2517 GLenum target = supports_seperate_framebuffer_binds ? | 2517 GLenum target = supports_separate_framebuffer_binds ? |
2518 GL_READ_FRAMEBUFFER : GL_FRAMEBUFFER; | 2518 GL_READ_FRAMEBUFFER_EXT : GL_FRAMEBUFFER; |
2519 glBindFramebufferEXT(target, GetBackbufferServiceId()); | 2519 glBindFramebufferEXT(target, GetBackbufferServiceId()); |
2520 } | 2520 } |
2521 RemoveFramebufferInfo(client_ids[ii]); | 2521 RemoveFramebufferInfo(client_ids[ii]); |
2522 } | 2522 } |
2523 } | 2523 } |
2524 } | 2524 } |
2525 | 2525 |
2526 void GLES2DecoderImpl::DeleteRenderbuffersHelper( | 2526 void GLES2DecoderImpl::DeleteRenderbuffersHelper( |
2527 GLsizei n, const GLuint* client_ids) { | 2527 GLsizei n, const GLuint* client_ids) { |
2528 bool supports_seperate_framebuffer_binds = | 2528 bool supports_separate_framebuffer_binds = |
2529 feature_info_->feature_flags().chromium_framebuffer_multisample; | 2529 feature_info_->feature_flags().chromium_framebuffer_multisample; |
2530 for (GLsizei ii = 0; ii < n; ++ii) { | 2530 for (GLsizei ii = 0; ii < n; ++ii) { |
2531 RenderbufferManager::RenderbufferInfo* renderbuffer = | 2531 RenderbufferManager::RenderbufferInfo* renderbuffer = |
2532 GetRenderbufferInfo(client_ids[ii]); | 2532 GetRenderbufferInfo(client_ids[ii]); |
2533 if (renderbuffer && !renderbuffer->IsDeleted()) { | 2533 if (renderbuffer && !renderbuffer->IsDeleted()) { |
2534 if (bound_renderbuffer_ == renderbuffer) { | 2534 if (bound_renderbuffer_ == renderbuffer) { |
2535 bound_renderbuffer_ = NULL; | 2535 bound_renderbuffer_ = NULL; |
2536 } | 2536 } |
2537 // Unbind from current framebuffers. | 2537 // Unbind from current framebuffers. |
2538 if (supports_seperate_framebuffer_binds) { | 2538 if (supports_separate_framebuffer_binds) { |
2539 if (bound_read_framebuffer_) { | 2539 if (bound_read_framebuffer_) { |
2540 bound_read_framebuffer_->UnbindRenderbuffer( | 2540 bound_read_framebuffer_->UnbindRenderbuffer( |
2541 GL_READ_FRAMEBUFFER, renderbuffer); | 2541 GL_READ_FRAMEBUFFER_EXT, renderbuffer); |
2542 } | 2542 } |
2543 if (bound_draw_framebuffer_) { | 2543 if (bound_draw_framebuffer_) { |
2544 bound_draw_framebuffer_->UnbindRenderbuffer( | 2544 bound_draw_framebuffer_->UnbindRenderbuffer( |
2545 GL_DRAW_FRAMEBUFFER, renderbuffer); | 2545 GL_DRAW_FRAMEBUFFER_EXT, renderbuffer); |
2546 } | 2546 } |
2547 } else { | 2547 } else { |
2548 if (bound_draw_framebuffer_) { | 2548 if (bound_draw_framebuffer_) { |
2549 bound_draw_framebuffer_->UnbindRenderbuffer( | 2549 bound_draw_framebuffer_->UnbindRenderbuffer( |
2550 GL_FRAMEBUFFER, renderbuffer); | 2550 GL_FRAMEBUFFER, renderbuffer); |
2551 } | 2551 } |
2552 } | 2552 } |
2553 state_dirty_ = true; | 2553 state_dirty_ = true; |
2554 RemoveRenderbufferInfo(client_ids[ii]); | 2554 RemoveRenderbufferInfo(client_ids[ii]); |
2555 } | 2555 } |
2556 } | 2556 } |
2557 } | 2557 } |
2558 | 2558 |
2559 void GLES2DecoderImpl::DeleteTexturesHelper( | 2559 void GLES2DecoderImpl::DeleteTexturesHelper( |
2560 GLsizei n, const GLuint* client_ids) { | 2560 GLsizei n, const GLuint* client_ids) { |
2561 bool supports_seperate_framebuffer_binds = | 2561 bool supports_separate_framebuffer_binds = |
2562 feature_info_->feature_flags().chromium_framebuffer_multisample; | 2562 feature_info_->feature_flags().chromium_framebuffer_multisample; |
2563 for (GLsizei ii = 0; ii < n; ++ii) { | 2563 for (GLsizei ii = 0; ii < n; ++ii) { |
2564 TextureManager::TextureInfo* texture = GetTextureInfo(client_ids[ii]); | 2564 TextureManager::TextureInfo* texture = GetTextureInfo(client_ids[ii]); |
2565 if (texture && !texture->IsDeleted()) { | 2565 if (texture && !texture->IsDeleted()) { |
2566 if (texture->IsAttachedToFramebuffer()) { | 2566 if (texture->IsAttachedToFramebuffer()) { |
2567 state_dirty_ = true; | 2567 state_dirty_ = true; |
2568 } | 2568 } |
2569 // Unbind texture from texture units. | 2569 // Unbind texture from texture units. |
2570 for (size_t jj = 0; jj < group_->max_texture_units(); ++jj) { | 2570 for (size_t jj = 0; jj < group_->max_texture_units(); ++jj) { |
2571 texture_units_[ii].Unbind(texture); | 2571 texture_units_[ii].Unbind(texture); |
2572 } | 2572 } |
2573 // Unbind from current framebuffers. | 2573 // Unbind from current framebuffers. |
2574 if (supports_seperate_framebuffer_binds) { | 2574 if (supports_separate_framebuffer_binds) { |
2575 if (bound_read_framebuffer_) { | 2575 if (bound_read_framebuffer_) { |
2576 bound_read_framebuffer_->UnbindTexture(GL_READ_FRAMEBUFFER, texture); | 2576 bound_read_framebuffer_->UnbindTexture( |
| 2577 GL_READ_FRAMEBUFFER_EXT, texture); |
2577 } | 2578 } |
2578 if (bound_draw_framebuffer_) { | 2579 if (bound_draw_framebuffer_) { |
2579 bound_draw_framebuffer_->UnbindTexture(GL_DRAW_FRAMEBUFFER, texture); | 2580 bound_draw_framebuffer_->UnbindTexture( |
| 2581 GL_DRAW_FRAMEBUFFER_EXT, texture); |
2580 } | 2582 } |
2581 } else { | 2583 } else { |
2582 if (bound_draw_framebuffer_) { | 2584 if (bound_draw_framebuffer_) { |
2583 bound_draw_framebuffer_->UnbindTexture(GL_FRAMEBUFFER, texture); | 2585 bound_draw_framebuffer_->UnbindTexture(GL_FRAMEBUFFER, texture); |
2584 } | 2586 } |
2585 } | 2587 } |
2586 GLuint service_id = texture->service_id(); | 2588 GLuint service_id = texture->service_id(); |
2587 if (texture->IsStreamTexture() && stream_texture_manager_) { | 2589 if (texture->IsStreamTexture() && stream_texture_manager_) { |
2588 stream_texture_manager_->DestroyStreamTexture(service_id); | 2590 stream_texture_manager_->DestroyStreamTexture(service_id); |
2589 } | 2591 } |
(...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2723 bound_draw_framebuffer_, GL_FRAMEBUFFER_EXT, func_name); | 2725 bound_draw_framebuffer_, GL_FRAMEBUFFER_EXT, func_name); |
2724 } | 2726 } |
2725 return CheckFramebufferValid( | 2727 return CheckFramebufferValid( |
2726 bound_draw_framebuffer_, GL_DRAW_FRAMEBUFFER_EXT, func_name) && | 2728 bound_draw_framebuffer_, GL_DRAW_FRAMEBUFFER_EXT, func_name) && |
2727 CheckFramebufferValid( | 2729 CheckFramebufferValid( |
2728 bound_read_framebuffer_, GL_READ_FRAMEBUFFER_EXT, func_name); | 2730 bound_read_framebuffer_, GL_READ_FRAMEBUFFER_EXT, func_name); |
2729 } | 2731 } |
2730 | 2732 |
2731 gfx::Size GLES2DecoderImpl::GetBoundReadFrameBufferSize() { | 2733 gfx::Size GLES2DecoderImpl::GetBoundReadFrameBufferSize() { |
2732 FramebufferManager::FramebufferInfo* framebuffer = | 2734 FramebufferManager::FramebufferInfo* framebuffer = |
2733 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER); | 2735 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER_EXT); |
2734 if (framebuffer != NULL) { | 2736 if (framebuffer != NULL) { |
2735 const FramebufferManager::FramebufferInfo::Attachment* attachment = | 2737 const FramebufferManager::FramebufferInfo::Attachment* attachment = |
2736 framebuffer->GetAttachment(GL_COLOR_ATTACHMENT0); | 2738 framebuffer->GetAttachment(GL_COLOR_ATTACHMENT0); |
2737 if (attachment) { | 2739 if (attachment) { |
2738 return gfx::Size(attachment->width(), attachment->height()); | 2740 return gfx::Size(attachment->width(), attachment->height()); |
2739 } | 2741 } |
2740 return gfx::Size(0, 0); | 2742 return gfx::Size(0, 0); |
2741 } else if (offscreen_target_frame_buffer_.get()) { | 2743 } else if (offscreen_target_frame_buffer_.get()) { |
2742 return offscreen_size_; | 2744 return offscreen_size_; |
2743 } else { | 2745 } else { |
2744 return surface_->GetSize(); | 2746 return surface_->GetSize(); |
2745 } | 2747 } |
2746 } | 2748 } |
2747 | 2749 |
2748 GLenum GLES2DecoderImpl::GetBoundReadFrameBufferInternalFormat() { | 2750 GLenum GLES2DecoderImpl::GetBoundReadFrameBufferInternalFormat() { |
2749 FramebufferManager::FramebufferInfo* framebuffer = | 2751 FramebufferManager::FramebufferInfo* framebuffer = |
2750 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER); | 2752 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER_EXT); |
2751 if (framebuffer != NULL) { | 2753 if (framebuffer != NULL) { |
2752 return framebuffer->GetColorAttachmentFormat(); | 2754 return framebuffer->GetColorAttachmentFormat(); |
2753 } else if (offscreen_target_frame_buffer_.get()) { | 2755 } else if (offscreen_target_frame_buffer_.get()) { |
2754 return offscreen_target_color_format_; | 2756 return offscreen_target_color_format_; |
2755 } else { | 2757 } else { |
2756 return back_buffer_color_format_; | 2758 return back_buffer_color_format_; |
2757 } | 2759 } |
2758 } | 2760 } |
2759 | 2761 |
2760 GLenum GLES2DecoderImpl::GetBoundDrawFrameBufferInternalFormat() { | 2762 GLenum GLES2DecoderImpl::GetBoundDrawFrameBufferInternalFormat() { |
2761 FramebufferManager::FramebufferInfo* framebuffer = | 2763 FramebufferManager::FramebufferInfo* framebuffer = |
2762 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER); | 2764 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT); |
2763 if (framebuffer != NULL) { | 2765 if (framebuffer != NULL) { |
2764 return framebuffer->GetColorAttachmentFormat(); | 2766 return framebuffer->GetColorAttachmentFormat(); |
2765 } else if (offscreen_target_frame_buffer_.get()) { | 2767 } else if (offscreen_target_frame_buffer_.get()) { |
2766 return offscreen_target_color_format_; | 2768 return offscreen_target_color_format_; |
2767 } else { | 2769 } else { |
2768 return back_buffer_color_format_; | 2770 return back_buffer_color_format_; |
2769 } | 2771 } |
2770 } | 2772 } |
2771 | 2773 |
2772 void GLES2DecoderImpl::UpdateParentTextureInfo() { | 2774 void GLES2DecoderImpl::UpdateParentTextureInfo() { |
(...skipping 573 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3346 glBindBuffer(target, service_id); | 3348 glBindBuffer(target, service_id); |
3347 } | 3349 } |
3348 | 3350 |
3349 bool GLES2DecoderImpl::BoundFramebufferHasColorAttachmentWithAlpha() { | 3351 bool GLES2DecoderImpl::BoundFramebufferHasColorAttachmentWithAlpha() { |
3350 return (GLES2Util::GetChannelsForFormat( | 3352 return (GLES2Util::GetChannelsForFormat( |
3351 GetBoundDrawFrameBufferInternalFormat()) & 0x0008) != 0; | 3353 GetBoundDrawFrameBufferInternalFormat()) & 0x0008) != 0; |
3352 } | 3354 } |
3353 | 3355 |
3354 bool GLES2DecoderImpl::BoundFramebufferHasDepthAttachment() { | 3356 bool GLES2DecoderImpl::BoundFramebufferHasDepthAttachment() { |
3355 FramebufferManager::FramebufferInfo* framebuffer = | 3357 FramebufferManager::FramebufferInfo* framebuffer = |
3356 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER); | 3358 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT); |
3357 if (framebuffer) { | 3359 if (framebuffer) { |
3358 return framebuffer->HasDepthAttachment(); | 3360 return framebuffer->HasDepthAttachment(); |
3359 } | 3361 } |
3360 if (offscreen_target_frame_buffer_.get()) { | 3362 if (offscreen_target_frame_buffer_.get()) { |
3361 return offscreen_target_depth_format_ != 0; | 3363 return offscreen_target_depth_format_ != 0; |
3362 } | 3364 } |
3363 return back_buffer_has_depth_; | 3365 return back_buffer_has_depth_; |
3364 } | 3366 } |
3365 | 3367 |
3366 bool GLES2DecoderImpl::BoundFramebufferHasStencilAttachment() { | 3368 bool GLES2DecoderImpl::BoundFramebufferHasStencilAttachment() { |
3367 FramebufferManager::FramebufferInfo* framebuffer = | 3369 FramebufferManager::FramebufferInfo* framebuffer = |
3368 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER); | 3370 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT); |
3369 if (framebuffer) { | 3371 if (framebuffer) { |
3370 return framebuffer->HasStencilAttachment(); | 3372 return framebuffer->HasStencilAttachment(); |
3371 } | 3373 } |
3372 if (offscreen_target_frame_buffer_.get()) { | 3374 if (offscreen_target_frame_buffer_.get()) { |
3373 return offscreen_target_stencil_format_ != 0 || | 3375 return offscreen_target_stencil_format_ != 0 || |
3374 offscreen_target_depth_format_ == GL_DEPTH24_STENCIL8; | 3376 offscreen_target_depth_format_ == GL_DEPTH24_STENCIL8; |
3375 } | 3377 } |
3376 return back_buffer_has_stencil_; | 3378 return back_buffer_has_stencil_; |
3377 } | 3379 } |
3378 | 3380 |
(...skipping 422 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3801 } else { | 3803 } else { |
3802 *params = 0; | 3804 *params = 0; |
3803 } | 3805 } |
3804 } | 3806 } |
3805 return true; | 3807 return true; |
3806 case GL_FRAMEBUFFER_BINDING: | 3808 case GL_FRAMEBUFFER_BINDING: |
3807 // case GL_DRAW_FRAMEBUFFER_BINDING_EXT: (same as GL_FRAMEBUFFER_BINDING) | 3809 // case GL_DRAW_FRAMEBUFFER_BINDING_EXT: (same as GL_FRAMEBUFFER_BINDING) |
3808 *num_written = 1; | 3810 *num_written = 1; |
3809 if (params) { | 3811 if (params) { |
3810 FramebufferManager::FramebufferInfo* framebuffer = | 3812 FramebufferManager::FramebufferInfo* framebuffer = |
3811 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER); | 3813 GetFramebufferInfoForTarget(GL_FRAMEBUFFER); |
3812 if (framebuffer) { | 3814 if (framebuffer) { |
3813 GLuint client_id = 0; | 3815 GLuint client_id = 0; |
3814 framebuffer_manager()->GetClientId( | 3816 framebuffer_manager()->GetClientId( |
3815 framebuffer->service_id(), &client_id); | 3817 framebuffer->service_id(), &client_id); |
3816 *params = client_id; | 3818 *params = client_id; |
3817 } else { | 3819 } else { |
3818 *params = 0; | 3820 *params = 0; |
3819 } | 3821 } |
3820 } | 3822 } |
3821 return true; | 3823 return true; |
3822 case GL_READ_FRAMEBUFFER_BINDING: | 3824 case GL_READ_FRAMEBUFFER_BINDING_EXT: |
3823 *num_written = 1; | 3825 *num_written = 1; |
3824 if (params) { | 3826 if (params) { |
3825 FramebufferManager::FramebufferInfo* framebuffer = | 3827 FramebufferManager::FramebufferInfo* framebuffer = |
3826 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER); | 3828 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER_EXT); |
3827 if (framebuffer) { | 3829 if (framebuffer) { |
3828 GLuint client_id = 0; | 3830 GLuint client_id = 0; |
3829 framebuffer_manager()->GetClientId( | 3831 framebuffer_manager()->GetClientId( |
3830 framebuffer->service_id(), &client_id); | 3832 framebuffer->service_id(), &client_id); |
3831 *params = client_id; | 3833 *params = client_id; |
3832 } else { | 3834 } else { |
3833 *params = 0; | 3835 *params = 0; |
3834 } | 3836 } |
3835 } | 3837 } |
3836 return true; | 3838 return true; |
(...skipping 5396 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
9233 } | 9235 } |
9234 | 9236 |
9235 | 9237 |
9236 // Include the auto-generated part of this file. We split this because it means | 9238 // Include the auto-generated part of this file. We split this because it means |
9237 // we can easily edit the non-auto generated parts right here in this file | 9239 // we can easily edit the non-auto generated parts right here in this file |
9238 // instead of having to edit some template or the code generator. | 9240 // instead of having to edit some template or the code generator. |
9239 #include "gpu/command_buffer/service/gles2_cmd_decoder_autogen.h" | 9241 #include "gpu/command_buffer/service/gles2_cmd_decoder_autogen.h" |
9240 | 9242 |
9241 } // namespace gles2 | 9243 } // namespace gles2 |
9242 } // namespace gpu | 9244 } // namespace gpu |
OLD | NEW |