| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright 2012 Google Inc. | 2 * Copyright 2012 Google Inc. |
| 3 * | 3 * |
| 4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
| 5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
| 6 */ | 6 */ |
| 7 | 7 |
| 8 | 8 |
| 9 #include "GrGLCaps.h" | 9 #include "GrGLCaps.h" |
| 10 | 10 |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 42 fVertexArrayObjectSupport = false; | 42 fVertexArrayObjectSupport = false; |
| 43 fInstancedDrawingSupport = false; | 43 fInstancedDrawingSupport = false; |
| 44 fDirectStateAccessSupport = false; | 44 fDirectStateAccessSupport = false; |
| 45 fDebugSupport = false; | 45 fDebugSupport = false; |
| 46 fES2CompatibilitySupport = false; | 46 fES2CompatibilitySupport = false; |
| 47 fMultisampleDisableSupport = false; | 47 fMultisampleDisableSupport = false; |
| 48 fUseNonVBOVertexAndIndexDynamicData = false; | 48 fUseNonVBOVertexAndIndexDynamicData = false; |
| 49 fIsCoreProfile = false; | 49 fIsCoreProfile = false; |
| 50 fFullClearIsFree = false; | 50 fFullClearIsFree = false; |
| 51 fBindFragDataLocationSupport = false; | 51 fBindFragDataLocationSupport = false; |
| 52 fSRGBWriteControl = false; |
| 52 | 53 |
| 53 fReadPixelsSupportedCache.reset(); | 54 fReadPixelsSupportedCache.reset(); |
| 54 | 55 |
| 55 fShaderCaps.reset(SkNEW_ARGS(GrGLSLCaps, (contextOptions))); | 56 fShaderCaps.reset(SkNEW_ARGS(GrGLSLCaps, (contextOptions))); |
| 56 | 57 |
| 57 this->init(contextOptions, ctxInfo, glInterface); | 58 this->init(contextOptions, ctxInfo, glInterface); |
| 58 } | 59 } |
| 59 | 60 |
| 60 void GrGLCaps::init(const GrContextOptions& contextOptions, | 61 void GrGLCaps::init(const GrContextOptions& contextOptions, |
| 61 const GrGLContextInfo& ctxInfo, | 62 const GrGLContextInfo& ctxInfo, |
| (...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 184 } | 185 } |
| 185 } | 186 } |
| 186 fImagingSupport = kGL_GrGLStandard == standard && | 187 fImagingSupport = kGL_GrGLStandard == standard && |
| 187 ctxInfo.hasExtension("GL_ARB_imaging"); | 188 ctxInfo.hasExtension("GL_ARB_imaging"); |
| 188 | 189 |
| 189 // ES 2 only guarantees RGBA/uchar + one other format/type combo for | 190 // ES 2 only guarantees RGBA/uchar + one other format/type combo for |
| 190 // ReadPixels. The other format has to checked at run-time since it | 191 // ReadPixels. The other format has to checked at run-time since it |
| 191 // can change based on which render target is bound | 192 // can change based on which render target is bound |
| 192 fTwoFormatLimit = kGLES_GrGLStandard == standard; | 193 fTwoFormatLimit = kGLES_GrGLStandard == standard; |
| 193 | 194 |
| 195 // We only enable srgb support if both textures and FBOs support srgb. |
| 196 bool srgbSupport = false; |
| 197 if (kGL_GrGLStandard == standard) { |
| 198 if (ctxInfo.version() >= GR_GL_VER(3,0)) { |
| 199 srgbSupport = true; |
| 200 } else if (ctxInfo.hasExtension("GL_EXT_texture_sRGB")) { |
| 201 if (ctxInfo.hasExtension("GL_ARB_framebuffer_sRGB") || |
| 202 ctxInfo.hasExtension("GL_EXT_framebuffer_sRGB")) { |
| 203 srgbSupport = true; |
| 204 } |
| 205 } |
| 206 // All the above srgb extensions support toggling srgb writes |
| 207 fSRGBWriteControl = srgbSupport; |
| 208 } else { |
| 209 srgbSupport = ctxInfo.version() >= GR_GL_VER(3,0) || |
| 210 ctxInfo.hasExtension("GL_EXT_sRGB"); |
| 211 // ES through 3.1 requires EXT_srgb_write_control to support toggling |
| 212 // sRGB writing for destinations. |
| 213 fSRGBWriteControl = ctxInfo.hasExtension("GL_EXT_sRGB_write_control"); |
| 214 } |
| 215 |
| 194 // Frag Coords Convention support is not part of ES | 216 // Frag Coords Convention support is not part of ES |
| 195 // Known issue on at least some Intel platforms: | 217 // Known issue on at least some Intel platforms: |
| 196 // http://code.google.com/p/skia/issues/detail?id=946 | 218 // http://code.google.com/p/skia/issues/detail?id=946 |
| 197 if (kIntel_GrGLVendor != ctxInfo.vendor() && kGLES_GrGLStandard != standard)
{ | 219 if (kIntel_GrGLVendor != ctxInfo.vendor() && kGLES_GrGLStandard != standard)
{ |
| 198 fFragCoordsConventionSupport = ctxInfo.glslGeneration() >= k150_GrGLSLGe
neration || | 220 fFragCoordsConventionSupport = ctxInfo.glslGeneration() >= k150_GrGLSLGe
neration || |
| 199 ctxInfo.hasExtension("GL_ARB_fragment_coo
rd_conventions"); | 221 ctxInfo.hasExtension("GL_ARB_fragment_coo
rd_conventions"); |
| 200 } | 222 } |
| 201 | 223 |
| 202 // SGX and Mali GPUs that are based on a tiled-deferred architecture that ha
ve trouble with | 224 // SGX and Mali GPUs that are based on a tiled-deferred architecture that ha
ve trouble with |
| 203 // frequently changing VBOs. We've measured a performance increase using non
-VBO vertex | 225 // frequently changing VBOs. We've measured a performance increase using non
-VBO vertex |
| (...skipping 244 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 448 version >= GR_GL_VER(3, 2) || | 470 version >= GR_GL_VER(3, 2) || |
| 449 (ctxInfo.hasExtension("GL_ARB_draw_instanced") && | 471 (ctxInfo.hasExtension("GL_ARB_draw_instanced") && |
| 450 ctxInfo.hasExtension("GL_ARB_instanced_arrays")); | 472 ctxInfo.hasExtension("GL_ARB_instanced_arrays")); |
| 451 } else { | 473 } else { |
| 452 fSupportsInstancedDraws = | 474 fSupportsInstancedDraws = |
| 453 version >= GR_GL_VER(3, 0) || | 475 version >= GR_GL_VER(3, 0) || |
| 454 (ctxInfo.hasExtension("GL_EXT_draw_instanced") && | 476 (ctxInfo.hasExtension("GL_EXT_draw_instanced") && |
| 455 ctxInfo.hasExtension("GL_EXT_instanced_arrays")); | 477 ctxInfo.hasExtension("GL_EXT_instanced_arrays")); |
| 456 } | 478 } |
| 457 | 479 |
| 458 this->initConfigTexturableTable(ctxInfo, gli); | 480 this->initConfigTexturableTable(ctxInfo, gli, srgbSupport); |
| 459 this->initConfigRenderableTable(ctxInfo); | 481 this->initConfigRenderableTable(ctxInfo, srgbSupport); |
| 460 this->initShaderPrecisionTable(ctxInfo, gli, glslCaps); | 482 this->initShaderPrecisionTable(ctxInfo, gli, glslCaps); |
| 461 | 483 |
| 462 this->applyOptionsOverrides(contextOptions); | 484 this->applyOptionsOverrides(contextOptions); |
| 463 glslCaps->applyOptionsOverrides(contextOptions); | 485 glslCaps->applyOptionsOverrides(contextOptions); |
| 464 } | 486 } |
| 465 | 487 |
| 466 bool GrGLCaps::hasPathRenderingSupport(const GrGLContextInfo& ctxInfo, const GrG
LInterface* gli) { | 488 bool GrGLCaps::hasPathRenderingSupport(const GrGLContextInfo& ctxInfo, const GrG
LInterface* gli) { |
| 467 bool hasChromiumPathRendering = ctxInfo.hasExtension("GL_CHROMIUM_path_rende
ring"); | 489 bool hasChromiumPathRendering = ctxInfo.hasExtension("GL_CHROMIUM_path_rende
ring"); |
| 468 | 490 |
| 469 if (!(ctxInfo.hasExtension("GL_NV_path_rendering") || hasChromiumPathRenderi
ng)) { | 491 if (!(ctxInfo.hasExtension("GL_NV_path_rendering") || hasChromiumPathRenderi
ng)) { |
| (...skipping 19 matching lines...) Expand all Loading... |
| 489 if (NULL == gli->fFunctions.fStencilThenCoverFillPath || | 511 if (NULL == gli->fFunctions.fStencilThenCoverFillPath || |
| 490 NULL == gli->fFunctions.fStencilThenCoverStrokePath || | 512 NULL == gli->fFunctions.fStencilThenCoverStrokePath || |
| 491 NULL == gli->fFunctions.fStencilThenCoverFillPathInstanced || | 513 NULL == gli->fFunctions.fStencilThenCoverFillPathInstanced || |
| 492 NULL == gli->fFunctions.fStencilThenCoverStrokePathInstanced || | 514 NULL == gli->fFunctions.fStencilThenCoverStrokePathInstanced || |
| 493 NULL == gli->fFunctions.fProgramPathFragmentInputGen) { | 515 NULL == gli->fFunctions.fProgramPathFragmentInputGen) { |
| 494 return false; | 516 return false; |
| 495 } | 517 } |
| 496 return true; | 518 return true; |
| 497 } | 519 } |
| 498 | 520 |
| 499 void GrGLCaps::initConfigRenderableTable(const GrGLContextInfo& ctxInfo) { | 521 void GrGLCaps::initConfigRenderableTable(const GrGLContextInfo& ctxInfo, bool sr
gbSupport) { |
| 500 // OpenGL < 3.0 | 522 // OpenGL < 3.0 |
| 501 // no support for render targets unless the GL_ARB_framebuffer_object | 523 // no support for render targets unless the GL_ARB_framebuffer_object |
| 502 // extension is supported (in which case we get ALPHA, RED, RG, RGB, | 524 // extension is supported (in which case we get ALPHA, RED, RG, RGB, |
| 503 // RGBA (ALPHA8, RGBA4, RGBA8) for OpenGL > 1.1). Note that we | 525 // RGBA (ALPHA8, RGBA4, RGBA8) for OpenGL > 1.1). Note that we |
| 504 // probably don't get R8 in this case. | 526 // probably don't get R8 in this case. |
| 505 | 527 |
| 506 // OpenGL 3.0 | 528 // OpenGL 3.0 |
| 507 // base color renderable: ALPHA, RED, RG, RGB, and RGBA | 529 // base color renderable: ALPHA, RED, RG, RGB, and RGBA |
| 508 // sized derivatives: ALPHA8, R8, RGBA4, RGBA8 | 530 // sized derivatives: ALPHA8, R8, RGBA4, RGBA8 |
| 509 | 531 |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 567 // configs that are color-renderable and can be passed to glRenderBuffer
StorageMultisample. | 589 // configs that are color-renderable and can be passed to glRenderBuffer
StorageMultisample. |
| 568 // Chromium may have an extension to allow BGRA renderbuffers to work on
desktop platforms. | 590 // Chromium may have an extension to allow BGRA renderbuffers to work on
desktop platforms. |
| 569 if (ctxInfo.hasExtension("GL_CHROMIUM_renderbuffer_format_BGRA8888")) { | 591 if (ctxInfo.hasExtension("GL_CHROMIUM_renderbuffer_format_BGRA8888")) { |
| 570 fConfigRenderSupport[kBGRA_8888_GrPixelConfig][kYes_MSAA] = true; | 592 fConfigRenderSupport[kBGRA_8888_GrPixelConfig][kYes_MSAA] = true; |
| 571 } else { | 593 } else { |
| 572 fConfigRenderSupport[kBGRA_8888_GrPixelConfig][kYes_MSAA] = | 594 fConfigRenderSupport[kBGRA_8888_GrPixelConfig][kYes_MSAA] = |
| 573 !fBGRAIsInternalFormat || !this->usesMSAARenderBuffers(); | 595 !fBGRAIsInternalFormat || !this->usesMSAARenderBuffers(); |
| 574 } | 596 } |
| 575 } | 597 } |
| 576 | 598 |
| 577 if (this->fRGBA8RenderbufferSupport && this->isConfigTexturable(kSRGBA_8888_
GrPixelConfig)) { | 599 if (this->fRGBA8RenderbufferSupport && srgbSupport) { |
| 578 if (kGL_GrGLStandard == standard) { | 600 fConfigRenderSupport[kSRGBA_8888_GrPixelConfig][kNo_MSAA] = true; |
| 579 if (ctxInfo.version() >= GR_GL_VER(3,0) || | 601 fConfigRenderSupport[kSRGBA_8888_GrPixelConfig][kYes_MSAA] = true; |
| 580 ctxInfo.hasExtension("GL_ARB_framebuffer_sRGB") || | |
| 581 ctxInfo.hasExtension("GL_EXT_framebuffer_sRGB")) { | |
| 582 fConfigRenderSupport[kSRGBA_8888_GrPixelConfig][kNo_MSAA] = true
; | |
| 583 fConfigRenderSupport[kSRGBA_8888_GrPixelConfig][kYes_MSAA] = tru
e; | |
| 584 } | |
| 585 } else { | |
| 586 if (ctxInfo.version() >= GR_GL_VER(3,0) || | |
| 587 ctxInfo.hasExtension("GL_EXT_sRGB")) { | |
| 588 fConfigRenderSupport[kSRGBA_8888_GrPixelConfig][kNo_MSAA] = true
; | |
| 589 fConfigRenderSupport[kSRGBA_8888_GrPixelConfig][kYes_MSAA] = tru
e; | |
| 590 } | |
| 591 } | |
| 592 } | 602 } |
| 593 | 603 |
| 594 if (this->isConfigTexturable(kRGBA_float_GrPixelConfig)) { | 604 if (this->isConfigTexturable(kRGBA_float_GrPixelConfig)) { |
| 595 if (kGL_GrGLStandard == standard) { | 605 if (kGL_GrGLStandard == standard) { |
| 596 fConfigRenderSupport[kRGBA_float_GrPixelConfig][kNo_MSAA] = true; | 606 fConfigRenderSupport[kRGBA_float_GrPixelConfig][kNo_MSAA] = true; |
| 597 fConfigRenderSupport[kRGBA_float_GrPixelConfig][kYes_MSAA] = true; | 607 fConfigRenderSupport[kRGBA_float_GrPixelConfig][kYes_MSAA] = true; |
| 598 } else { | 608 } else { |
| 599 // for now we only enable this on desktop, because on ES we'd have t
o solve many | 609 // for now we only enable this on desktop, because on ES we'd have t
o solve many |
| 600 // precision issues and no clients actually want this yet | 610 // precision issues and no clients actually want this yet |
| 601 /* | 611 /* |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 651 | 661 |
| 652 // If we don't support MSAA then undo any places above where we set a config
as renderable with | 662 // If we don't support MSAA then undo any places above where we set a config
as renderable with |
| 653 // msaa. | 663 // msaa. |
| 654 if (kNone_MSFBOType == fMSFBOType) { | 664 if (kNone_MSFBOType == fMSFBOType) { |
| 655 for (int i = 0; i < kGrPixelConfigCnt; ++i) { | 665 for (int i = 0; i < kGrPixelConfigCnt; ++i) { |
| 656 fConfigRenderSupport[i][kYes_MSAA] = false; | 666 fConfigRenderSupport[i][kYes_MSAA] = false; |
| 657 } | 667 } |
| 658 } | 668 } |
| 659 } | 669 } |
| 660 | 670 |
| 661 void GrGLCaps::initConfigTexturableTable(const GrGLContextInfo& ctxInfo, const G
rGLInterface* gli) { | 671 void GrGLCaps::initConfigTexturableTable(const GrGLContextInfo& ctxInfo, const G
rGLInterface* gli, |
| 672 bool srgbSupport) { |
| 662 GrGLStandard standard = ctxInfo.standard(); | 673 GrGLStandard standard = ctxInfo.standard(); |
| 663 GrGLVersion version = ctxInfo.version(); | 674 GrGLVersion version = ctxInfo.version(); |
| 664 | 675 |
| 665 // Base texture support | 676 // Base texture support |
| 666 fConfigTextureSupport[kAlpha_8_GrPixelConfig] = true; | 677 fConfigTextureSupport[kAlpha_8_GrPixelConfig] = true; |
| 667 fConfigTextureSupport[kRGB_565_GrPixelConfig] = true; | 678 fConfigTextureSupport[kRGB_565_GrPixelConfig] = true; |
| 668 fConfigTextureSupport[kRGBA_4444_GrPixelConfig] = true; | 679 fConfigTextureSupport[kRGBA_4444_GrPixelConfig] = true; |
| 669 fConfigTextureSupport[kRGBA_8888_GrPixelConfig] = true; | 680 fConfigTextureSupport[kRGBA_8888_GrPixelConfig] = true; |
| 670 | 681 |
| 671 // Check for 8-bit palette.. | 682 // Check for 8-bit palette.. |
| (...skipping 18 matching lines...) Expand all Loading... |
| 690 if (ctxInfo.hasExtension("GL_APPLE_texture_format_BGRA8888")) { | 701 if (ctxInfo.hasExtension("GL_APPLE_texture_format_BGRA8888")) { |
| 691 fConfigTextureSupport[kBGRA_8888_GrPixelConfig] = true; | 702 fConfigTextureSupport[kBGRA_8888_GrPixelConfig] = true; |
| 692 } else if (ctxInfo.hasExtension("GL_EXT_texture_format_BGRA8888")) { | 703 } else if (ctxInfo.hasExtension("GL_EXT_texture_format_BGRA8888")) { |
| 693 fConfigTextureSupport[kBGRA_8888_GrPixelConfig] = true; | 704 fConfigTextureSupport[kBGRA_8888_GrPixelConfig] = true; |
| 694 fBGRAIsInternalFormat = true; | 705 fBGRAIsInternalFormat = true; |
| 695 } | 706 } |
| 696 SkASSERT(fConfigTextureSupport[kBGRA_8888_GrPixelConfig] || | 707 SkASSERT(fConfigTextureSupport[kBGRA_8888_GrPixelConfig] || |
| 697 kSkia8888_GrPixelConfig != kBGRA_8888_GrPixelConfig); | 708 kSkia8888_GrPixelConfig != kBGRA_8888_GrPixelConfig); |
| 698 } | 709 } |
| 699 | 710 |
| 700 // Check for sRGBA | 711 fConfigTextureSupport[kSRGBA_8888_GrPixelConfig] = srgbSupport; |
| 701 if (kGL_GrGLStandard == standard) { | |
| 702 fConfigTextureSupport[kSRGBA_8888_GrPixelConfig] = | |
| 703 (version >= GR_GL_VER(3,0) || ctxInfo.hasExtension("GL_EXT_texture_s
RGB")); | |
| 704 } else { | |
| 705 fConfigTextureSupport[kSRGBA_8888_GrPixelConfig] = | |
| 706 (version >= GR_GL_VER(3,0) || ctxInfo.hasExtension("GL_EXT_sRGB")); | |
| 707 } | |
| 708 | 712 |
| 709 // Compressed texture support | 713 // Compressed texture support |
| 710 | 714 |
| 711 // glCompressedTexImage2D is available on all OpenGL ES devices... | 715 // glCompressedTexImage2D is available on all OpenGL ES devices... |
| 712 // however, it is only available on standard OpenGL after version 1.3 | 716 // however, it is only available on standard OpenGL after version 1.3 |
| 713 bool hasCompressTex2D = (kGL_GrGLStandard != standard || version >= GR_GL_VE
R(1, 3)); | 717 bool hasCompressTex2D = (kGL_GrGLStandard != standard || version >= GR_GL_VE
R(1, 3)); |
| 714 | 718 |
| 715 fCompressedTexSubImageSupport = | 719 fCompressedTexSubImageSupport = |
| 716 hasCompressTex2D && (gli->fFunctions.fCompressedTexSubImage2D); | 720 hasCompressTex2D && (gli->fFunctions.fCompressedTexSubImage2D); |
| 717 | 721 |
| (...skipping 393 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1111 r.appendf("Fragment coord conventions support: %s\n", | 1115 r.appendf("Fragment coord conventions support: %s\n", |
| 1112 (fFragCoordsConventionSupport ? "YES": "NO")); | 1116 (fFragCoordsConventionSupport ? "YES": "NO")); |
| 1113 r.appendf("Vertex array object support: %s\n", (fVertexArrayObjectSupport ?
"YES": "NO")); | 1117 r.appendf("Vertex array object support: %s\n", (fVertexArrayObjectSupport ?
"YES": "NO")); |
| 1114 r.appendf("Instanced drawing support: %s\n", (fInstancedDrawingSupport ? "YE
S": "NO")); | 1118 r.appendf("Instanced drawing support: %s\n", (fInstancedDrawingSupport ? "YE
S": "NO")); |
| 1115 r.appendf("Direct state access support: %s\n", (fDirectStateAccessSupport ?
"YES": "NO")); | 1119 r.appendf("Direct state access support: %s\n", (fDirectStateAccessSupport ?
"YES": "NO")); |
| 1116 r.appendf("Debug support: %s\n", (fDebugSupport ? "YES": "NO")); | 1120 r.appendf("Debug support: %s\n", (fDebugSupport ? "YES": "NO")); |
| 1117 r.appendf("Multisample disable support: %s\n", (fMultisampleDisableSupport ?
"YES" : "NO")); | 1121 r.appendf("Multisample disable support: %s\n", (fMultisampleDisableSupport ?
"YES" : "NO")); |
| 1118 r.appendf("Use non-VBO for dynamic data: %s\n", | 1122 r.appendf("Use non-VBO for dynamic data: %s\n", |
| 1119 (fUseNonVBOVertexAndIndexDynamicData ? "YES" : "NO")); | 1123 (fUseNonVBOVertexAndIndexDynamicData ? "YES" : "NO")); |
| 1120 r.appendf("Full screen clear is free: %s\n", (fFullClearIsFree ? "YES" : "NO
")); | 1124 r.appendf("Full screen clear is free: %s\n", (fFullClearIsFree ? "YES" : "NO
")); |
| 1125 r.appendf("SRGB write contol: %s\n", (fSRGBWriteControl ? "YES" : "NO")); |
| 1121 return r; | 1126 return r; |
| 1122 } | 1127 } |
| 1123 | 1128 |
| 1124 static GrGLenum precision_to_gl_float_type(GrSLPrecision p) { | 1129 static GrGLenum precision_to_gl_float_type(GrSLPrecision p) { |
| 1125 switch (p) { | 1130 switch (p) { |
| 1126 case kLow_GrSLPrecision: | 1131 case kLow_GrSLPrecision: |
| 1127 return GR_GL_LOW_FLOAT; | 1132 return GR_GL_LOW_FLOAT; |
| 1128 case kMedium_GrSLPrecision: | 1133 case kMedium_GrSLPrecision: |
| 1129 return GR_GL_MEDIUM_FLOAT; | 1134 return GR_GL_MEDIUM_FLOAT; |
| 1130 case kHigh_GrSLPrecision: | 1135 case kHigh_GrSLPrecision: |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1201 for (int p = 0; p < kGrSLPrecisionCount; ++p) { | 1206 for (int p = 0; p < kGrSLPrecisionCount; ++p) { |
| 1202 glslCaps->fFloatPrecisions[kGeometry_GrShaderType][p] = | 1207 glslCaps->fFloatPrecisions[kGeometry_GrShaderType][p] = |
| 1203 glslCaps->fFloatPrecisions[kVerte
x_GrShaderType][p]; | 1208 glslCaps->fFloatPrecisions[kVerte
x_GrShaderType][p]; |
| 1204 } | 1209 } |
| 1205 } | 1210 } |
| 1206 } | 1211 } |
| 1207 | 1212 |
| 1208 | 1213 |
| 1209 | 1214 |
| 1210 | 1215 |
| OLD | NEW |