Shader.cpp revision 6062c5912dc79704b489fc8c289b78a400ed05ee
1#include <jni.h> 2#include "GraphicsJNI.h" 3 4#include "SkShader.h" 5#include "SkGradientShader.h" 6#include "SkPorterDuff.h" 7#include "SkComposeShader.h" 8#include "SkTemplates.h" 9#include "SkXfermode.h" 10 11#include <SkiaShader.h> 12#include <Caches.h> 13 14using namespace android::uirenderer; 15 16static struct { 17 jclass clazz; 18 jfieldID shader; 19} gShaderClassInfo; 20 21static void ThrowIAE_IfNull(JNIEnv* env, void* ptr) { 22 if (NULL == ptr) { 23 doThrowIAE(env); 24 } 25} 26 27static void Color_RGBToHSV(JNIEnv* env, jobject, int red, int green, int blue, jfloatArray hsvArray) 28{ 29 SkScalar hsv[3]; 30 SkRGBToHSV(red, green, blue, hsv); 31 32 AutoJavaFloatArray autoHSV(env, hsvArray, 3); 33 float* values = autoHSV.ptr(); 34 for (int i = 0; i < 3; i++) { 35 values[i] = SkScalarToFloat(hsv[i]); 36 } 37} 38 39static int Color_HSVToColor(JNIEnv* env, jobject, int alpha, jfloatArray hsvArray) 40{ 41 AutoJavaFloatArray autoHSV(env, hsvArray, 3); 42 float* values = autoHSV.ptr();; 43 SkScalar hsv[3]; 44 45 for (int i = 0; i < 3; i++) { 46 hsv[i] = SkFloatToScalar(values[i]); 47 } 48 49 return SkHSVToColor(alpha, hsv); 50} 51 52/////////////////////////////////////////////////////////////////////////////////////////////// 53 54static void Shader_destructor(JNIEnv* env, jobject o, SkShader* shader, SkiaShader* skiaShader) 55{ 56 SkSafeUnref(shader); 57 // skiaShader == NULL when not !USE_OPENGL_RENDERER, so no need to delete it outside the ifdef 58#ifdef USE_OPENGL_RENDERER 59 if (android::uirenderer::Caches::hasInstance()) { 60 android::uirenderer::Caches::getInstance().resourceCache.destructor(skiaShader); 61 } else { 62 delete skiaShader; 63 } 64#endif 65} 66 67static void Shader_setLocalMatrix(JNIEnv* env, jobject o, SkShader* shader, SkiaShader* skiaShader, 68 const SkMatrix* matrix) 69{ 70 if (shader) { 71 if (NULL == matrix) { 72 shader->resetLocalMatrix(); 73 } 74 else { 75 shader->setLocalMatrix(*matrix); 76 } 77#ifdef USE_OPENGL_RENDERER 78 skiaShader->setMatrix(const_cast<SkMatrix*>(matrix)); 79#endif 80 } 81} 82 83/////////////////////////////////////////////////////////////////////////////////////////////// 84 85static SkShader* BitmapShader_constructor(JNIEnv* env, jobject o, const SkBitmap* bitmap, 86 int tileModeX, int tileModeY) 87{ 88 SkShader* s = SkShader::CreateBitmapShader(*bitmap, 89 (SkShader::TileMode)tileModeX, 90 (SkShader::TileMode)tileModeY); 91 92 ThrowIAE_IfNull(env, s); 93 return s; 94} 95 96static SkiaShader* BitmapShader_postConstructor(JNIEnv* env, jobject o, SkShader* shader, 97 SkBitmap* bitmap, int tileModeX, int tileModeY) { 98#ifdef USE_OPENGL_RENDERER 99 SkiaShader* skiaShader = new SkiaBitmapShader(bitmap, shader, 100 static_cast<SkShader::TileMode>(tileModeX), static_cast<SkShader::TileMode>(tileModeY), 101 NULL, (shader->getFlags() & SkShader::kOpaqueAlpha_Flag) == 0); 102 return skiaShader; 103#else 104 return NULL; 105#endif 106} 107 108/////////////////////////////////////////////////////////////////////////////////////////////// 109 110static SkShader* LinearGradient_create1(JNIEnv* env, jobject o, 111 float x0, float y0, float x1, float y1, 112 jintArray colorArray, jfloatArray posArray, int tileMode) 113{ 114 SkPoint pts[2]; 115 pts[0].set(SkFloatToScalar(x0), SkFloatToScalar(y0)); 116 pts[1].set(SkFloatToScalar(x1), SkFloatToScalar(y1)); 117 118 size_t count = env->GetArrayLength(colorArray); 119 const jint* colorValues = env->GetIntArrayElements(colorArray, NULL); 120 121 SkAutoSTMalloc<8, SkScalar> storage(posArray ? count : 0); 122 SkScalar* pos = NULL; 123 124 if (posArray) { 125 AutoJavaFloatArray autoPos(env, posArray, count); 126 const float* posValues = autoPos.ptr(); 127 pos = (SkScalar*)storage.get(); 128 for (size_t i = 0; i < count; i++) { 129 pos[i] = SkFloatToScalar(posValues[i]); 130 } 131 } 132 133 SkShader* shader = SkGradientShader::CreateLinear(pts, 134 reinterpret_cast<const SkColor*>(colorValues), 135 pos, count, 136 static_cast<SkShader::TileMode>(tileMode)); 137 138 env->ReleaseIntArrayElements(colorArray, const_cast<jint*>(colorValues), JNI_ABORT); 139 ThrowIAE_IfNull(env, shader); 140 return shader; 141} 142 143static SkiaShader* LinearGradient_postCreate1(JNIEnv* env, jobject o, SkShader* shader, 144 float x0, float y0, float x1, float y1, jintArray colorArray, 145 jfloatArray posArray, int tileMode) { 146#ifdef USE_OPENGL_RENDERER 147 size_t count = env->GetArrayLength(colorArray); 148 const jint* colorValues = env->GetIntArrayElements(colorArray, NULL); 149 150 jfloat* storedBounds = new jfloat[4]; 151 storedBounds[0] = x0; storedBounds[1] = y0; 152 storedBounds[2] = x1; storedBounds[3] = y1; 153 jfloat* storedPositions = new jfloat[count]; 154 uint32_t* storedColors = new uint32_t[count]; 155 for (size_t i = 0; i < count; i++) { 156 storedColors[i] = static_cast<uint32_t>(colorValues[i]); 157 } 158 159 if (posArray) { 160 AutoJavaFloatArray autoPos(env, posArray, count); 161 const float* posValues = autoPos.ptr(); 162 for (size_t i = 0; i < count; i++) { 163 storedPositions[i] = posValues[i]; 164 } 165 } else { 166 storedPositions[0] = 0.0f; 167 storedPositions[1] = 1.0f; 168 } 169 170 SkiaShader* skiaShader = new SkiaLinearGradientShader(storedBounds, storedColors, 171 storedPositions, count, shader, static_cast<SkShader::TileMode>(tileMode), NULL, 172 (shader->getFlags() & SkShader::kOpaqueAlpha_Flag) == 0); 173 174 env->ReleaseIntArrayElements(colorArray, const_cast<jint*>(colorValues), JNI_ABORT); 175 return skiaShader; 176#else 177 return NULL; 178#endif 179} 180 181static SkiaShader* LinearGradient_postCreate2(JNIEnv* env, jobject o, SkShader* shader, 182 float x0, float y0, float x1, float y1, int color0, int color1, int tileMode) { 183#ifdef USE_OPENGL_RENDERER 184 float* storedBounds = new float[4]; 185 storedBounds[0] = x0; storedBounds[1] = y0; 186 storedBounds[2] = x1; storedBounds[3] = y1; 187 188 float* storedPositions = new float[2]; 189 storedPositions[0] = 0.0f; 190 storedPositions[1] = 1.0f; 191 192 uint32_t* storedColors = new uint32_t[2]; 193 storedColors[0] = static_cast<uint32_t>(color0); 194 storedColors[1] = static_cast<uint32_t>(color1); 195 196 SkiaShader* skiaShader = new SkiaLinearGradientShader(storedBounds, storedColors, 197 storedPositions, 2, shader, static_cast<SkShader::TileMode>(tileMode), NULL, 198 (shader->getFlags() & SkShader::kOpaqueAlpha_Flag) == 0); 199 200 return skiaShader; 201#else 202 return NULL; 203#endif 204} 205 206static SkShader* LinearGradient_create2(JNIEnv* env, jobject o, 207 float x0, float y0, float x1, float y1, 208 int color0, int color1, int tileMode) 209{ 210 SkPoint pts[2]; 211 pts[0].set(SkFloatToScalar(x0), SkFloatToScalar(y0)); 212 pts[1].set(SkFloatToScalar(x1), SkFloatToScalar(y1)); 213 214 SkColor colors[2]; 215 colors[0] = color0; 216 colors[1] = color1; 217 218 SkShader* s = SkGradientShader::CreateLinear(pts, colors, NULL, 2, (SkShader::TileMode)tileMode); 219 220 ThrowIAE_IfNull(env, s); 221 return s; 222} 223 224/////////////////////////////////////////////////////////////////////////////////////////////// 225 226static SkShader* RadialGradient_create1(JNIEnv* env, jobject, float x, float y, float radius, 227 jintArray colorArray, jfloatArray posArray, int tileMode) { 228 SkPoint center; 229 center.set(SkFloatToScalar(x), SkFloatToScalar(y)); 230 231 size_t count = env->GetArrayLength(colorArray); 232 const jint* colorValues = env->GetIntArrayElements(colorArray, NULL); 233 234 SkAutoSTMalloc<8, SkScalar> storage(posArray ? count : 0); 235 SkScalar* pos = NULL; 236 237 if (posArray) { 238 AutoJavaFloatArray autoPos(env, posArray, count); 239 const float* posValues = autoPos.ptr(); 240 pos = (SkScalar*)storage.get(); 241 for (size_t i = 0; i < count; i++) 242 pos[i] = SkFloatToScalar(posValues[i]); 243 } 244 245 SkShader* shader = SkGradientShader::CreateRadial(center, 246 SkFloatToScalar(radius), 247 reinterpret_cast<const SkColor*>(colorValues), 248 pos, count, 249 static_cast<SkShader::TileMode>(tileMode)); 250 env->ReleaseIntArrayElements(colorArray, const_cast<jint*>(colorValues), 251 JNI_ABORT); 252 253 ThrowIAE_IfNull(env, shader); 254 return shader; 255} 256 257static SkShader* RadialGradient_create2(JNIEnv* env, jobject, float x, float y, float radius, 258 int color0, int color1, int tileMode) { 259 SkPoint center; 260 center.set(SkFloatToScalar(x), SkFloatToScalar(y)); 261 262 SkColor colors[2]; 263 colors[0] = color0; 264 colors[1] = color1; 265 266 SkShader* s = SkGradientShader::CreateRadial(center, SkFloatToScalar(radius), colors, NULL, 267 2, (SkShader::TileMode)tileMode); 268 ThrowIAE_IfNull(env, s); 269 return s; 270} 271 272static SkiaShader* RadialGradient_postCreate1(JNIEnv* env, jobject o, SkShader* shader, 273 float x, float y, float radius, jintArray colorArray, jfloatArray posArray, int tileMode) { 274#ifdef USE_OPENGL_RENDERER 275 size_t count = env->GetArrayLength(colorArray); 276 const jint* colorValues = env->GetIntArrayElements(colorArray, NULL); 277 278 jfloat* storedPositions = new jfloat[count]; 279 uint32_t* storedColors = new uint32_t[count]; 280 for (size_t i = 0; i < count; i++) { 281 storedColors[i] = static_cast<uint32_t>(colorValues[i]); 282 } 283 284 if (posArray) { 285 AutoJavaFloatArray autoPos(env, posArray, count); 286 const float* posValues = autoPos.ptr(); 287 for (size_t i = 0; i < count; i++) { 288 storedPositions[i] = posValues[i]; 289 } 290 } else { 291 storedPositions[0] = 0.0f; 292 storedPositions[1] = 1.0f; 293 } 294 295 SkiaShader* skiaShader = new SkiaCircularGradientShader(x, y, radius, storedColors, 296 storedPositions, count, shader, (SkShader::TileMode) tileMode, NULL, 297 (shader->getFlags() & SkShader::kOpaqueAlpha_Flag) == 0); 298 299 env->ReleaseIntArrayElements(colorArray, const_cast<jint*>(colorValues), JNI_ABORT); 300 return skiaShader; 301#else 302 return NULL; 303#endif 304} 305 306static SkiaShader* RadialGradient_postCreate2(JNIEnv* env, jobject o, SkShader* shader, 307 float x, float y, float radius, int color0, int color1, int tileMode) { 308#ifdef USE_OPENGL_RENDERER 309 float* storedPositions = new float[2]; 310 storedPositions[0] = 0.0f; 311 storedPositions[1] = 1.0f; 312 313 uint32_t* storedColors = new uint32_t[2]; 314 storedColors[0] = static_cast<uint32_t>(color0); 315 storedColors[1] = static_cast<uint32_t>(color1); 316 317 SkiaShader* skiaShader = new SkiaCircularGradientShader(x, y, radius, storedColors, 318 storedPositions, 2, shader, (SkShader::TileMode) tileMode, NULL, 319 (shader->getFlags() & SkShader::kOpaqueAlpha_Flag) == 0); 320 321 return skiaShader; 322#else 323 return NULL; 324#endif 325} 326 327/////////////////////////////////////////////////////////////////////////////// 328 329static SkShader* SweepGradient_create1(JNIEnv* env, jobject, float x, float y, 330 jintArray jcolors, jfloatArray jpositions) { 331 size_t count = env->GetArrayLength(jcolors); 332 const jint* colors = env->GetIntArrayElements(jcolors, NULL); 333 334 SkAutoSTMalloc<8, SkScalar> storage(jpositions ? count : 0); 335 SkScalar* pos = NULL; 336 337 if (NULL != jpositions) { 338 AutoJavaFloatArray autoPos(env, jpositions, count); 339 const float* posValues = autoPos.ptr(); 340 pos = (SkScalar*)storage.get(); 341 for (size_t i = 0; i < count; i++) { 342 pos[i] = SkFloatToScalar(posValues[i]); 343 } 344 } 345 346 SkShader* shader = SkGradientShader::CreateSweep(SkFloatToScalar(x), 347 SkFloatToScalar(y), 348 reinterpret_cast<const SkColor*>(colors), 349 pos, count); 350 env->ReleaseIntArrayElements(jcolors, const_cast<jint*>(colors), 351 JNI_ABORT); 352 ThrowIAE_IfNull(env, shader); 353 return shader; 354} 355 356static SkShader* SweepGradient_create2(JNIEnv* env, jobject, float x, float y, 357 int color0, int color1) { 358 SkColor colors[2]; 359 colors[0] = color0; 360 colors[1] = color1; 361 SkShader* s = SkGradientShader::CreateSweep(SkFloatToScalar(x), SkFloatToScalar(y), 362 colors, NULL, 2); 363 ThrowIAE_IfNull(env, s); 364 return s; 365} 366 367static SkiaShader* SweepGradient_postCreate1(JNIEnv* env, jobject o, SkShader* shader, 368 float x, float y, jintArray colorArray, jfloatArray posArray) { 369#ifdef USE_OPENGL_RENDERER 370 size_t count = env->GetArrayLength(colorArray); 371 const jint* colorValues = env->GetIntArrayElements(colorArray, NULL); 372 373 jfloat* storedPositions = new jfloat[count]; 374 uint32_t* storedColors = new uint32_t[count]; 375 for (size_t i = 0; i < count; i++) { 376 storedColors[i] = static_cast<uint32_t>(colorValues[i]); 377 } 378 379 if (posArray) { 380 AutoJavaFloatArray autoPos(env, posArray, count); 381 const float* posValues = autoPos.ptr(); 382 for (size_t i = 0; i < count; i++) { 383 storedPositions[i] = posValues[i]; 384 } 385 } else { 386 storedPositions[0] = 0.0f; 387 storedPositions[1] = 1.0f; 388 } 389 390 SkiaShader* skiaShader = new SkiaSweepGradientShader(x, y, storedColors, storedPositions, count, 391 shader, NULL, (shader->getFlags() & SkShader::kOpaqueAlpha_Flag) == 0); 392 393 env->ReleaseIntArrayElements(colorArray, const_cast<jint*>(colorValues), JNI_ABORT); 394 return skiaShader; 395#else 396 return NULL; 397#endif 398} 399 400static SkiaShader* SweepGradient_postCreate2(JNIEnv* env, jobject o, SkShader* shader, 401 float x, float y, int color0, int color1) { 402#ifdef USE_OPENGL_RENDERER 403 float* storedPositions = new float[2]; 404 storedPositions[0] = 0.0f; 405 storedPositions[1] = 1.0f; 406 407 uint32_t* storedColors = new uint32_t[2]; 408 storedColors[0] = static_cast<uint32_t>(color0); 409 storedColors[1] = static_cast<uint32_t>(color1); 410 411 SkiaShader* skiaShader = new SkiaSweepGradientShader(x, y, storedColors, storedPositions, 2, 412 shader, NULL, (shader->getFlags() & SkShader::kOpaqueAlpha_Flag) == 0); 413 414 return skiaShader; 415#else 416 return NULL; 417#endif 418} 419 420/////////////////////////////////////////////////////////////////////////////////////////////// 421 422static SkShader* ComposeShader_create1(JNIEnv* env, jobject o, 423 SkShader* shaderA, SkShader* shaderB, SkXfermode* mode) 424{ 425 return new SkComposeShader(shaderA, shaderB, mode); 426} 427 428static SkShader* ComposeShader_create2(JNIEnv* env, jobject o, 429 SkShader* shaderA, SkShader* shaderB, SkPorterDuff::Mode porterDuffMode) 430{ 431 SkAutoUnref au(SkPorterDuff::CreateXfermode(porterDuffMode)); 432 SkXfermode* mode = (SkXfermode*) au.get(); 433 return new SkComposeShader(shaderA, shaderB, mode); 434} 435 436static SkiaShader* ComposeShader_postCreate2(JNIEnv* env, jobject o, SkShader* shader, 437 SkiaShader* shaderA, SkiaShader* shaderB, SkPorterDuff::Mode porterDuffMode) { 438#ifdef USE_OPENGL_RENDERER 439 SkXfermode::Mode mode = SkPorterDuff::ToXfermodeMode(porterDuffMode); 440 return new SkiaComposeShader(shaderA, shaderB, mode, shader); 441#else 442 return NULL; 443#endif 444} 445 446static SkiaShader* ComposeShader_postCreate1(JNIEnv* env, jobject o, SkShader* shader, 447 SkiaShader* shaderA, SkiaShader* shaderB, SkXfermode* mode) { 448#ifdef USE_OPENGL_RENDERER 449 SkXfermode::Mode skiaMode; 450 if (!SkXfermode::IsMode(mode, &skiaMode)) { 451 // TODO: Support other modes 452 skiaMode = SkXfermode::kSrcOver_Mode; 453 } 454 return new SkiaComposeShader(shaderA, shaderB, skiaMode, shader); 455#else 456 return NULL; 457#endif 458} 459 460/////////////////////////////////////////////////////////////////////////////////////////////// 461 462static JNINativeMethod gColorMethods[] = { 463 { "nativeRGBToHSV", "(III[F)V", (void*)Color_RGBToHSV }, 464 { "nativeHSVToColor", "(I[F)I", (void*)Color_HSVToColor } 465}; 466 467static JNINativeMethod gShaderMethods[] = { 468 { "nativeDestructor", "(II)V", (void*)Shader_destructor }, 469 { "nativeSetLocalMatrix", "(III)V", (void*)Shader_setLocalMatrix } 470}; 471 472static JNINativeMethod gBitmapShaderMethods[] = { 473 { "nativeCreate", "(III)I", (void*)BitmapShader_constructor }, 474 { "nativePostCreate", "(IIII)I", (void*)BitmapShader_postConstructor } 475}; 476 477static JNINativeMethod gLinearGradientMethods[] = { 478 { "nativeCreate1", "(FFFF[I[FI)I", (void*)LinearGradient_create1 }, 479 { "nativeCreate2", "(FFFFIII)I", (void*)LinearGradient_create2 }, 480 { "nativePostCreate1", "(IFFFF[I[FI)I", (void*)LinearGradient_postCreate1 }, 481 { "nativePostCreate2", "(IFFFFIII)I", (void*)LinearGradient_postCreate2 } 482}; 483 484static JNINativeMethod gRadialGradientMethods[] = { 485 { "nativeCreate1", "(FFF[I[FI)I", (void*)RadialGradient_create1 }, 486 { "nativeCreate2", "(FFFIII)I", (void*)RadialGradient_create2 }, 487 { "nativePostCreate1", "(IFFF[I[FI)I", (void*)RadialGradient_postCreate1 }, 488 { "nativePostCreate2", "(IFFFIII)I", (void*)RadialGradient_postCreate2 } 489}; 490 491static JNINativeMethod gSweepGradientMethods[] = { 492 { "nativeCreate1", "(FF[I[F)I", (void*)SweepGradient_create1 }, 493 { "nativeCreate2", "(FFII)I", (void*)SweepGradient_create2 }, 494 { "nativePostCreate1", "(IFF[I[F)I", (void*)SweepGradient_postCreate1 }, 495 { "nativePostCreate2", "(IFFII)I", (void*)SweepGradient_postCreate2 } 496}; 497 498static JNINativeMethod gComposeShaderMethods[] = { 499 { "nativeCreate1", "(III)I", (void*)ComposeShader_create1 }, 500 { "nativeCreate2", "(III)I", (void*)ComposeShader_create2 }, 501 { "nativePostCreate1", "(IIII)I", (void*)ComposeShader_postCreate1 }, 502 { "nativePostCreate2", "(IIII)I", (void*)ComposeShader_postCreate2 } 503}; 504 505#include <android_runtime/AndroidRuntime.h> 506 507#define REG(env, name, array) \ 508 result = android::AndroidRuntime::registerNativeMethods(env, name, array, SK_ARRAY_COUNT(array)); \ 509 if (result < 0) return result 510 511int register_android_graphics_Shader(JNIEnv* env); 512int register_android_graphics_Shader(JNIEnv* env) 513{ 514 int result; 515 516 REG(env, "android/graphics/Color", gColorMethods); 517 REG(env, "android/graphics/Shader", gShaderMethods); 518 REG(env, "android/graphics/BitmapShader", gBitmapShaderMethods); 519 REG(env, "android/graphics/LinearGradient", gLinearGradientMethods); 520 REG(env, "android/graphics/RadialGradient", gRadialGradientMethods); 521 REG(env, "android/graphics/SweepGradient", gSweepGradientMethods); 522 REG(env, "android/graphics/ComposeShader", gComposeShaderMethods); 523 524 return result; 525} 526 527