OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2010 Google Inc. | 2 * Copyright 2010 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 #include "SkGr.h" | 8 #include "SkGr.h" |
9 #include "SkColorFilter.h" | 9 #include "SkColorFilter.h" |
10 #include "SkConfig8888.h" | 10 #include "SkConfig8888.h" |
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
124 | 124 |
125 virtual void onChange() SK_OVERRIDE { | 125 virtual void onChange() SK_OVERRIDE { |
126 const GrResourceInvalidatedMessage message = { fKey }; | 126 const GrResourceInvalidatedMessage message = { fKey }; |
127 SkMessageBus<GrResourceInvalidatedMessage>::Post(message); | 127 SkMessageBus<GrResourceInvalidatedMessage>::Post(message); |
128 } | 128 } |
129 }; | 129 }; |
130 | 130 |
131 } // namespace | 131 } // namespace |
132 | 132 |
133 static void add_genID_listener(GrResourceKey key, SkPixelRef* pixelRef) { | 133 static void add_genID_listener(GrResourceKey key, SkPixelRef* pixelRef) { |
134 SkASSERT(NULL != pixelRef); | 134 SkASSERT(pixelRef); |
135 pixelRef->addGenIDChangeListener(SkNEW_ARGS(GrResourceInvalidator, (key))); | 135 pixelRef->addGenIDChangeListener(SkNEW_ARGS(GrResourceInvalidator, (key))); |
136 } | 136 } |
137 | 137 |
138 #ifndef SK_IGNORE_ETC1_SUPPORT | 138 #ifndef SK_IGNORE_ETC1_SUPPORT |
139 static GrTexture *load_etc1_texture(GrContext* ctx, | 139 static GrTexture *load_etc1_texture(GrContext* ctx, |
140 const GrTextureParams* params, | 140 const GrTextureParams* params, |
141 const SkBitmap &bm, GrTextureDesc desc) { | 141 const SkBitmap &bm, GrTextureDesc desc) { |
142 SkAutoTUnref<SkData> data(bm.pixelRef()->refEncodedData()); | 142 SkAutoTUnref<SkData> data(bm.pixelRef()->refEncodedData()); |
143 | 143 |
144 // Is this even encoded data? | 144 // Is this even encoded data? |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
181 } else { | 181 } else { |
182 return NULL; | 182 return NULL; |
183 } | 183 } |
184 | 184 |
185 // This texture is likely to be used again so leave it in the cache | 185 // This texture is likely to be used again so leave it in the cache |
186 GrCacheID cacheID; | 186 GrCacheID cacheID; |
187 generate_bitmap_cache_id(bm, &cacheID); | 187 generate_bitmap_cache_id(bm, &cacheID); |
188 | 188 |
189 GrResourceKey key; | 189 GrResourceKey key; |
190 GrTexture* result = ctx->createTexture(params, desc, cacheID, bytes, 0, &key
); | 190 GrTexture* result = ctx->createTexture(params, desc, cacheID, bytes, 0, &key
); |
191 if (NULL != result) { | 191 if (result) { |
192 add_genID_listener(key, bm.pixelRef()); | 192 add_genID_listener(key, bm.pixelRef()); |
193 } | 193 } |
194 return result; | 194 return result; |
195 } | 195 } |
196 #endif // SK_IGNORE_ETC1_SUPPORT | 196 #endif // SK_IGNORE_ETC1_SUPPORT |
197 | 197 |
198 static GrTexture *load_yuv_texture(GrContext* ctx, const GrTextureParams* params
, | 198 static GrTexture *load_yuv_texture(GrContext* ctx, const GrTextureParams* params
, |
199 const SkBitmap& bm, const GrTextureDesc& desc
) { | 199 const SkBitmap& bm, const GrTextureDesc& desc
) { |
200 GrTexture* result = NULL; | 200 GrTexture* result = NULL; |
201 | 201 |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
243 kRenderTarget_GrTextureFlagBit | | 243 kRenderTarget_GrTextureFlagBit | |
244 kNoStencil_GrTextureFlagBit; | 244 kNoStencil_GrTextureFlagBit; |
245 | 245 |
246 // This texture is likely to be used again so leave it in the cache | 246 // This texture is likely to be used again so leave it in the cache |
247 GrCacheID cacheID; | 247 GrCacheID cacheID; |
248 generate_bitmap_cache_id(bm, &cacheID); | 248 generate_bitmap_cache_id(bm, &cacheID); |
249 | 249 |
250 GrResourceKey key; | 250 GrResourceKey key; |
251 result = ctx->createTexture(params, rtDesc, cacheID, NULL, 0, &key); | 251 result = ctx->createTexture(params, rtDesc, cacheID, NULL, 0, &key); |
252 GrRenderTarget* renderTarget = result ? result->asRenderTarget() : NULL; | 252 GrRenderTarget* renderTarget = result ? result->asRenderTarget() : NULL; |
253 if (NULL != renderTarget) { | 253 if (renderTarget) { |
254 add_genID_listener(key, bm.pixelRef()); | 254 add_genID_listener(key, bm.pixelRef()); |
255 SkAutoTUnref<GrEffect> yuvToRgbEffect(GrYUVtoRGBEffect::Create( | 255 SkAutoTUnref<GrEffect> yuvToRgbEffect(GrYUVtoRGBEffect::Create( |
256 yuvTextures[0].texture(), yuvTextures[1].texture(), yuvTextures[2].t
exture())); | 256 yuvTextures[0].texture(), yuvTextures[1].texture(), yuvTextures[2].t
exture())); |
257 GrPaint paint; | 257 GrPaint paint; |
258 paint.addColorEffect(yuvToRgbEffect); | 258 paint.addColorEffect(yuvToRgbEffect); |
259 SkRect r = SkRect::MakeWH(SkIntToScalar(yuvSizes[0].fWidth), | 259 SkRect r = SkRect::MakeWH(SkIntToScalar(yuvSizes[0].fWidth), |
260 SkIntToScalar(yuvSizes[0].fHeight)); | 260 SkIntToScalar(yuvSizes[0].fHeight)); |
261 GrContext::AutoRenderTarget autoRT(ctx, renderTarget); | 261 GrContext::AutoRenderTarget autoRT(ctx, renderTarget); |
262 GrContext::AutoMatrix am; | 262 GrContext::AutoMatrix am; |
263 am.setIdentity(ctx); | 263 am.setIdentity(ctx); |
(...skipping 30 matching lines...) Expand all Loading... |
294 // our compressed data will be trimmed, so pass width() for its | 294 // our compressed data will be trimmed, so pass width() for its |
295 // "rowBytes", since they are the same now. | 295 // "rowBytes", since they are the same now. |
296 | 296 |
297 if (cache) { | 297 if (cache) { |
298 GrCacheID cacheID; | 298 GrCacheID cacheID; |
299 generate_bitmap_cache_id(origBitmap, &cacheID); | 299 generate_bitmap_cache_id(origBitmap, &cacheID); |
300 | 300 |
301 GrResourceKey key; | 301 GrResourceKey key; |
302 GrTexture* result = ctx->createTexture(params, desc, cacheID, | 302 GrTexture* result = ctx->createTexture(params, desc, cacheID, |
303 storage.get(), bitmap->wi
dth(), &key); | 303 storage.get(), bitmap->wi
dth(), &key); |
304 if (NULL != result) { | 304 if (result) { |
305 add_genID_listener(key, origBitmap.pixelRef()); | 305 add_genID_listener(key, origBitmap.pixelRef()); |
306 } | 306 } |
307 return result; | 307 return result; |
308 } else { | 308 } else { |
309 GrTexture* result = ctx->lockAndRefScratchTexture(desc, | 309 GrTexture* result = ctx->lockAndRefScratchTexture(desc, |
310 GrContext::kExact_Sc
ratchTexMatch); | 310 GrContext::kExact_Sc
ratchTexMatch); |
311 result->writePixels(0, 0, bitmap->width(), | 311 result->writePixels(0, 0, bitmap->width(), |
312 bitmap->height(), desc.fConfig, | 312 bitmap->height(), desc.fConfig, |
313 storage.get()); | 313 storage.get()); |
314 return result; | 314 return result; |
(...skipping 14 matching lines...) Expand all Loading... |
329 cache | 329 cache |
330 // Make sure that the underlying device supports ETC1 textures before we
go ahead | 330 // Make sure that the underlying device supports ETC1 textures before we
go ahead |
331 // and check the data. | 331 // and check the data. |
332 && ctx->getGpu()->caps()->isConfigTexturable(kETC1_GrPixelConfig) | 332 && ctx->getGpu()->caps()->isConfigTexturable(kETC1_GrPixelConfig) |
333 // If the bitmap had compressed data and was then uncompressed, it'll st
ill return | 333 // If the bitmap had compressed data and was then uncompressed, it'll st
ill return |
334 // compressed data on 'refEncodedData' and upload it. Probably not good,
since if | 334 // compressed data on 'refEncodedData' and upload it. Probably not good,
since if |
335 // the bitmap has available pixels, then they might not be what the deco
mpressed | 335 // the bitmap has available pixels, then they might not be what the deco
mpressed |
336 // data is. | 336 // data is. |
337 && !(bitmap->readyToDraw())) { | 337 && !(bitmap->readyToDraw())) { |
338 GrTexture *texture = load_etc1_texture(ctx, params, *bitmap, desc); | 338 GrTexture *texture = load_etc1_texture(ctx, params, *bitmap, desc); |
339 if (NULL != texture) { | 339 if (texture) { |
340 return texture; | 340 return texture; |
341 } | 341 } |
342 } | 342 } |
343 #endif // SK_IGNORE_ETC1_SUPPORT | 343 #endif // SK_IGNORE_ETC1_SUPPORT |
344 | 344 |
345 else { | 345 else { |
346 GrTexture *texture = load_yuv_texture(ctx, params, *bitmap, desc); | 346 GrTexture *texture = load_yuv_texture(ctx, params, *bitmap, desc); |
347 if (NULL != texture) { | 347 if (texture) { |
348 return texture; | 348 return texture; |
349 } | 349 } |
350 } | 350 } |
351 SkAutoLockPixels alp(*bitmap); | 351 SkAutoLockPixels alp(*bitmap); |
352 if (!bitmap->readyToDraw()) { | 352 if (!bitmap->readyToDraw()) { |
353 return NULL; | 353 return NULL; |
354 } | 354 } |
355 if (cache) { | 355 if (cache) { |
356 // This texture is likely to be used again so leave it in the cache | 356 // This texture is likely to be used again so leave it in the cache |
357 GrCacheID cacheID; | 357 GrCacheID cacheID; |
358 generate_bitmap_cache_id(origBitmap, &cacheID); | 358 generate_bitmap_cache_id(origBitmap, &cacheID); |
359 | 359 |
360 GrResourceKey key; | 360 GrResourceKey key; |
361 GrTexture* result = ctx->createTexture(params, desc, cacheID, | 361 GrTexture* result = ctx->createTexture(params, desc, cacheID, |
362 bitmap->getPixels(), bitmap->rowB
ytes(), &key); | 362 bitmap->getPixels(), bitmap->rowB
ytes(), &key); |
363 if (NULL != result) { | 363 if (result) { |
364 add_genID_listener(key, origBitmap.pixelRef()); | 364 add_genID_listener(key, origBitmap.pixelRef()); |
365 } | 365 } |
366 return result; | 366 return result; |
367 } else { | 367 } else { |
368 // This texture is unlikely to be used again (in its present form) so | 368 // This texture is unlikely to be used again (in its present form) so |
369 // just use a scratch texture. This will remove the texture from the | 369 // just use a scratch texture. This will remove the texture from the |
370 // cache so no one else can find it. Additionally, once unlocked, the | 370 // cache so no one else can find it. Additionally, once unlocked, the |
371 // scratch texture will go to the end of the list for purging so will | 371 // scratch texture will go to the end of the list for purging so will |
372 // likely be available for this volatile bitmap the next time around. | 372 // likely be available for this volatile bitmap the next time around. |
373 GrTexture* result = ctx->lockAndRefScratchTexture(desc, GrContext::kExac
t_ScratchTexMatch); | 373 GrTexture* result = ctx->lockAndRefScratchTexture(desc, GrContext::kExac
t_ScratchTexMatch); |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
413 result = sk_gr_create_bitmap_texture(ctx, cache, params, bitmap); | 413 result = sk_gr_create_bitmap_texture(ctx, cache, params, bitmap); |
414 } | 414 } |
415 if (NULL == result) { | 415 if (NULL == result) { |
416 GrPrintf("---- failed to create texture for cache [%d %d]\n", | 416 GrPrintf("---- failed to create texture for cache [%d %d]\n", |
417 bitmap.width(), bitmap.height()); | 417 bitmap.width(), bitmap.height()); |
418 } | 418 } |
419 return result; | 419 return result; |
420 } | 420 } |
421 | 421 |
422 void GrUnlockAndUnrefCachedBitmapTexture(GrTexture* texture) { | 422 void GrUnlockAndUnrefCachedBitmapTexture(GrTexture* texture) { |
423 SkASSERT(NULL != texture->getContext()); | 423 SkASSERT(texture->getContext()); |
424 | 424 |
425 texture->getContext()->unlockScratchTexture(texture); | 425 texture->getContext()->unlockScratchTexture(texture); |
426 texture->unref(); | 426 texture->unref(); |
427 } | 427 } |
428 | 428 |
429 /////////////////////////////////////////////////////////////////////////////// | 429 /////////////////////////////////////////////////////////////////////////////// |
430 | 430 |
431 // alphatype is ignore for now, but if GrPixelConfig is expanded to encompass | 431 // alphatype is ignore for now, but if GrPixelConfig is expanded to encompass |
432 // alpha info, that will be considered. | 432 // alpha info, that will be considered. |
433 GrPixelConfig SkImageInfo2GrPixelConfig(SkColorType ct, SkAlphaType) { | 433 GrPixelConfig SkImageInfo2GrPixelConfig(SkColorType ct, SkAlphaType) { |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
488 | 488 |
489 grPaint->setDither(skPaint.isDither()); | 489 grPaint->setDither(skPaint.isDither()); |
490 grPaint->setAntiAlias(skPaint.isAntiAlias()); | 490 grPaint->setAntiAlias(skPaint.isAntiAlias()); |
491 | 491 |
492 SkXfermode::Coeff sm; | 492 SkXfermode::Coeff sm; |
493 SkXfermode::Coeff dm; | 493 SkXfermode::Coeff dm; |
494 | 494 |
495 SkXfermode* mode = skPaint.getXfermode(); | 495 SkXfermode* mode = skPaint.getXfermode(); |
496 GrEffect* xferEffect = NULL; | 496 GrEffect* xferEffect = NULL; |
497 if (SkXfermode::AsNewEffectOrCoeff(mode, &xferEffect, &sm, &dm)) { | 497 if (SkXfermode::AsNewEffectOrCoeff(mode, &xferEffect, &sm, &dm)) { |
498 if (NULL != xferEffect) { | 498 if (xferEffect) { |
499 grPaint->addColorEffect(xferEffect)->unref(); | 499 grPaint->addColorEffect(xferEffect)->unref(); |
500 sm = SkXfermode::kOne_Coeff; | 500 sm = SkXfermode::kOne_Coeff; |
501 dm = SkXfermode::kZero_Coeff; | 501 dm = SkXfermode::kZero_Coeff; |
502 } | 502 } |
503 } else { | 503 } else { |
504 //SkDEBUGCODE(SkDebugf("Unsupported xfer mode.\n");) | 504 //SkDEBUGCODE(SkDebugf("Unsupported xfer mode.\n");) |
505 // Fall back to src-over | 505 // Fall back to src-over |
506 sm = SkXfermode::kOne_Coeff; | 506 sm = SkXfermode::kOne_Coeff; |
507 dm = SkXfermode::kISA_Coeff; | 507 dm = SkXfermode::kISA_Coeff; |
508 } | 508 } |
509 grPaint->setBlendFunc(sk_blend_to_grblend(sm), sk_blend_to_grblend(dm)); | 509 grPaint->setBlendFunc(sk_blend_to_grblend(sm), sk_blend_to_grblend(dm)); |
510 | 510 |
511 //set the color of the paint to the one of the parameter | 511 //set the color of the paint to the one of the parameter |
512 grPaint->setColor(paintColor); | 512 grPaint->setColor(paintColor); |
513 | 513 |
514 SkColorFilter* colorFilter = skPaint.getColorFilter(); | 514 SkColorFilter* colorFilter = skPaint.getColorFilter(); |
515 if (NULL != colorFilter) { | 515 if (colorFilter) { |
516 // if the source color is a constant then apply the filter here once rat
her than per pixel | 516 // if the source color is a constant then apply the filter here once rat
her than per pixel |
517 // in a shader. | 517 // in a shader. |
518 if (constantColor) { | 518 if (constantColor) { |
519 SkColor filtered = colorFilter->filterColor(skPaint.getColor()); | 519 SkColor filtered = colorFilter->filterColor(skPaint.getColor()); |
520 grPaint->setColor(SkColor2GrColor(filtered)); | 520 grPaint->setColor(SkColor2GrColor(filtered)); |
521 } else { | 521 } else { |
522 SkAutoTUnref<GrEffect> effect(colorFilter->asNewEffect(context)); | 522 SkAutoTUnref<GrEffect> effect(colorFilter->asNewEffect(context)); |
523 if (NULL != effect.get()) { | 523 if (effect.get()) { |
524 grPaint->addColorEffect(effect); | 524 grPaint->addColorEffect(effect); |
525 } | 525 } |
526 } | 526 } |
527 } | 527 } |
528 | 528 |
529 #ifndef SK_IGNORE_GPU_DITHER | 529 #ifndef SK_IGNORE_GPU_DITHER |
530 // If the dither flag is set, then we need to see if the underlying context | 530 // If the dither flag is set, then we need to see if the underlying context |
531 // supports it. If not, then install a dither effect. | 531 // supports it. If not, then install a dither effect. |
532 if (skPaint.isDither() && grPaint->numColorStages() > 0) { | 532 if (skPaint.isDither() && grPaint->numColorStages() > 0) { |
533 // What are we rendering into? | 533 // What are we rendering into? |
534 const GrRenderTarget *target = context->getRenderTarget(); | 534 const GrRenderTarget *target = context->getRenderTarget(); |
535 SkASSERT(NULL != target); | 535 SkASSERT(target); |
536 | 536 |
537 // Suspect the dithering flag has no effect on these configs, otherwise | 537 // Suspect the dithering flag has no effect on these configs, otherwise |
538 // fall back on setting the appropriate state. | 538 // fall back on setting the appropriate state. |
539 if (target->config() == kRGBA_8888_GrPixelConfig || | 539 if (target->config() == kRGBA_8888_GrPixelConfig || |
540 target->config() == kBGRA_8888_GrPixelConfig) { | 540 target->config() == kBGRA_8888_GrPixelConfig) { |
541 // The dither flag is set and the target is likely | 541 // The dither flag is set and the target is likely |
542 // not going to be dithered by the GPU. | 542 // not going to be dithered by the GPU. |
543 SkAutoTUnref<GrEffect> effect(GrDitherEffect::Create()); | 543 SkAutoTUnref<GrEffect> effect(GrDitherEffect::Create()); |
544 if (NULL != effect.get()) { | 544 if (effect.get()) { |
545 grPaint->addColorEffect(effect); | 545 grPaint->addColorEffect(effect); |
546 grPaint->setDither(false); | 546 grPaint->setDither(false); |
547 } | 547 } |
548 } | 548 } |
549 } | 549 } |
550 #endif | 550 #endif |
551 } | 551 } |
552 | 552 |
553 /** | 553 /** |
554 * Unlike GrContext::AutoMatrix, this doesn't require setting a new matrix. GrCo
ntext::AutoMatrix | 554 * Unlike GrContext::AutoMatrix, this doesn't require setting a new matrix. GrCo
ntext::AutoMatrix |
555 * likes to set the new matrix in its constructor because it is usually necessar
y to simulataneously | 555 * likes to set the new matrix in its constructor because it is usually necessar
y to simulataneously |
556 * update a GrPaint. This AutoMatrix is used while initially setting up GrPaint,
however. | 556 * update a GrPaint. This AutoMatrix is used while initially setting up GrPaint,
however. |
557 */ | 557 */ |
558 class AutoMatrix { | 558 class AutoMatrix { |
559 public: | 559 public: |
560 AutoMatrix(GrContext* context) { | 560 AutoMatrix(GrContext* context) { |
561 fMatrix = context->getMatrix(); | 561 fMatrix = context->getMatrix(); |
562 fContext = context; | 562 fContext = context; |
563 } | 563 } |
564 ~AutoMatrix() { | 564 ~AutoMatrix() { |
565 SkASSERT(NULL != fContext); | 565 SkASSERT(fContext); |
566 fContext->setMatrix(fMatrix); | 566 fContext->setMatrix(fMatrix); |
567 } | 567 } |
568 private: | 568 private: |
569 GrContext* fContext; | 569 GrContext* fContext; |
570 SkMatrix fMatrix; | 570 SkMatrix fMatrix; |
571 }; | 571 }; |
572 | 572 |
573 void SkPaint2GrPaintShader(GrContext* context, const SkPaint& skPaint, | 573 void SkPaint2GrPaintShader(GrContext* context, const SkPaint& skPaint, |
574 bool constantColor, GrPaint* grPaint) { | 574 bool constantColor, GrPaint* grPaint) { |
575 SkShader* shader = skPaint.getShader(); | 575 SkShader* shader = skPaint.getShader(); |
(...skipping 12 matching lines...) Expand all Loading... |
588 // SkShader::asNewEffect() may do offscreen rendering. Save off the curr
ent RT, clip, and | 588 // SkShader::asNewEffect() may do offscreen rendering. Save off the curr
ent RT, clip, and |
589 // matrix. We don't reset the matrix on the context because SkShader::as
NewEffect may use | 589 // matrix. We don't reset the matrix on the context because SkShader::as
NewEffect may use |
590 // GrContext::getMatrix() to know the transformation from local coords t
o device space. | 590 // GrContext::getMatrix() to know the transformation from local coords t
o device space. |
591 GrContext::AutoRenderTarget art(context, NULL); | 591 GrContext::AutoRenderTarget art(context, NULL); |
592 GrContext::AutoClip ac(context, GrContext::AutoClip::kWideOpen_InitialCl
ip); | 592 GrContext::AutoClip ac(context, GrContext::AutoClip::kWideOpen_InitialCl
ip); |
593 AutoMatrix am(context); | 593 AutoMatrix am(context); |
594 | 594 |
595 // Allow the shader to modify paintColor and also create an effect to be
installed as | 595 // Allow the shader to modify paintColor and also create an effect to be
installed as |
596 // the first color effect on the GrPaint. | 596 // the first color effect on the GrPaint. |
597 GrEffect* effect = NULL; | 597 GrEffect* effect = NULL; |
598 if (shader->asNewEffect(context, skPaint, NULL, &paintColor, &effect) &&
NULL != effect) { | 598 if (shader->asNewEffect(context, skPaint, NULL, &paintColor, &effect) &&
effect) { |
599 grPaint->addColorEffect(effect)->unref(); | 599 grPaint->addColorEffect(effect)->unref(); |
600 constantColor = false; | 600 constantColor = false; |
601 } | 601 } |
602 } | 602 } |
603 | 603 |
604 // The grcolor is automatically set when calling asneweffect. | 604 // The grcolor is automatically set when calling asneweffect. |
605 // If the shader can be seen as an effect it returns true and adds its effec
t to the grpaint. | 605 // If the shader can be seen as an effect it returns true and adds its effec
t to the grpaint. |
606 SkPaint2GrPaintNoShader(context, skPaint, paintColor, constantColor, grPaint
); | 606 SkPaint2GrPaintNoShader(context, skPaint, paintColor, constantColor, grPaint
); |
607 } | 607 } |
OLD | NEW |